Podstawy testowania oprogramowania obiektowego 1)

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

Kurs programowania. Wstęp - wykład 0. Wojciech Macyna. 22 lutego 2016

Środowisko wspomagające testowanie oprogramowania obiektowego

Programowanie obiektowe - 1.

Kurs programowania. Wykład 12. Wojciech Macyna. 7 czerwca 2017

Podstawy Programowania Obiektowego

Testowanie oprogramowania. Testowanie oprogramowania 1/34

Modelowanie i Programowanie Obiektowe

Programowanie Obiektowe i C++

Programowanie współbieżne Wykład 8 Podstawy programowania obiektowego. Iwona Kochaoska

Programowanie Obiektowe i C++ Marcin Benke

Wykład 8. Testowanie w JEE 5.0 (1) Autor: Zofia Kruczkiewicz. Zofia Kruczkiewicz

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

Programowanie obiektowe

Problemy projektowania obiektowego. Czy podobne problemy można rozwiązywac w podobny sposób?

Porównanie metod i technik testowania oprogramowania. Damian Ryś Maja Wojnarowska

Testowanie oprogramowania. Piotr Ciskowski

Rysunek 1: Przykłady graficznej prezentacji klas.

Technologie obiektowe

Architektura Systemu. Architektura systemu umożliwia kontrolowanie iteracyjnego i przyrostowego procesu tworzenia systemu.

Wykład 7. Projektowanie kodu oprogramowania

Komputerowe Systemy Przemysłowe: Modelowanie - UML. Arkadiusz Banasik arkadiusz.banasik@polsl.pl

TEMAT : KLASY DZIEDZICZENIE

Jakość w procesie wytwarzania oprogramowania

Programowanie obiektowe

Kumulowanie się defektów jest możliwe - analiza i potwierdzenie tezy

Analiza i projektowanie obiektowe 2016/2017. Wykład 10: Tworzenie projektowego diagramu klas

Programowanie obiektowe

Paweł Kurzawa, Delfina Kongo

Myśl w języku Python! : nauka programowania / Allen B. Downey. Gliwice, cop Spis treści

ZARZĄDZANIU. Wykład VI. dr Jan Kazimirski

Język programowania. Andrzej Bobyk

Wprowadzenie do programowanie obiektowego w języku C++

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

SPOSOBY POMIARU KĄTÓW W PROGRAMIE AutoCAD

Klasy abstrakcyjne, interfejsy i polimorfizm

2. Klasy cz. 2 - Konstruktor kopiujący. Pola tworzone statycznie i dynamicznie - Funkcje zaprzyjaźnione - Składowe statyczne

UPEDU: Implementacja (ang. Implementation discipline)

> C++ dziedziczenie. Dane: Iwona Polak. Uniwersytet Śląski Instytut Informatyki

Wprowadzenie do systemów informacyjnych

Tworzenie przypadków testowych

PROJEKTOWANIE. kodowanie implementacja. PROJEKT most pomiędzy specyfikowaniem a kodowaniem

TECHNOLOGIE OBIEKTOWE. Wykład 3

Klasy abstrakcyjne i interfejsy

Dziedziczenie. Tomasz Borzyszkowski

Testowanie oprogramowania

Dziedziczenie jednobazowe, poliformizm

Programowanie obiektowe

Wzorce Strukturalne. Adapter: opis. Tomasz Borzyszkowski

12) Wadą modelu kaskadowego jest: Zagadnienia obowiązujące na egzaminie z inżynierii oprogramowania: 13) Wadą modelu opartego na prototypowaniu jest:

Typy klasowe (klasy) 1. Programowanie obiektowe. 2. Założenia paradygmatu obiektowego:

Modelowanie diagramów klas w języku UML. Łukasz Gorzel @stud.umk.pl 7 marca 2014

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np

Polimorfizm, metody wirtualne i klasy abstrakcyjne

Iteracyjno-rozwojowy proces tworzenia oprogramowania Wykład 3 część 1

INŻYNIERIA OROGRAMOWANIA TESTOWANIE JEDNOSTKOWE 2015/2016

Dziedziczenie. dr Jarosław Skaruz

Programowanie 2. Język C++. Wykład 3.

Podstawy Programowania Programowanie Obiektowe

C++ - dziedziczenie. C++ - dziedziczenie. C++ - dziedziczenie. C++ - dziedziczenie. C++ - dziedziczenie C++ - DZIEDZICZENIE.

Programowanie obiektowe

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Wykład 8: klasy cz. 4

Wzorce projektowe i refaktoryzacja

1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie?

Analiza i projektowanie oprogramowania. Analiza i projektowanie oprogramowania 1/32

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

Programowanie obiektowe. Wprowadzenie

Informatyka I. Dziedziczenie. Nadpisanie metod. Klasy abstrakcyjne. Wskaźnik this. Metody i pola statyczne. dr inż. Andrzej Czerepicki

Podstawy modelowania programów Kod przedmiotu

UML w Visual Studio. Michał Ciećwierz

Możliwe strategie tworzenia niezawodnego oprogramowania:

Programowanie w Javie 1 Wykład i Ćwiczenia 3 Programowanie obiektowe w Javie cd. Płock, 16 października 2013 r.

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

INŻYNIERIA OPROGRAMOWANIA TESTOWANIE SYSTEMOWE

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


Technologie i usługi internetowe cz. 2

Historia modeli programowania

Język JAVA podstawy. Wykład 4, część 1. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Jarosław Kuchta Jakość Systemów Informatycznych Jakość Oprogramowania. Pomiary w inżynierii oprogramowania

KARTA KURSU. Programowanie obiektowe

JAVA W SUPER EXPRESOWEJ PIGUŁCE

.NET Klasy, obiekty. ciąg dalszy

Wzorce projektowe. dr inż. Marcin Pietroo

Programowanie obiektowe 2 - opis przedmiotu

WYKŁAD. Jednostka prowadząca: Wydział Techniczny. Kierunek studiów: Elektronika i telekomunikacja. Nazwa przedmiotu: Język programowania C++

Paradygmaty programowania

problem w określonym kontekście siły istotę jego rozwiązania

Testy poziom po poziomie

Zawód tester, czyli na czym polega testowanie. Katarzyna Łabinska Justyna Sacha - Gawlik

INŻYNIERIA OPROGRAMOWANIA TESTOWANIE INTEGRACYJNE

PARADYGMATY PROGRAMOWANIA Wykład 4

Programowanie obiektowe

Rozdział 4 KLASY, OBIEKTY, METODY

Multi-wyszukiwarki. Mediacyjne Systemy Zapytań wprowadzenie. Architektury i technologie integracji danych Systemy Mediacyjne

Programowanie obiektowe

Testowanie według modelu (MBT) Stowarzyszenie Inżynierii Wymagań wymagania.org.pl

Wykład 1. Projektowanie efektywnych algorytmów przetwarzania danych w sieciowych systemach usług, rzeczy i multimediów.

Laboratorium nr 12. Temat: Struktury, klasy. Zakres laboratorium:

Transkrypt:

Podstawy testowania oprogramowania obiektowego 1) Ilona Bluemke Instytut Informatyki Politechniki Warszawskiej ul. Nowowiejska 15/19 00-665 Warszawa e-mail : ibl@ii.pw.edu.pl Streszczenie. W pracy przedstawiono podstawy testowania oprogramowania napisanego w językach obiektowych. Zwrócono uwagę na fakt, że testowanie programów obiektowych wymaga nie mniejszego wysiłku, niż testowanie programów napisanych w językach strukturalnych. Wzrost złożoności testowania wynika z podstawowych cech języków obiektowych takich jak hermetyzacja, dziedziczenie, polimorfizm czy dynamiczne wiązanie. Podano także pewne wskazówki praktyczne dotyczące testowania klas. Słowa kluczowe: inżynieria oprogramowania, programowanie obiektowe, jakość oprogramowania, testowanie obiektowe, aksjomaty testowania 1. Wprowadzenie Testowanie oprogramowania jest jednym ze środków pozwalających zapewnić wysoką jakość oprogramowania. Celem testowania jest wykrycie jak największej liczby błędów wykonania programu przy minimalnym koszcie. Właściwy test powinien wykrywać błędne zachowanie programu niepoprawne wyniki, czy zachowanie niezgodnie z oczekiwaniami użytkownika. Koszty testowania to 40% do 80 % kosztów produkcji oprogramowania stąd redukcja tych kosztów i poprawa jakości testowania są ważnym problemem od lat przyciągającym uwagę informatyków. W ostatnim trzydziestoleciu lat zaproponowano wiele strategii testowania i metod zwiększania niezawodności oprogramowania np. przeglądy kodu, testowanie ścieżek, testowanie struktur sterujących, analiza wartości brzegowych czy symboliczne wykonywanie. Metody te zostały zaproponowane dla oprogramowania strukturalnego i większość z nich nie nadaje się zbyt dobrze do testowania oprogramowania obiektowego. Od końca lat osiemdziesiątych prowadzone są prace nad metodami testowania dostosowanymi do testowania programów pisanych w językach obiektowych. Poniżej przedstawiono podstawy testowania oprogramowania obiektowego. W celu osiągnięcia akceptowalnego poziomu niezawodności konieczne jest testowanie ukierunkowane na wyszukiwanie defektów ( defect testing ) w programie [9]. Zaproponowano następujące podejścia do testowania : 1) Praca została wykonana w ramach grantu JM Rektora PW nr 503/G/1032/1570/200.

1. Funkcjonalne (black box) testy są wyprowadzane ze specyfikacji oprogramowania. Program jest traktowany jako czarna skrzynka, której zachowanie może być określone na podstawie wejść i odpowiadających im wyjść. Celem testowania jest określenie, czy program spełnia funkcjonalne i niefunkcjonalne (np. wydajnościowe) wymagania. 2. Strukturalne (white box) testy są wyprowadzane na podstawie znajomości struktury programu. Cechą charakterystyczną tego podejścia jest sprawdzanie pokrycia programu np. sprawdzenie, czy wykonano wszystkie instrukcje, skoki, ścieżki przepływu danych. W praktyce stosuje się łącznie oba podejścia. Testowanie funkcjonalne określa na ile program spełnia specyfikację wykonuje funkcje oczekiwane od niego, ale nie określa, które jego części są wykonywane by wypełnić poszczególne wymagania w specyfikacji. Testowanie strukturalne może więc być jego uzupełnieniem. Zazwyczaj testowanie strukturalne stosuje się do niewielkich fragmentów oprogramowania np. do testowania jednostek. Testowanie funkcjonalne także może być użyte do testowania jednostek, jednak stosuje się je także do testowania większych fragmentów podsystemów, systemów. 2. Aksjomaty testowania obiektowego Aksjomaty testowania dla programów napisanych w językach strukturalnych zostały podane przez Weyuker w 1986 [10]. Było to osiem aksjomatów równoważności testów i danych testowych. W 1988 roku zostały dodane przez Weyuker [11] jeszcze trzy aksjomaty. Aksjomaty testowania oprogramowania strukturalnego Weyuker zostały przejrzane przez Perry ego i Kaisera pod kątem ich przydatności dla oprogramowania napisanego w językach obiektowych. W pracy [7] omówiono aksjomaty mające zastosowanie przy testowaniu oprogramowania obiektowego. Pewne z aksjomatów podanych przez Weyuker są intuicyjnie oczywiste dla programów obiektowych. Są to: Stosowalność (applicability) Dla każdego programu istnieje właściwy zbiór testów tzn. testów spełniających wymagane kryterium testowania. Nie wyczerpująca stosowalność (non-exhaustive applicability) Program P ma właściwy zbiór testów T, zbiór T nie jest wyczerpującym zbiorem testów (wszystkich możliwych). Monotoniczność (monotonicity) Jeżeli zbór testów T jest właściwy dla programu P i T jest podzbiorem zbioru T, to T jest także właściwy dla programu P. Niewłaściwość zbioru pustego (inadequate empty set) Nie ma programu dla którego pusty zbiór testów jest właściwy. Aksjomaty te stosują się do wszystkich programów niezależnie od języka programowania, w którym zostały napisane i nadają się zarówno do testowania strukturalnego jak i funkcjonalnego. Trzy inne aksjomaty Weyuker są także intuicyjnie oczywiste dla programów obiektowych, są to: Przemianowanie (renaming) Niech program P będzie przemianowaniem Q. Test T jest właściwy dla P tylko wtedy, gdy jest on właściwy dla Q. Program P jest przemianowaniem Q jeśli jest identyczny z Q z dokładnością do instancji

(np. zmiennej) o nazwie x z programu Q, która została nazwana y w P i identyfikator y nie występuje w Q. Jest to także prawdziwe dla zbioru przemianowań. Złożoność (complexity) Dla każdego n istnieje program P taki, że P jest właściwie testowany (testami spełniającymi wymagane kryterium testowania) przez zbiór testów o wielkości n, ale nie przez zbiór o wielkości n-1. Pokrycie instrukcji (statement coverage) Jeśli zbiór testów T jest właściwy dla P, przy kryterium testowania, którym jest pokrycie instrukcji, to T powoduje wykonanie każdej wykonywalnej instrukcji z P. Aksjomat pokrycia instrukcji jest przykładem aksjomatu stosowalności. Aksjomaty złożoności i przemianowania są stosowane do testowania strukturalnego jak i funkcjonalnego. Aksjomat pokrycia instrukcji stosuje się do testowania strukturalnego. Poniżej przedstawiono pozostałe cztery aksjomaty dotyczące testowania części programu i ich relacji z całym programem. Wskazują one na nieadekwatność pewnych testów dla programów obiektowych. Anty rozszerzalość (antiextensionality) Jeżeli dwa programy obliczają tę samą funkcję (są bliskie semantycznie) to właściwy dla jednego z nich test strukturalny niekoniecznie jest właściwy dla drugiego. Programy te mogą mieć inną implementację i test pokrywający np. wszystkie ścieżki grafu przepływu sterowania jednego z nich, nie będzie pokrywał drugiego programu (napisanego wg zupełnie innego algorytmu i mającego inny graf przepływu sterowania). Testy bazujące na specyfikacji (funkcjonalne) mogą być właściwe, gdyż oba programy obliczają tę samą funkcję. Zmiana semantyczna (general multiple change) Jeśli dwa programy są syntaktycznie podobne mają podobną budowę (jeden można otrzymać z drugiego poprzez zmianę stałych i/lub operatorów) to wymagają one różnych zbiorów testów. Jeśli test strukturalny jest właściwy dla jednego programu np. wymusza wykonanie obu gałęzi każdej instrukcji warunkowej, to nowy operator relacyjny i/lub stała w predykacie może wymusić inny test pokrywający gałęzie instrukcji warunkowej. Anty dekompozycja (antidecomposition) Testowanie podprogramu w kontekście otaczającego go programu może być właściwe, jednak po zmianie tego kontekstu (otoczenia podprogramu) może nie być wystarczające, czyli nie będzie wystarczające dla innych użyć komponentu. Aksjomat ten dotyczy testowania funkcjonalnego i strukturalnego. Test funkcjonalny może być adekwatny dla pewnego otoczenia A, które nie zawiera jakiejś funkcjonalności występującej w specyfikacji innego otoczenia B. Nie będzie ten test właściwy dla specyfikacji B. Program może być właściwie przetestowany strukturalnie nawet jeśli zawiera kod nieosiągalny i kod ten nie został przetestowany w otoczeniu A. Jednak w innym otoczeniu kod ten może być osiągalny i test nie będzie go pokrywał. Anty kompozycja (anticomposition) Właściwe testowanie komponentów programu w izolacji może nie być wystarczające do przetestowania całego programu. Kompozycja dwóch komponentów programu powoduje powstawanie interakcji, które nie mają miejsca w izolacji. Np. komponent A wywołuje kilka razy komponent B lub są one wzajemnie rekursywne. W obu przypadkach programy mogą modyfikować kontekst widziany przez drugi

komponent w sposób bardziej złożony niż przy indywidualnym testowaniu komponentów. Aksjomat ten dotyczy testowania strukturalnego i funkcjonalnego. 3. Wpływ cech języków obiektowych na testowanie Testowanie oprogramowania obiektowego [3] musi być dostosowane do cech języków obiektowych. Cechy oprogramowania obiektowego takie jak np. hermetyzacja, dziedziczenie, polimorfizm, dynamiczne wiązanie są bardzo wygodne i korzystne przy projektowaniu i programowaniu ale stwarzają pewne problemy podczas testowania. Hermetyzacja oznacza zamknięcie w obiekcie atrybutów i operacji które obiekt może wykonywać ( lub które można wykonywać na obiekcie). Operacje są udostępnione poprzez interfejs a szczegóły implementacyjne są ukryte wewnątrz. Interakcje pomiędzy obiektami są niełatwe do zrozumienia, wyobrażenia sobie, toteż przygotowanie testów interakcji obiektów jest sprawą trudną [4]. Dziedziczenie oznacza, że własności zdefiniowane dla klasy są dostępne (zostały odziedziczone) przez jej podklasy (o ile nie zostały w nich inaczej zdefiniowane). Metoda, która została przetestowana i jest poprawna w klasie bazowej może nie być poprawna w kontekście podklasy [7]. Polimorfizm oznacza, że atrybut może być różnych typów, metoda może mieć różne implementacje. Dynamiczne wiązanie kodu oznacza, że operacja nie jest znana do czasu wykonania. Cechy te czynią testowanie bardzo trudnym, gdyż dokładnego typu atrybutu czy implementacji operacji nie da się określić statycznie. Poniżej opisano wpływ hermetyzacji, dziedziczenia, polimorfizmu i dynamicznego wiązania na testowanie programów obiektowych opracowany na podstawie prac [7] i [8]. Hermetyzacja Hermetyzacja w językach obiektowych powoduje, że zmiana w implementacji przy zachowanym interfejsie zewnętrznym nie powinna wpływać na inne obiekty. Intuicja oparta na testowaniu funkcjonalnym podpowiada nam, że w takim przypadku wystarczy ograniczyć testowanie do obiektu zmodyfikowanego. Aksjomat anty kompozycji powiada, że należy także ponownie przetestować wszystkie obiekty zależne od modyfikowanego. Pokazana na rys. 1 klasa A zawiera metodę M, która została właściwie przetestowana w kontekście klasy A. Klasa B jest podklasą klasy A. Klasa B dziedziczy metodę M, nie zastępuje jej własną realizacją. Zgodnie z aksjomatem anty kompozycji należy przetestować metodę M w kontekście klasy B, mogą pojawić się bowiem nowe błędy wynikające z rozszerzonego kontekstu np. na rys. 1 pokazano konflikt zmiennej x (ustawianej przez metodę M klasy A i metodę L klasy B). Powyższy przykład pokazuje, że testowanie integracyjne jest zawsze konieczne jako uzupełnienie testowania jednostek, niezależnie od stosowanego języka programowania.

Klasa A Zmienne : x,... Metody: M,... M ustawia x na 1 nadklasa Klasa B Zmienne :... Metody: L,... L ustawia x na 0 podklasa Rys. 1 Konflikt zmiennej x Dziedziczenie W językach programowania obiektowych jeżeli jest modyfikowana klasa to konieczne i wystarczające będzie przetestowanie tej klasy i wszystkich klas od niej jawnie zależnych. Jeżeli modyfikowana jest nadklasa to należy przetestować wszystkie jej podklasy, gdyż są one zależne dziedzicząc jej metody. Aksjomat anty kompozycji mówi, że jeśli dodajemy nową podklasę (lub modyfikujemy istniejącą podklasę) to musimy przetestować metody odziedziczone z każdej klasy będącej jej przodkiem (nadklasą). Jest pewien przypadek w którym ponowne testowanie metod odziedziczonych z nadklasy nie jest konieczne. Chodzi o sytuację, w której podklasa jest czystym rozszerzeniem klasy będącej jej przodkiem tzn. dodaje nowe metody lub zmienne, ale nie ma żadnych zależności pomiędzy zmiennymi i metodami nowymi i odziedziczonymi. Polimorfizm W językach obiektowych podklasa może zastąpić metodę odziedziczoną poprzez lokalną definicję metody o tej samej nazwie. Jest oczywiste, że podklasa przykrywająca metodę powinna być przetestowana, jednak nie tak oczywistym jest to, że często konieczne są inne zbiory testów fakt ten podkreśla aksjomat anty rozszerzalności. Rozważmy sytuację pokazaną na rys. 2, w której klasa A zawierająca metodę M ma podklasę B. Klasa B nie ma lokalnej definicji metody M. Niech obiekt O będący instancją klasy B otrzyma komunikat powodujący wykonanie metody M. Metoda M w zastosowaniu do obiektu O była właściwie przetestowana. Jeżeli klasa B doda własną definicję metody M, która ma taki interfejs jak metoda M z klasy A A.M, to oczywista jest konieczność ponownego przetestowania klasy B. Aksjomat anty rozszerzalności przypomina, że należy opracować nowe przypadki testowe z dwóch powodów: 1. Jest wysoce prawdopodobne, że nowa definicja metody wpływa nie tylko na wewnętrzną strukturę klasy ale także zmienia jej specyfikację funkcjonalną

inne jest zewnętrzne zachowanie tej klasy. W takim przypadku konieczne są także inne testy funkcjonalne. Klasa A Metody: M, N... nadklasa Klasa A Metody: M,... Klasa B Metody:... podklasa Klasa B Metody: M... Metoda B.M nie wymaga testowania Rys. 2 Metoda B.M wymaga testowania 2. W testowaniu strukturalnym dąży się do pokrycia gałęzi lub instrukcji programu. Jeżeli instrukcje lub gałęzie są różne (a taki jest zazwyczaj cel nowej definicji np. inny algorytm) w obu realizacjach, to test pokrywający A.M może nie pokryć B.M. Dziedziczenie wielopoziomowe i wielobazowe Powyżej przedstawiono dwustronną zależność pomiędzy klasą i nadklasą powodującą konieczność testowania odziedziczonych metod w kontekście definiującym i każdym kontekście odziedziczonym. Nie uwzględniono wpływu aksjomatu anty rozszerzalności na to dodatkowe testowanie. Różne zbiory testów mogą być potrzebne w każdym punkcie łańcucha dziedziczenia, pomiędzy klasą przodkiem definiującą zastępowaną metodę i klasą potomkiem definiującą metodę zastępującą. Klasa A Metody: M, N... (M korzysta z N) Klasa B Metody: M,... (M używa N z A) Klasa C Metody: N... (M z B używa N z C) Rys.3 Łańcuch dziedziczenia

Na przykład pokazana na rys. 3 klasa A ma metody M i N, metoda M używa metody N. Klasa B jest podklasą klasy A i ma własną metodę M, która korzysta z metody N z klasy A. Klasa C jest potomkiem klasy B, definiuje własną metodę N, przykrywającą metodę N odziedziczoną z A i nie ma własnej definicji metody M. Aksjomat anty rozszerzalności mówi o różnych dla klas A, B, C danych testowych dla metody M. Jest to oczywiste dla A i B gdyż korzystają one z różnych metod M, nawet jeśli metody te są bliskie semantycznie to dane właściwe dla jednej klasy mogą nie być właściwe dla drugiej. Dla klas B i C jest to mniej oczywiste, gdyż używają one tej samej metody M. Jednak w klasie B metoda M wywołuje metodę A.N a w klasie C metodę B.N. Konieczne są różne zbiory testów, gdyż wysoce prawdopodobne jest że A.N i B.N mają inną funkcjonalność i/lub strukturę. Pewne języki obiektowe pozwalają na dziedziczenie wielobazowe. Niech klasa C dziedziczy po klasach A i B. Obie klasy A i B zawierają definicję metody M, a klasa C nie redefiniuje tej metody. Jeżeli kolejność dziedziczenia ustalono na najpierw A potem B to klasa C będzie używać metody A.M. Po zmianie kolejności nadklas na B potem A, klasa C odziedziczy metodę B.M zamiast jak poprzednio A.M. Klasa C musi być wówczas ponownie przetestowana. Nie ma powodu zakładać by A.M i B.M były semantycznie lub składniowo podobne a nawet jeśli są, to aksjomaty anty rozszerzalności i zmiany semantycznej przypominają o konieczności przygotowania innych zbiorów testów. Przepływ sterowania Innym problemem jest przepływ sterowania w programach obiektowych inny niż w konwencjonalnych. Podczas wykonywania programu obiektowego obiekty są tworzone, wykonują swoje metody, zmienia się ich stan, w końcu są niszczone. Przepływ sterowania w takich programach można widzieć jako przekazywanie komunikatów z jednego obiektu do drugiego powodujący wykonanie przez obiekt odbierający pewnej operacji, której rezultatem może być np. badanie lub zmiana stanu obiektu. W testowaniu takich programów bardziej właściwe niż określanie wejścia/wyjścia jest określanie zmian stanów obiektu pod pewnymi warunkami. W niektórych językach obiektowych obiekty mogą być niezależnymi współbieżnymi jednostkami. Wysłanie dwóch komunikatów z jednego obiektu do dwóch innych może powodować ich równoległe działanie. Ze względu na różnorodne zależności czasowe i wiele sytuacji, które należy rozważyć i sprawdzić, testowanie takich systemów jest bardzo skomplikowane. Dynamiczne wiązanie Pewne języki obiektowe np. Smalltalk, C++ pozwalają na dynamiczne wiązanie komunikatu z metodą. W języku C++ wskazanie na obiekt, referencja do obiektu może dotyczyć nie tylko obiektów zadeklarowanej klasy ale i jej potomków. Kiedy wykonywana jest operacja na obiekcie, funkcja zadeklarowana jako wirtualna, dynamicznie wiąże implementację tej funkcji z właściwą funkcją dla wykonywanego typu obiektu. Różne implementacje funkcji ustalą różne relacje w programie a analiza statyczna nie zawsze jest w stanie precyzyjnie określić wszystkie możliwe zależności. W praktyce stosowane są następujące rozwiązania [12]: Analiza najgorszego przypadku - brane są pod uwagę wszystkie możliwe implementacje funkcji i rozważa się zależności jakie one wprowadzają. Analiza dynamiczna program jest wykonywany dla różnych przypadków testowych, bada się rzeczywistą klasę, faktycznie wykonywaną funkcję.

Przypadki testowe mogą nie wykryć wszystkich możliwych zachowań programu i mogą być wyciągnięte nieprawidłowe wnioski. Interwencja użytkownika - człowiek wymusza powstanie obiektu określonej klasy. Analiza systemu też może być nieprawidłowa człowiek może wyciągnąć błędne wnioski. 4. Uwagi końcowe W pracy przedstawiono podstawowe problemy związane z testowaniem oprogramowania obiektowego. Uwzględniono takie cechy języków obiektowych jak hermetyzacja, dziedziczenie, polimorfizm, czy dynamiczne wiązanie. Podano także pewne wskazówki praktyczne np.: 1. Jeżeli dodajemy podklasę to odziedziczone metody powinny być przetestowane w nowo utworzonym kontekście. 2. Jeżeli kolejność specyfikacji podklas została zmieniona to podklasy powinny być ponownie testowane. 3. Nawet jeśli zastępowane metody są podobne semantycznie, to klasa powinna być testowana w kontekście metod zastępujących. Nie poruszono wielu innych problemów testowania oprogramowania obiektowego np. testowania ścieżek komunikatów [2, 5], czy zmian stanów obiektów i tematyki automatycznej generacji testów [1, 6]. Literatura [1] Binder R. (editor), Object-Oriented Software Testing, CACM, 9 (1994), 28-29 [2] Jorgensen P. C. Ericson C., Object Oriented Integration Testing, CACM, 9 (1994) [3] Kung D.C., Hsia P., Gao J., (editors), Testing Object-Oriented Software, IEEE Computer Society, (1998) [4] Letovski S., Soloway E., Delocalized Plans and Program Comprehension, IEEE Trans. Software, 3 (1986), 41-49 [5] Murphy G.C. et al. Experiences with Cluster and Class Testing, CACM, 9(1994) [6] Poston R.M., Automated Testing from Object Models, CACM, 9 (1994) [7] Perry D.E., Kaiser G.E., Adequate Testing and Object-Oriented Programming, J. Object-Oriented Programming, Jan.-Feb 1990, 13-19. [8] Smith M.D., Robson D.J., Object-Oriented Programming the Problems of Validation, Proc. IEEE Conf. Software Maintenance, IEEE Society Press, Los Alamitos 1990, 272-281 [9] Sommerville I., Software Engineering,fifth edition, Addison Wesley 1996 [10] Weyuker E.J., Axiomating Software Test Data Adequacy, IEEE Trans. Software, 12 (1986), 1128-1138 [11] Weyuker E.J., The Evaluation of Program-Based Software Test Data Adequacy Criteria, CACM, 6 (1988), 668-675 [12] Wilde N., Huit R., Maintenance Support for Object-Oriented Programs, IEEE Trans. Software, 12 (1992) 1038-1044

dane o autorze: dr inż. Ilona Bluemke jest pracownikiem Instytutu Informatyki Politechniki Warszawskiej Abstract In this paper main problems of testing object programs are presented. Weyuker axioms for adequacy of test and test data (applicability, non-exaustive applicability, monotonicity, complexity, inadequate empty set, anticomposition, antidecomposition, statement coverage, renaming, antiextensionality, general multiple change) are discussed in the context of object programs. The role of object properties (encapsulation, inheritance, polymorphism, dynamic bindings) in the testing process is pointed out. Some practical hints to object testing are also given. Keywords: software engineering, object oriented testing, axioms of testing, properties of object programs