http://www.codeguru.pl/articleprint.aspx



Podobne dokumenty
Programowanie obiektowe

Testowanie II. Celem zajęć jest zapoznanie studentów z oceną jakości testów przy wykorzystaniu metryk pokrycia kodu testami (ang. code coverage).

Prosta książka telefoniczna z wykorzystaniem zapisu do pliku

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej.

Tak przygotowane pliki należy umieścić w głównym folderze naszego programu. Klub IKS

1 Podstawy c++ w pigułce.

PLAN WYNIKOWY PROGRAMOWANIE APLIKACJI INTERNETOWYCH. KL III TI 4 godziny tygodniowo (4x30 tygodni =120 godzin ),

- Narzędzie Windows Forms. - Przykładowe aplikacje. Wyższa Metody Szkoła programowania Techniczno Ekonomiczna 1 w Świdnicy

Testujemy dedykowanymi zasobami (ang. agile testers)

Wyjątki. Streszczenie Celem wykładu jest omówienie tematyki wyjątków w Javie. Czas wykładu 45 minut.

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

Jarosław Kuchta Dokumentacja i Jakość Oprogramowania. Wymagania jakości w Agile Programming

2. W oknie dialogowym Choose Toolbox Items w zakładce.net Framework Components naciskamy przycisk Browse...

Lista, Stos, Kolejka, Tablica Asocjacyjna

Metodyki zwinne wytwarzania oprogramowania

Podstawy języka C++ Maciej Trzebiński. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. Praktyki studenckie na LHC IVedycja,2016r.

Przykładowa dostępna aplikacja w Visual Studio - krok po kroku

Klasy abstrakcyjne i interfejsy

Leszek Stasiak Zastosowanie technologii LINQ w

Laboratorium z przedmiotu: Inżynieria Oprogramowania INEK Instrukcja 7

Języki i techniki programowania Ćwiczenia 4 Wzorce

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 1

PLAN WYNIKOWY PROGRAMOWANIE APLIKACJI INTERNETOWYCH. KL IV TI 6 godziny tygodniowo (6x15 tygodni =90 godzin ),

Programowanie obiektowe. Literatura: Autor: dr inŝ. Zofia Kruczkiewicz

Programowanie obiektowe

Testowanie II. Cel zajęć. Pokrycie kodu

Klasy abstrakcyjne, interfejsy i polimorfizm

Wprowadzenie do Behaviordriven

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Wykład 12. Programowanie serwera MS SQL 2005 w C#

Programowanie obiektowe i zdarzeniowe wykład 4 Kompozycja, kolekcje, wiązanie danych

Szablony funkcji i klas (templates)

Programowanie poprzez testy z wykorzystaniem JUnit

Programowanie Zespołowe

Być może jesteś doświadczonym programistą, biegle programujesz w Javie,

C++ Przeładowanie operatorów i wzorce w klasach

Algorytm. a programowanie -

Aplikacje w środowisku Java

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

5.4. Tworzymy formularze

Programowanie obiektowe

Builder (budowniczy) Cel: Przykład:

System kontroli wersji, system zarządzania kodem źródłowym

Programowanie Obiektowe Ćwiczenie 4

Laboratorium Informatyka (I) AiR Ćwiczenia z debugowania

Ćwiczenie 1. Przygotowanie środowiska JAVA

Języki i paradygmaty programowania - 1

Wprowadzenie do projektu QualitySpy

Testowanie oprogramowania

Programowanie obiektowe i zdarzeniowe

Programowanie obiektowe

Języki i paradygmaty programowania doc. dr inż. Tadeusz Jeleniewski

Spis treści. Rozdział 1. Aplikacje konsoli w stylu ANSI C i podstawowe operacje w Visual C

Programowanie obiektowe zastosowanie języka Java SE

Zapisywanie algorytmów w języku programowania

1 Podstawy c++ w pigułce.

Testowanie I. Celem zajęć jest zapoznanie studentów z podstawami testowania ze szczególnym uwzględnieniem testowania jednostkowego.

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost;

Klasy i obiekty cz II

lekcja 8a Gry komputerowe MasterMind

Programowanie obiektowe

Dziedziczenie. Streszczenie Celem wykładu jest omówienie tematyki dziedziczenia klas. Czas wykładu 45 minut.

Programowanie w środowiskach graficznych. Wykład 3 Język C#

Czym są właściwości. Poprawne projektowanie klas

Programowanie obiektowe

Typy, klasy typów, składnie w funkcji

Politechnika Gdańska Katedra Optoelektroniki i Systemów Elektronicznych

Dzisiejszy wykład. Wzorce projektowe. Visitor Client-Server Factory Singleton

Podstawy Programowania 2

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

Java: kilka brakujących szczegółów i uniwersalna nadklasa Object

TEMAT : KLASY DZIEDZICZENIE

Cel: Przypisujemy przyciskom określone funkcje panel górny (Panel1)

Słowem wstępu. Część rodziny języków XSL. Standard: W3C XSLT razem XPath 1.0 XSLT Trwają prace nad XSLT 3.0

GNU GProf i GCov. przygotował: Krzysztof Jurczuk Politechnika Białostocka Wydział Informatyki Katedra Oprogramowania ul. Wiejska 45A Białystok

Podstawy programowania obiektowego

Laboratorium z przedmiotu Programowanie obiektowe - zestaw 04

Programowanie obiektowe

WYKORZYSTANIE JĘZYKA GROOVY W TESTACH JEDNOSTKOWYCH, INTEGRACYJNYCH I AUTOMATYCZNYCH. Mirosław Gołda, Programista Java

Instrukcja laboratoryjna cz.3

Laboratorium 1 - Programowanie proceduralne i obiektowe

Obiektowy PHP. Czym jest obiekt? Definicja klasy. Składowe klasy pola i metody

dr inż. Piotr Czapiewski Tworzenie aplikacji w języku Java Laboratorium 1

Programowanie obiektowe

PARADYGMATY PROGRAMOWANIA Wykład 4

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Wskaźnik może wskazywać na jakąś zmienną, strukturę, tablicę a nawet funkcję. Oto podstawowe operatory niezbędne do operowania wskaźnikami:

Cwiczenie nr 1 Pierwszy program w języku C na mikrokontroler AVR

Zad. 5: Układ równań liniowych liczb zespolonych

Lista dwukierunkowa - przykład implementacji destruktorów

Acceptance Test Driven Development wspierane przez narzędzie ROBOT Framework. Edyta Tomalik Grzegorz Ziemiecki

Logger. Następnie w klasie Bootstrapper muimy zarejestrować nasz nowy logger:

Celem tego projektu jest stworzenie

Podstawy programowania obiektowego

Programowanie obiektowe

Wyjątki (exceptions)

Rozdział 4 KLASY, OBIEKTY, METODY

WSNHiD, Programowanie 2 Lab. 2 Język Java struktura programu, dziedziczenie, abstrakcja, polimorfizm, interfejsy

Maciej Oleksy Zenon Matuszyk

Laboratorium z przedmiotu: Inżynieria Oprogramowania INEK Instrukcja 6

Transkrypt:

Strona 1 z 8 Drukuj Zamknij Testowanie modułów oraz tworzenie metodą testy-najpierw 2003-10-15 08:00:44 Użytkownik systemowy - Administratorzy, Portal.NET Jeśli czytelnik jest jednym z nielicznych zapewne ludzi, którzy przeczytali moją biografię na końcu, może już wie, że zanim stałem się kierownikiem programowym, byłem głównym testerem dla kompilatora C#, a jeszcze wcześniej dla kompilatora C++. To czyni mnie bardziej niż nieco zainteresowanym analizowaniem i, kiedy to tylko możliwe, unikaniem błędów. Jednym ze sposobów na zredukowanie liczby błędów trafiających się w tworzonym oprogramowaniu jest zatrudnianie profesjonalnego zespołu testowego, którego zadaniem są agresywne próby spowodowania awarii tego programu. Niestety, tam gdzie jest taki zespół, pojawia się tendencja nawet u doświadczonych programistów by poświęcać mniejszą ilość czasu na zwiększanie niezawodności ich kodu. Popularną w świecie oprogramowania tezą jest, że programiści nie powinni testować własnego kodu. Opiera się to na teorii, że programiści wiedzą tak dużo o swoim własnym kodzie, że będą mieli z góry wyrobione opinie, jak należy go właściwie przetestować. Jest w tym więcej niż tylko ziarno prawdy, ale teoria ta pomija jedną ważną kwestię: jeśli programiści nie będą testować własnego kodu, skąd będą wiedzieli, czy działa tak, jak powinien działać? Prosta odpowiedź brzmi: nie będą wiedzieli. A programista piszący kod, który nie działa lub który działa tylko w pewnych sytuacjach, to duży problem. Zamiast sprawdzić, czy ich kod działa we wszystkich przypadkach, zwykle testują ich tylko kilka. Wykrywanie błędów Istnieje wiele sytuacji, w których wykrywa się błędy: 1. przez programistę podczas pisania kodu pierwszy raz, 2. przez programistę podczas prób doprowadzenia kodu do działania, 3. przez innego programistę lub testera w zespole. 4. w ramach większego testu produktu, 5. przez użytkownika końcowego. Jeśli błąd został wykryty w sytuacji 1), jest łatwy i tani do usunięcia. W miarę przesuwania się w dół listy staje się to coraz kosztowniejsze, a naprawienie błędu odkrytego przez użytkownika końcowego może kosztować 100 lub 1000 razy więcej. Nie wspominając już o fakcie, że użytkownik będzie się borykał z tym błędem aż do wydania kolejnej wersji programu. Najlepiej by było, gdyby wszystkie błędy były wykrywane już podczas pisania kodu przez programistę. W tym celu powinien mieć on testy, które można uruchamiać podczas pisania kodu. Istnieje ciekawa metodologia, która właśnie temu służy. Tworzenie metodą testy-najpierw Przy tworzeniu kodu z zastosowaniem metody testy-najpierw pisze się testy przed napisaniem kodu. Gdy wszystkie testy działają, wiadomo, że kod też działa poprawnie, a w miarę dodawania nowych funkcji te testy również sprawdzają, czy nic nie zostało zepsute. Pojęcie to powstało we wczesnych latach 90. XX wieku w świecie Smalltalk, gdy Kent Beck napisał SmalltalkUnit. Przez następne lata narzędzia do testowania modułów napisano dla większości środowisk; między innymi powstało bardzo dobre narzędzie dla Infrastruktury.NET, znane jako nunit. Przykład Aby wyjaśnić sposób działania tej metody tworzenia, napiszę klasę IntegerList. Jest to odmiana klasy ArrayList przechowującej liczby całkowite w postaci rodzimej, dzięki czemu nie ma narzutu spowodowanego pakowaniem (ang. boxing) oraz rozpakowywaniem (ang. unboxing). Pierwszym moim krokiem będzie stworzenie projektu konsoli i dodanie do niego pliku źródłowego IntegerList.cs source. Aby podłączyć infrastrukturę nunit, muszę dodać odwołania do infrastruktury nunit. W moim systemie znajdują się one w d:\program files\nunit v2.0\bin. Kolejną rzeczą będzie zastanowienie się nad tym, jak tę klasę będziemy testować. Przypomina to decydowanie,

Strona 2 z 8 jakie możliwości powinna mieć dana klasa, ale skupia się na konkretnych jej użyciach (dodaj wartość 1 do listy, a następnie sprawdź, czy się to udało), a nie na samych możliwościach (dodaj element do listy). Zanim więc stworzymy klasę, najpierw układamy listę testów, które wobec niej wykonamy: 1. Test sprawdzający, czy ta klasa może zostać skonstruowana. 2. Dodanie dwóch liczb całkowitych do listy i upewnienie się, że liczba elementów jest prawidłowa oraz że same elementy są prawidłowe. 3. Test jak w punkcie 2, ale z większą liczbą elementów. 4. Konwersja listy na łańcuch. 5. Wyliczenie listy za pomocą foreach. Ten przykład jest nieco nietypowy w tym sensie, że już na samym początku wiemy, co ta klasa powinna robić. Większość klas jest budowanych krok po kroku i w miarę jak klasa rośnie, powinny być dodawane także testy. Teraz możemy już zacząć pracę. Utworzę plik nowej klasy C#, który nazwę IntegerListTest.cs i który będzie zawierał wszystkie moje testy. Oto plik z pierwszym testem: using System; using System.Collections; using NUnit.Framework; namespace IntegerList /// <streszczenie> /// Streszczony opis IntegerClassTest. /// </streszczenie> [TestFixture] public class IntegerClassTest public void ListCreation() IntegerList list = new IntegerList(); Assertion.AssertNotNull(list); Atrybut[TestFixture] oznacza tę klasę jako klasę testową, zaś atrybut oznacza ListCreation() jako metodę testową. W tej metodzie tworzymy listę, a następnie sprawdzamy, czy obiekt został utworzony, za pomocą klasy Assertion. Uruchamiamy tester GUI nunit, otwieramy plik wykonywalny, a następnie wydajemy polecenie uruchomienia testów. W wyniku uzyskujemy widok z Rysunku 1.

Strona 3 z 8 Rysunek 1. GUI nunit wyświetla wyniki testów Na rysunku widać, że klasa przeszła wszystkie nasze testy. Teraz będę chciał dodać jakieś prawdziwe funkcje. Pierwszą rzeczą, którą chcę być w stanie zrobić, jest dodanie do listy liczby całkowitej. Oto ten test: public void TestSimpleAdd() IntegerList list = new IntegerList(); list.add(5); list.add(10); Assertion.AssertEquals(2, list.count); Assertion.AssertEquals(5, list[0]); Assertion.AssertEquals(10, list[1]); W tym teście postanowiłem przetestować kilka rzeczy na raz: Czy lista utrzymuje prawidłową wartość właściwości Count. Czy lista może przechowywać dwa elementy. Niektórzy orędownicy tworzenia kierowanego testami postulują, żeby testy były tak rozdrobnione, jak to tylko możliwe, ale dla mnie dziwne by było testowanie liczby elementów bez testowania samych elementów, więc takie właśnie rozwiązanie wybrałem. Nie można tego kodu skompilować, ponieważ w klasie IntegerList nie ma metod. Dodaję więc do niej następujące puste metody, dzięki którym kompilacja się powiedzie: public int Count return -1;

Strona 4 z 8 public void Add(int value) public int this[int index] return -1; Powracam do testów, które i tym razem wyświetlają się na czerwono co sygnalizuje niepowodzenie testów. To dobrze, ponieważ to oznacza, że moje testy rzeczywiście testują coś, co w chwili obecnej jeszcze nie działa. Teraz mogę wykonać implementację zrobię coś prostego, ale nieefektywnego: public int Count return elements.length; public void Add(int value) int newindex; if (elements!= null) int[] newelements = new int[elements.length + 1]; for (int index = 0; index < elements.length; index++) newelements[index] = elements[index]; newindex = elements.length; elements = newelements; else elements = new int[1]; newindex = 0; elements[newindex] = value;

Strona 5 z 8 public int this[int index] return elements[index]; Mam już zrobioną małą część mojej klasy oraz testy zapewniające, że działa ona poprawnie, ale przetestowałem ją tylko dla małej liczby elementów. Napiszę więc test sprawdzający ją dla 1000 elementów: public void TestOneThousandItems() list = new IntegerList(); for (int i = 0; i < 1000; i++) list.add(i); Assertion.AssertEquals(1000, list.count); for (int i = 0; i < 1000; i++) Assertion.AssertEquals(i, list[i]); Ten test został zakończony pomyślnie, więc nie muszę już dokonywać żadnych zmian. Dodawanie metody ToString() Dodam teraz kod testujący, czy ToString() działa poprawnie: public void TestToString() IntegerList list = new IntegerList(); list.add(5); list.add(10); string t = list.tostring(); Assertion.AssertEquals("5, 10", t.tostring()); To jednak zawodzi. Poniżej znajduje się kod, który sprawia, że klasa przechodzi test: public override string ToString() string[] items = new string[elements.length];

Strona 6 z 8 for (int index = 0; index < elements.length; index++) items[index] = elements[index].tostring(); return String.Join(", ", items); Włączanie Foreach Wielu użytkowników zapewne będzie chciało wykonać foreach dla mojej listy. W tym celu muszę dla tej klasy zaimplementować IEnumerable oraz zdefiniować osobną klasę implementującą IEnumerable. Najpierw więc test: public void TestForeach() IntegerList list = new IntegerList(); list.add(5); list.add(10); list.add(15); list.add(20); ArrayList items = new ArrayList(); foreach (int value in list) items.add(value); Assertion.AssertEquals("Liczba", 4, items.count); Assertion.AssertEquals("indeks 0", 5, items[0]); Assertion.AssertEquals("indeks 1", 10, items[1]); Assertion.AssertEquals("indeks 2", 15, items[2]); Assertion.AssertEquals("indeks 3", 20, items[3]); Zaimplementowałem także Ienumerable w IntegerList: public IEnumerator GetEnumerator() return null; To powoduje wystąpienie wyjątku po uruchomieniu testu. Aby zaimplementować to poprawnie, zastosuję w charakterze mechanizmu wyliczeniowego klasę zagnieżdżoną. class IntegerListEnumerator: IEnumerator IntegerList list; int index = -1;

Strona 7 z 8 public IntegerListEnumerator(IntegerList list) this.list = list; public bool MoveNext() index++; if (index == list.count) return(false); else return(true); public object Current return(list[index]); public void Reset() index = -1; Klasa ta otrzymuje wskaźnik na obiekt IntegerList, a potem po prostu zwraca jej elementy. To włącza foreach dla naszej listy, ale niestety właściwość Current jest typu obiektowego, co oznacza, że każda wartość będzie opakowywana w celu przekazania jej z powrotem. Ten problem można rozwiązać przyjmując podejście oparte na wzorcach, które wygląda tak samo jak obecne, z tą tylko różnicą, że GetEnumerator() zwraca prawdziwą klasę (a nie IEnumerator), oraz właściwość Current w tej klasie jest typu int. Gdy jednak już to zrobię, chcę mieć pewność, że nadal mogę używać podejścia opartego na interfejsie w przypadku języków nieobsługujących wzorca. Skopiuję ostatni napisany test i zmodyfikuję foreach tak, aby było ono rzucane na interfejs: foreach (int value in (IEnumerable) list) Kilka zmian i lista działa już dla obu przypadków. Więcej szczegółów oraz więcej testów można znaleźć w kodzie przykładowym. Komentarze Napisanie kodu oraz tekstu do artykułu na ten miesiąc zajęło mi około godziny. Miłą stroną pisania testów jest przede wszystkim to, że ma się dobre pojęcie o tym, co trzeba dodać do klasy, żeby ten test przeszła, więc już pisanie kodu jest łatwiejsze. To podejście działa najlepiej w przypadku małych, przyrostowych testów. Zachęcam do wypróbowania tej metody na jakimś małym projekcie. Tworzenie metodą testy-najpierw jest częścią czegoś określanego mianem zwinnych metodologii (ang. Agile Methodologies). Więcej informacji o zwinnym tworzeniu można znaleźć pod adresem http://www.agilealliance.com/home. Spojrzenie w przyszłość

Strona 8 z 8 Bawiłem się ostatnio Microsoft DirectX 9, więc nie zdziwcie się, jeśli to będzie kolejny opisany temat. ERIC GUNNERSON Microsoft Corporation 1 marca 2003 roku Eric Gunnerson jest kierownikiem programowym zespołu Visual C#, byłym członkiem zespołu projektowego języka C# oraz autorem Wstęp do C# dla Programistów, Drugie Wydanie (A Programmer s Introduction to C#, 2nd Edition). Był programistą wystarczająco długo, by wiedzieć, jak wyglądają 8-calowe dyskietki i kiedyś potrafił zakładać taśmy jedną ręką. W wolnym czasie próbował ściąć drzewo za pomocą śledzia. Drukuj Zamknij