Udostępnij przez


Generowanie danych wejściowych przy użyciu dynamicznego wykonywania symbolicznego

Narzędzie IntelliTest generuje dane wejściowe dla sparametryzowanych testów jednostkowych , analizując warunki gałęzi w programie. Dane wejściowe testowe są wybierane na podstawie tego, czy mogą wyzwalać nowe zachowania rozgałęziania programu. Analiza jest procesem przyrostowym. Uściśli predykat q: I -> {true, false} dla formalnych parametrów I wejściowych testu. q reprezentuje zestaw zachowań zaobserwowanych już przez narzędzie IntelliTest. Początkowo , q := falseponieważ nic nie zostało jeszcze zaobserwowane.

Oto kroki pętli:

  1. Narzędzie IntelliTest określa dane wejściowe i takie, że q(i)=false używając modułu rozwiązywania ograniczeń. Z założenia dane wejściowe i przyjmą ścieżkę przetwarzania, której nie widziano wcześniej. Początkowo oznacza to, że i może to być dowolne dane wejściowe, ponieważ nie odnaleziono jeszcze żadnej ścieżki wykonywania.

  2. Narzędzie IntelliTest wykonuje test z wybranymi danymi wejściowymi ii monitoruje wykonywanie testu i testowany program.

  3. Podczas wykonywania program przyjmuje określoną ścieżkę, która jest określana przez wszystkie gałęzie warunkowe programu. Zestaw wszystkich warunków określających wykonanie jest nazywany warunkiem ścieżki, zapisanym jako predykat p: I -> {true, false} nad formalnymi parametrami wejściowymi. Narzędzie IntelliTest oblicza reprezentację tego predykatu.

  4. IntelliTest zestawia q := (q or p). Innymi słowy, rejestruje fakt, że widział ścieżkę reprezentowaną przez p element.

  5. Przejdź do kroku 1.

Narzędzie do rozwiązywania ograniczeń intelliTest może obsługiwać wartości wszystkich typów, które mogą występować w programach platformy .NET:

IntelliTest filtruje dane wejściowe naruszające określone założenia.

Oprócz natychmiastowych danych wejściowych (argumentów do sparametryzowanych testów jednostkowych) test może pobierać dalsze wartości wejściowe z klasy statycznej PexChoose. Opcje określają również zachowanie sparametryzowanych mocków.

Moduł rozwiązywania ograniczeń

Narzędzie IntelliTest używa modułu rozwiązywania ograniczeń w celu określenia odpowiednich wartości wejściowych testu i testowego programu.

Narzędzie IntelliTest używa modułu rozwiązywania ograniczeń Z3 .

dynamiczne pokrycie kodu

Jako efekt uboczny monitorowania środowiska uruchomieniowego intelliTest zbiera dynamiczne dane pokrycia kodu. Jest to nazywane dynamicznym , ponieważ narzędzie IntelliTest wie tylko o kodzie, który został wykonany, dlatego nie może nadawać wartości bezwzględnych pokrycia w taki sam sposób, jak zwykle inne narzędzie pokrycia.

Na przykład, gdy funkcja IntelliTest zgłasza pokrycie dynamiczne wynoszące 5/10 podstawowych bloków, oznacza to, że ujęto pięć bloków z dziesięciu, gdzie całkowita liczba bloków we wszystkich metodach, jakie analiza osiągnęła do tej pory (w przeciwieństwie do wszystkich metod istniejących w zestawie testowanym) wynosi dziesięć. W dalszej części analizy, w miarę odnajdywanie bardziej osiągalnych metod, może wzrosnąć zarówno licznik (5 w tym przykładzie), jak i mianownik (10).

Liczby całkowite i liczby zmiennoprzecinkowe

Moduł rozwiązywacza ograniczeń IntelliTest określa wartości danych wejściowych typów pierwotnych, takich jak bajt, liczba całkowita, zmiennoprzecinkowy i inne, aby wyzwolić różne ścieżki wykonawcze dla testu i testowanego programu.

Objects

Narzędzie IntelliTest może tworzyć wystąpienia istniejących klas platformy .NET lub za pomocą narzędzia IntelliTest automatycznie tworzyć makiety obiektów implementujących określony interfejs i zachowywać się w różny sposób w zależności od użycia.

Instancjonowanie istniejących klas

Jaki jest problem?

Narzędzie IntelliTest monitoruje wykonane instrukcje, gdy uruchamia test i program w ramach testu. W szczególności monitoruje cały dostęp do pól. Następnie używa modułu rozwiązywania ograniczeń do określania nowych danych wejściowych testowych, w tym obiektów i ich wartości pól, tak aby test i program w ramach testu działały w inny interesujący sposób.

Oznacza to, że narzędzie IntelliTest musi tworzyć obiekty niektórych typów i ustawiać ich wartości pól. Jeśli klasa jest widoczna i ma widoczny konstruktor domyślny, narzędzie IntelliTest może utworzyć wystąpienie klasy. Jeśli wszystkie pola klasy są widoczne, narzędzie IntelliTest może automatycznie ustawić pola.

Jeśli typ nie jest widoczny lub pola nie są widoczne, narzędzie IntelliTest potrzebuje pomocy w tworzeniu obiektów i dostarczaniu ich do interesujących stanów w celu osiągnięcia maksymalnego pokrycia kodu. Narzędzie IntelliTest może użyć refleksji w celu utworzenia i zainicjowania wystąpień w dowolny sposób, ale zwykle nie jest to pożądane, ponieważ może wprowadzić obiekt do stanu, który nigdy nie występuje podczas normalnego wykonywania programu. Zamiast tego narzędzie IntelliTest opiera się na wskazówkach od użytkownika.

Widoczność

Platforma .NET ma rozbudowany model widoczności: typy, metody, pola i inne elementy członkowskie mogą być prywatne, publiczne, wewnętrzne i inne.

Gdy narzędzie IntelliTest generuje testy, podejmie próbę wykonania tylko akcji (takich jak wywoływanie konstruktorów, metod i pól ustawień), które są legalne w odniesieniu do reguł widoczności platformy .NET z poziomu kontekstu wygenerowanych testów.

Reguły są następujące:

  • Widoczność wewnętrznych członków

    • IntelliTest zakłada, że wygenerowane testy będą miały dostęp do wewnętrznych elementów członkowskich, które były widoczne dla otaczającej klasy PexClass. W .NET istnieje atrybut InternalsVisibleToAttribute, który rozszerza widoczność elementów wewnętrznych na inne zestawy.
  • Widoczność prywatnych i rodzinnych (chronionych w języku C#) członków PexClass

    • Narzędzie IntelliTest zawsze umieszcza wygenerowane testy bezpośrednio w PexClass lub w podklasie. W związku z tym IntelliTest zakłada, że może używać wszystkich widocznych członków rodziny (protected w języku C#).
    • Jeśli wygenerowane testy są umieszczane bezpośrednio w PexClass (zwykle przy użyciu klas częściowych), IntelliTest zakłada, że może używać również wszystkich prywatnych elementów członkowskich PexClass.
  • Widoczność publicznych członków

    • IntelliTest zakłada, że może używać wszystkich wyeksportowanych elementów widocznych w kontekście PexClass.

Sparametryzowane mocki

Jak przetestować metodę, która ma parametr typu interfejsu? A może klasy nie zapieczętowanej? Narzędzie IntelliTest nie wie, które implementacje będą później używane w przypadku wywołania tej metody. I być może nawet nie ma rzeczywistej implementacji dostępnej w czasie testowania.

Konwencjonalną odpowiedzią jest użycie pozornych obiektów z wyraźnym zachowaniem.

Obiekt makiety implementuje interfejs (lub rozszerza klasę, która nie jest zapieczętowana). Nie reprezentuje on rzeczywistej implementacji, ale tylko skrót umożliwiający wykonywanie testów przy użyciu makiety obiektu. Jego zachowanie jest definiowane ręcznie w ramach każdego przypadku testowego, w którym jest używany. Istnieje wiele narzędzi, które ułatwiają definiowanie obiektów typu mock i ich oczekiwanego zachowania, ale zachowanie to nadal trzeba definiować ręcznie.

Zamiast trwale zakodowanych wartości w obiektach makiety, narzędzie IntelliTest może wygenerować wartości. Podobnie jak w przypadku sparametryzowanego testowania jednostkowego, narzędzie IntelliTest umożliwia również sparametryzowane makiety.

Parametryzowane mocki mają dwa różne tryby działania:

  • wybór: podczas eksplorowania kodu sparametryzowane makiety są źródłem dodatkowych danych wejściowych testów, a narzędzie IntelliTest spróbuje wybrać interesujące wartości
  • powtórzenie: podczas wykonywania wcześniej wygenerowanego testu sparametryzowane makiety zachowują się jak wycinki z zachowaniem (innymi słowy, wstępnie zdefiniowane zachowanie).

Użyj PexChoose, aby uzyskać wartości sparametryzowanych obiektów imitujących.

Struktury danych

Rozumowanie IntelliTest dotyczące wartości struktury jest podobne do sposobu, w jaki postępuje z obiektami.

Tablice i ciągi

Narzędzie IntelliTest monitoruje wykonane instrukcje w miarę uruchamiania testu i testowanego programu. W szczególności obserwuje, kiedy program zależy od długości ciągu lub tablicy (oraz dolnej granicy i długości tablicy wielowymiarowej). Obserwuje również, jak program używa różnych elementów ciągu lub tablicy. Następnie używa modułu rozwiązywania ograniczeń , aby określić, które długości i wartości elementów mogą spowodować, że test i program testowy zachowują się w ciekawy sposób.

Narzędzie IntelliTest próbuje zminimalizować rozmiar tablic i ciągów wymaganych do wyzwolenia interesujących zachowań programu.

Uzyskiwanie dodatkowych danych wejściowych

Klasa statyczna PexChoose może być używana do uzyskiwania dodatkowych danych wejściowych do testu oraz do implementowania sparametryzowanych makiet.

Masz opinię?

Opublikuj swoje pomysły i prośby dotyczące funkcji w społeczności deweloperów.