Testy jednostkowe Wybrane problemy testowania metod rekurencyjnych

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

Priorytetyzacja przypadków testowych za pomocą macierzy

Zastosowanie logiki matematycznej w procesie weryfikacji wymagań oprogramowania

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

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

Odwrotna analiza wartości brzegowych przy zaokrąglaniu wartości

Algorytmika i pseudoprogramowanie

Liczbowe funkcje rekurencyjne wielu zmiennych uczymy się na błędach

O pewnych problemach analizy wartości brzegowych

TEMAT : KLASY DZIEDZICZENIE

Klasy abstrakcyjne i interfejsy

ALGORYTMY I STRUKTURY DANYCH

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

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

Szablony funkcji i szablony klas

Poprawność semantyczna

Testowanie elementów programowalnych w systemie informatycznym

REKURENCJA W JĘZYKU HASKELL. Autor: Walczak Michał

Rekurencja (rekursja)

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

TEORETYCZNE PODSTAWY INFORMATYKI

Wstęp do programowania

Programowanie obiektowe

Instrukcja 2 Laboratorium z Podstaw Inżynierii Oprogramowania

Programowanie - wykład 4

Opis zagadnieo 1-3. Iteracja, rekurencja i ich realizacja

1. Nagłówek funkcji: int funkcja(void); wskazuje na to, że ta funkcja. 2. Schemat blokowy przedstawia algorytm obliczania

Paradygmaty programowania

Teoretyczne podstawy informatyki

Programowanie obiektowe

referencje Wykład 2. Programowanie (język C++) Referencje (1) int Num = 50; zdefiniowano zmienną Num (typu int) nadając jej wartość początkową 50.

Wykład 4: Klasy i Metody

5. Rekurencja. Przykłady

Konstruktor kopiujacy

Podstawy programowania 2. Temat: Funkcje i procedury rekurencyjne. Przygotował: mgr inż. Tomasz Michno

Lab 10. Funkcje w argumentach funkcji metoda Newtona. Synonimy nazw typów danych. Struktury. Tablice struktur.

Programowanie obiektowe i zdarzeniowe

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

Matematyka Dyskretna. Andrzej Szepietowski. 25 czerwca 2002 roku

Szablony funkcji i klas (templates)

Programowanie obiektowe

Rekurencje. Jeśli algorytm zawiera wywołanie samego siebie, jego czas działania moŝe być określony rekurencją. Przykład: sortowanie przez scalanie:

Programowanie strukturalne i obiektowe. Funkcje

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p.

Programowanie obiektowe

Strona główna. Strona tytułowa. Programowanie. Spis treści. Sobera Jolanta Strona 1 z 26. Powrót. Full Screen. Zamknij.

PARADYGMATY PROGRAMOWANIA Wykład 4

Wstęp do programowania

4. Funkcje. Przykłady

Technologie informacyjne - wykład 12 -

Programowanie w języku C++ Podstawowe paradygmaty programowania

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

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

Podstawy i języki programowania

Algorytm. a programowanie -

Wykład 8. Rekurencja. Iterować jest rzeczą ludzką, wykonywać rekursywnie boską. L. Peter Deutsch

Pętle i tablice. Spotkanie 3. Pętle: for, while, do while. Tablice. Przykłady

Wykład 3 Składnia języka C# (cz. 2)

Język programowania PASCAL

Strategia "dziel i zwyciężaj"

//warunki początkowe m=500; T=30; c=0.4; t=linspace(0,t,m); y0=[-2.5;2.5];

JAVA W SUPER EXPRESOWEJ PIGUŁCE

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

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów

wykład II uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C - funkcje, tablice i wskaźniki wykład II dr Jarosław Mederski Spis

Interfejsy. Programowanie obiektowe. Paweł Rogaliński Instytut Informatyki, Automatyki i Robotyki Politechniki Wrocławskiej

Zapisywanie algorytmów w języku programowania

Konstruktory. Streszczenie Celem wykładu jest zaprezentowanie konstruktorów w Javie, syntaktyki oraz zalet ich stosowania. Czas wykładu 45 minut.

Lista dwukierunkowa - przykład implementacji destruktorów

Ataki na RSA. Andrzej Chmielowiec. Centrum Modelowania Matematycznego Sigma. Ataki na RSA p. 1

Algorytmy komputerowe. dr inŝ. Jarosław Forenc

Rozdział 4 KLASY, OBIEKTY, METODY

Wieczorowe Studia Licencjackie Wrocław, Wykład nr 6 (w oparciu o notatki K. Lorysia, z modyfikacjami) Sito Eratostenesa

Wprowadzenie do programowania

Programowanie obiektowo zorientowane. Mirosław Głowacki Wykład w języku C++

Praktyka Programowania

4 Literatura. c Dr inż. Ignacy Pardyka (Inf.UJK) ASK MP.01 Rok akad. 2011/ / 24

Programowanie Niskopoziomowe

Zaawansowane programowanie obiektowe - wykład 5

Wstęp do programowania

Enkapsulacja, dziedziczenie, polimorfizm

Elektrotechnika I stopień (I stopień / II stopień) Ogólnoakademicki (ogólno akademicki / praktyczny) Niestacjonarne (stacjonarne / niestacjonarne)

Podstawy programowania funkcjonalnego

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

kiedy znowu uzyska sterowanie, to podejmuje obliczenie od miejsca, w którym poprzednio przerwała, i z dotychczasowymi wartościami zmiennych,

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

Język C++ umożliwia przeciążanie operatora, tzn. zmianę jego znaczenia na potrzeby danej klasy. W tym celu definiujemy funkcję o nazwie:

Zaawansowane algorytmy i struktury danych

Matematyczne Podstawy Informatyki

PoniŜej znajdują się pytania z egzaminów zawodowych teoretycznych. Jest to materiał poglądowy.

Wprowadzenie do szablonów szablony funkcji

Podstawy Programowania

Assembler w C++ Syntaksa AT&T oraz Intela

EFEKTY UCZENIA SIĘ DLA KIERUNKU INŻYNIERIA DANYCH W ODNIESIENIU DO EFEKTÓW UCZENIA SIĘ PRK POZIOM 6

Wprowadzenie do szablonów szablony funkcji

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

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

Historia modeli programowania

Rekurencja. Przygotowała: Agnieszka Reiter

Transkrypt:

Testy jednostkowe Wybrane problemy testowania metod rekurencyjnych Artykuł przeznaczony jest dla osób związanych z testowaniem, programowaniem, jakością oraz wytwarzaniem oprogramowania, wymaga jednak znajomości podstaw programowania obiektowego. Testy jednostkowe przeprowadzane są na poziomie kodu podczas procesu wytwarzania oprogramowania. Na ich temat można znaleźć wiele publikacji, książek i artykułów naukowych. Również w Internecie jest sporo wiadomości na ten temat. Nieczęsto jednak znajdziemy informacje o testowaniu metod wywoływanych rekurencyjnie. Okazuje się, że testy jednostkowe dla takich metod nie są proste i dodatkowo wymagają twórczego podejścia od autora. 1. Zjawisko rekurencji w naukach ścisłych Definicja 1.1 [1] Rekurencja jest techniką programowania, dzięki której procedura, funkcja lub podprogram jest w stanie w swoim ciele wywołać sam siebie. Dzięki rekurencji łatwo można wykonać zadanie, w którym potrzebne są wyniki cząstkowe do obliczenia całości. Rekurencja składa się z podania wartości brzegowych (początkowych) i z równania wyrażającego ogólną wartość za pomocą wartości wcześniejszych wyrazów. Klasycznym przykładem w zagadnieniu rekurencji jest liczenie silni dla dowolnej liczby naturalnej n, czyli (n!): Przykład 1.1 n! = 1, n = 0 n(n 1)!, n 1. Rekurencja może być z dobrym skutkiem stosowana w najefektywniejszych algorytmach sortowania. Rekurencyjny opis obliczeń (funkcji czy metod) jest na ogół bardziej zwarty (krótszy, przejrzysty) niż opis tych samych obliczeń bez użycia rekurencji. Taki opis jest stosowany np. przy opisie fraktali, które są definiowane, jako obiekty podobne do swoich części (obiekty samopodobne). Zwartość opisu rekurencyjnego nie zawsze idzie w parze z efektywnością realizacji algorytmów. Dlatego algorytmy rekurencyjne powinny być stosowane rozsądnie. Istnieje także pewna klasa funkcji rekurencyjnych, które można przedstawić jawnym wzorem typu f(n), gdzie n є N. Nie zawsze jednak jest to możliwe.

. Sformułowanie problemu Załóżmy, że w kodzie pewnego oprogramowania istnieją metody zaimplementowane rekurencyjnie. Do tych metod należy napisać testy jednostkowe. Wobec tego potrzebne są sposoby, dzięki którym będzie można otrzymać dane oczekiwane w celu sprawdzenia poprawności rezultatu testów jednostkowych. W takiej sytuacji z pewnością można napotkać następujące problemy: a) metoda jest zaimplementowana, jako funkcja jednej lub wielu zmiennych liczb naturalnych, b) metoda nie jest funkcją, która da się opisać wyrażeniem matematycznym, W artykule skupimy się na metodzie matematycznej. Załóżmy, że pewna firma handlowa potrzebuje aplikację (C#), która ułatwi zarządzanie wynagrodzeniami dla pracowników (w tym również systemem wypłaty premii). Należy zaimplementować metodę, która ma liczyć premię od ilości sprzedanych napojów, które są pakowane w pakiety. Premia może być wypłacona w dowolnym czasie (ale od całych pakietów z napojami), o czym decyduje osoba, której ta premia się należy. Kolejna premia jest pomniejszana o kwotę wypłaconą wcześniej. Zarząd firmy chce, aby: i) premia od sprzedaży uzależniona była od ilości poprzednio sprzedanych pakietów, ii) do bieżącej sprzedaży dodawane było wyrażanie m 1, gdzie m ilość wszystkich sprzedanych pakietów. Wobec tego, równanie przedstawiające kwotę premii będzie miało postać: f(m) = 0, m = 1 f(m 1) + m 1, m > 1 (1). Równania rekurencyjne o postaci (1) jak wyżej zazwyczaj dają się rozwiązać, a dzięki temu można otrzymać jawny wzór f(m). Wobec tego niech m 0. Rozpisując lewą stronę równania otrzymujemy wyrażenie: f(m) = f(m 1) + m 1 = f(m ) + m 1 1 + m 1 = f(m ) + (m ) + (m 1) = = f(m 3) + (m 3) + (m ) + (m 1) = ( ) () Podczas kolejnych cofnięć do poprzednich argumentów funkcji f dochodzimy do kroku: m k = 1, czyli m = k + 1. ( ) = f(m k) + km i = (m 1)m m i=1 m(m 1) = m m m m = m m. (3)

Dla zachowania poprawności postępowania wykażemy indukcyjnie, że rozwiązanie m m jest poprawne. 1) Dla m = 1 mamy f(m) = 0. ) Załóżmy, że równanie jest poprawnie rozwiązane dla każdego m є N. Wykazać należy, że dla każdego (m + 1) є N. Wobec tego: f(m + 1) = (m + 1) (m + 1) = m + m + 1 m 1 Z drugiej strony wstawiając do postaci rekurencyjnej m+1 za m mamy co należało wykazać. f(m + 1 1) + m + 1 1 = f(m) m, Kod funkcji f(m) umieszczony w pewnej klasie w języku C# ma postać: public class Funkcje = m m + m. public virtual int Premia(int m) if (m == 1) return 0; else return Premia(m - 1) + m + 1; // pochodna klasy Funkcje utworzona w celu zaprojektowania testów public class TesterFuncji : Funkcje public int liczbawywolan get; set; public override int Premia(int m) liczbawywolan ++; return base.premia(m); // metoda pomocnicza z rozwiąnym wzorem public int WzorFunkcji(int m) return (m*m-m)/; // klasa testowa

public class TestyJednostkowe // test sprawdza, czy wartości zwrócone rekurencyjnie są równe z // oczekiwanym rezultatem, czyli wzorem danym jawnie [Test] Public void CzySaRowne var tester = new TesterFunkcji(); for (int j = 1; j <= 100; j++) Assert.AreEqual(tester.WzorFunkcji(j),tester.Premia(j)); // test sprawdza, czy metoda się wywołuje co najmniej raz [Test] Public void CzyWywolujeSieRaz var tester = new TesterFunkcji(); tester.premia(1); Assert.GreaterOrEqual(1, tester.liczbawywolan); Wyżej przedstawiona metoda Premia w dość prosty sposób pozwoliła na zaimplementowanie testów niej samej. Istnieje również tzw. metoda szeregów funkcyjnych, która ma zastosowanie w rozwiązywaniu funkcji zdefiniowanych rekurencyjnie, np. takich jak ciąg Fibonacciego, ale nie należy do najprostszych sposobów rozwiązywania równań. Nie zawsze jednak musi tak być, że metoda rekurencyjna ma parametr, który jest liczbą naturalną. Nie zawsze też można taką metodę rozwiązań algebraicznie. W takim przypadku podejście do testów musi być dostosowane do metody, którą chcemy sprawdzić. 3. W czym jest dokładnie problem z rekurencją? Cały proces wywołania rekurencji musi pamiętać wszystkie wartości zmiennych na każdym poziomie wywołania. 1000 - razy wykonana rekurencja oznacza 1000 - krotne zapamiętanie wszystkich zmiennych, które są używane w metodzie, a to może powodować problem z wydajnością. Dokładna implementacja i rozmieszczenie pamięci do obliczeń rekurencyjnych są zależne od języka programowania, ale zazwyczaj dzieje się to w stosie, który przetrzymuje wartości funkcji. Następnie stos jest czyszczony od góry, co daje możliwość wykonywania obliczeń w odwrotnej kolejności. Należy jednak pamiętać, że pamięć na stosie jest ograniczona. Istnieją pewne metody optymalizacji wywołań rekurencyjnych np. optymalizacja ogonowa, która polega na usuwaniu operacji wracających z powrotem. Taka optymalizacja jest przydatna, gdy pojedyncze sekwencje wywołań metody są bardzo długie.

Języki programowania (np. C#) często zawierają instrukcje, które umożliwiają optymalizację rekurencji. Jednak po zastosowaniu tych instrukcji nie ma pewności, że wszystko zadziała poprawnie w każdym przypadku (środowisko uruchomieniowe C# ma instrukcje optymalizacji rekurencji, ale kompilator ich nie zweryfikuje [3]), dlatego dobre testy jednostkowe spełnią swoją rolę. Wnioski: i) testy jednostkowe dla metod rekurencyjnych powinny sprawdzać nie tylko wartości wyjściowe, ale również aspekty techniczne wywołania tych metod, np. wydajność, testy pamięci zależne od platformy, ii) osoba pisząca testy powinna wiedzieć, jak działa język programowania w przypadku implementacji metod rekurencyjnych, co jest w stanie sprawdzić kompilator, a czego nie sprawdza, jak po implementacji takich metod podejść do testowania, iii) testy jednostkowe dla metod rekurencyjnych powinny pisać osoby z dobrą techniczną znajomością języka programowania oraz wywołań rekurencyjnych. 4. Referencje [1]https://www.bryk.pl/wypracowania/pozosta%C5%8e/informatyka/15879rekurencjaiiteracjar%C3%B3 %C5%BCniceipodobie%C5%84stwa.html []http://stackoverflow.com/questions/41759/how-to-write-a-mockist-test-of-a-recursive-method [3]https://msdn.microsoft.com/pl-pl/library/optymalizacja-kodu-c-sharp--czesc-3.aspx Marek Żukowicz jest absolwentem matematyki na Uniwersytecie Rzeszowskim. Obecnie pracuje jako tester. Jego zainteresowania skupiają się wokół testowania, matematyki, zastosowania algorytmów ewolucyjnych oraz zastosowania matematyki w procesie testowania. Interesuje się również muzyką, grą na akordeonie oraz perkusji.