Sdílet prostřednictvím


Generování vstupu pomocí dynamického symbolického spouštění

IntelliTest generuje vstupy pro parametrizované testy jednotek tím, že analyzuje podmínky větve v programu. Vstupy testů se vybírají na základě toho, jestli mohou aktivovat nové chování větvení programu. Analýza je přírůstkový proces. Zpřesní predikát q: I -> {true, false} nad formálními vstupními parametry Itestu . q představuje sadu chování, které již IntelliTest pozoroval. Zpočátku , q := falseod té doby, co nic dosud nebylo pozorováno.

Kroky smyčky jsou:

  1. IntelliTest určuje vstupy i , které q(i)=false používají řešitel omezení. Díky konstrukci bude vstup i trvat cestu provádění, která ještě není vidět. Zpočátku to znamená, že i může být jakýkoli vstup, protože nebyla dosud zjištěna žádná cesta spuštění.

  2. IntelliTest spustí test s vybraným vstupem ia monitoruje provádění testu a programu, který se testuje.

  3. Během provádění program vezme konkrétní cestu, která je určena všemi podmíněnými větvemi programu. Sada všech podmínek, které určují spuštění, se nazývá podmínka cesty zapsaná jako predikát p: I -> {true, false} formálních vstupních parametrů. IntelliTest vypočítá reprezentaci tohoto predikátu.

  4. Sady q := (q or p)IntelliTest . Jinými slovy, zaznamenává skutečnost, že viděl cestu reprezentovanou p.

  5. Přejděte ke kroku 1.

Řešitel omezení IntelliTestu může pracovat s hodnotami všech typů, které se mohou objevit v programech .NET:

IntelliTest vyfiltruje vstupy, které porušují uvedené předpoklady.

Kromě okamžitých vstupů (argumentů pro parametrizované testy jednotek) může test nakreslit další vstupní hodnoty ze statické třídy PexChoose . Volby také určují chování parametrizovaných napodobení.

Řešitel omezení

IntelliTest používá řešitel omezení k určení relevantních vstupních hodnot testu a programu, který se testuje.

IntelliTest používá řešitel omezení Z3 .

Dynamické pokrytí kódu

IntelliTest shromažďuje data dynamického pokrytí kódu jako vedlejší účinek monitorování modulu runtime. Tato funkce se nazývá dynamická , protože IntelliTest ví pouze o kódu, který byl proveden, a proto nemůže poskytnout absolutní hodnoty pro pokrytí stejným způsobem jako jiný nástroj pokrytí obvykle.

Například když IntelliTest hlásí dynamické pokrytí jako základní bloky 5/10, znamená to, že bylo pokryto pět bloků z deseti, kde celkový počet bloků ve všech metodách, které byly dosud dosaženo analýzou (na rozdíl od všech metod, které existují v sestavení v rámci testu) je deset. Později v analýze, jak jsou zjištěny přístupnější metody, může se zvýšit jak čitatel (5 v tomto příkladu), tak jmenovatel (10).

Celá čísla a čísla s plovoucí desetinnou čárkou

Řešitel omezení IntelliTestu určuje vstupní hodnoty testovacích hodnot primitivních typů, jako jsou bajty, int, float a další, aby bylo možné aktivovat různé cesty spuštění pro test a program, který test testuje.

Objekty

IntelliTest může buď vytvářet instance existujících tříd .NET, nebo můžete použít IntelliTest k automatickému vytváření napodobených objektů, které implementují konkrétní rozhraní a chovají se různými způsoby v závislosti na využití.

Vytvoření instance existujících tříd

Jaký je problém?

IntelliTest monitoruje spuštěné instrukce, když spustí test a program pod testem. Konkrétně monitoruje veškerý přístup k polím. Potom pomocí řešitele omezení určí nové testovací vstupy, včetně objektů a jejich hodnot polí, aby se test a program pod testem chovali jinými zajímavými způsoby.

To znamená, že IntelliTest musí vytvářet objekty určitých typů a nastavit jejich hodnoty polí. Pokud je třída viditelná a má viditelný výchozí konstruktor, IntelliTest může vytvořit instanci třídy. Pokud jsou všechna pole třídy viditelná, IntelliTest může tato pole nastavit automaticky.

Pokud typ není viditelný nebo pole nejsou viditelná, potřebuje IntelliTest pomoct vytvořit objekty a přenést je do zajímavých stavů, aby bylo možné dosáhnout maximálního pokrytí kódu. IntelliTest by mohl použít reflexi k vytvoření a inicializaci instancí libovolným způsobem, ale to obvykle není žádoucí, protože by mohl přenést objekt do stavu, který se nikdy během normálního provádění programu neskončí. Místo toho IntelliTest spoléhá na rady od uživatele.

Viditelnost

.NET má propracovaný model viditelnosti: typy, metody, pole a další členy můžou být soukromé, veřejné, interní a další.

Když IntelliTest generuje testy, pokusí se provádět pouze akce (například volání konstruktorů, metod a nastavení polí), které jsou legální s ohledem na pravidla viditelnosti rozhraní .NET z kontextu vygenerovaných testů.

Pravidla jsou následující:

  • Viditelnost interních členů

    • IntelliTest předpokládá, že generované testy budou mít přístup k interním členům, které byly viditelné pro uzavřenou třídu PexClass. .NET má InternalsVisibleToAttribute , aby se rozšířila viditelnost interních členů na další sestavení.
  • Viditelnost soukromých členů a členů rodiny (chráněná v jazyce C#) třídy PexClass

    • IntelliTest vždy umístí vygenerované testy přímo do třídy PexClass nebo do podtřídy. IntelliTest proto předpokládá, že může používat všechny viditelné členy rodiny (chráněné v jazyce C#).
    • Pokud jsou generované testy umístěny přímo do třídy PexClass (obvykle pomocí částečných tříd), IntelliTest předpokládá, že může také používat všechny soukromé členy třídy PexClass.
  • Viditelnost veřejných členů

    • IntelliTest předpokládá, že může používat všechny exportované členy viditelné v kontextu třídy PexClass.

Parametrizované napodobeniny

Jak otestovat metodu, která má parametr typu rozhraní? Nebo nepečetěné třídy? IntelliTest neví, které implementace se později použijí při zavolání této metody. A možná není ani skutečná implementace dostupná v testovací době.

Konvenční odpovědí je použití napodobených objektů s explicitním chováním.

Napodobený objekt implementuje rozhraní (nebo rozšiřuje nezapečetěnou třídu). Nepředstavuje skutečnou implementaci, ale pouze zástupce, který umožňuje provádění testů pomocí napodobení objektu. Jeho chování je definováno ručně jako součást každého testovacího případu, kde se používá. Existuje mnoho nástrojů, které usnadňují definování napodobených objektů a jejich očekávaného chování, ale toto chování musí být stále ručně definováno.

Místo pevně zakódovaných hodnot v napodobených objektech může IntelliTest vygenerovat hodnoty. Stejně jako umožňuje parametrizované testování jednotek, IntelliTest také umožňuje parametrizované napodobení.

Parametrizované napodobení mají dva různé režimy spuštění:

  • výběr: při zkoumání kódu, parametrizovaných napodobení jsou zdrojem dalších testovacích vstupů a IntelliTest se pokusí zvolit zajímavé hodnoty.
  • replay: Při provádění dříve generovaného testu se parametrizované napodobení chovají jako zástupné procedury s chováním (jinými slovy předdefinované chování).

Pomocí PexChoose získejte hodnoty pro parametrizované napodobení.

Struktury

Odůvodnění IntelliTestu o hodnotách struktury je podobné způsobu, jakým se zabývá objekty.

Pole a řetězce

IntelliTest monitoruje spuštěné instrukce, protože spouští test a program pod testem. Zejména sleduje, kdy program závisí na délce řetězce nebo pole (a dolních mezích a délkách multidimenzionálního pole). Také sleduje, jak program používá různé prvky řetězce nebo pole. Pak pomocí řešitele omezení určí, které délky a hodnoty prvků můžou způsobit test a program v rámci testu se chovat zajímavými způsoby.

IntelliTest se pokouší minimalizovat velikost polí a řetězců potřebných k aktivaci zajímavého chování programu.

Získání dalších vstupů

Statickou třídu PexChoose lze použít k získání dalších vstupů testu a lze ji použít k implementaci parametrizovaných napodobení.

Máte zpětnou vazbu?

Své nápady a žádosti o funkce můžete zadávat na webu Developer Community.