Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
IntelliTest genererar indata för parametriserade enhetstester genom att analysera grenvillkoren i programmet. Testindata väljs baserat på om de kan utlösa nya förgreningsbeteenden för programmet. Analysen är en inkrementell process. Den förfinar ett predikat q: I -> {true, false} över de formella testindataparametrarna I.
q representerar den uppsättning beteenden som IntelliTest redan har observerat. Inledningsvis , q := falseeftersom ingenting ännu har observerats.
Stegen i loopen är:
IntelliTest bestämmer indata
isådana attq(i)=falsegenom att använda en begränsningslösare. Efter konstruktion tar indataien körningsväg som inte setts tidigare. Inledningsvis innebär det attikan vara vilken indata som helst, eftersom ingen körningssökväg ännu inte har upptäckts.IntelliTest kör testet med den valda indatan
ioch övervakar körningen av testet och programmet som testas.Under programmets körning tar programmet en viss sökväg som bestäms av alla villkorssatser i programmet. Uppsättningen med alla villkor som avgör körningen kallas sökvägsvillkoret, skrivet som predikat
p: I -> {true, false}över de formella indataparametrarna. IntelliTest beräknar en representation av det här predikatet.IntelliTest ställer in
q := (q or p). Med andra ord registrerar den det faktum att den har sett sökvägen som representeras avp.Gå till steg 1.
IntelliTests begränsningslösare kan hantera värden av alla typer som kan visas i .NET-program:
IntelliTest filtrerar ut indata som bryter mot angivna antaganden.
Förutom omedelbara indata (argument för parameteriserade enhetstester) kan ett test hämta ytterligare indatavärden från den statiska klassen PexChoose . Alternativen avgör också beteendet för parametriserade modeller.
Begränsningslösare
IntelliTest använder en begränsningslösare för att fastställa relevanta indatavärden för ett test och programmet som testas.
IntelliTest använder Z3-villkorslösaren.
Dynamisk kodtäckning
Som en bieffekt av exekveringsövervakningen samlar IntelliTest in data om dynamisk kodtäckning. Detta kallas dynamiskt eftersom IntelliTest bara vet om kod som har körts, därför kan det inte ge absoluta värden för täckning på samma sätt som andra täckningsverktyg brukar göra.
När IntelliTest till exempel rapporterar dynamisk täckning som 5/10 grundläggande block innebär det att fem block av tio täcktes, där det totala antalet block i alla metoder som hittills har nåtts av analysen (i motsats till alla metoder som finns i sammansättningen som testas) är tio. Senare i analysen, när mer åtkomliga metoder identifieras, kan både täljaren (5 i det här exemplet) och nämnaren (10) öka.
Heltal och flyttal
IntelliTests begränsningslösare bestämmer testindatavärden för primitiva typer som byte, int, float och andra för att utlösa olika körningsvägar för testet och programmet som testas.
Objects
IntelliTest kan antingen skapa instanser av befintliga .NET-klasser, eller så kan du använda IntelliTest för att automatiskt skapa falska objekt som implementerar ett specifikt gränssnitt och beter sig på olika sätt beroende på användning.
Instansiera befintliga klasser
Vad är problemet?
IntelliTest övervakar de utförda instruktionerna när det kör ett test och programmet under test. I synnerhet övervakar den all åtkomst till fält. Den använder sedan en begränsningslösare för att fastställa nya testindata, inklusive objekt och deras fältvärden, så att testet och programmet som testas fungerar på andra intressanta sätt.
Det innebär att IntelliTest måste skapa objekt av vissa typer och ange sina fältvärden. Om klassen är synlig och har en synlig standardkonstruktor kan IntelliTest skapa en instans av klassen. Om alla fält i klassen är synliga kan IntelliTest ange fälten automatiskt.
Om typen inte visas eller om fälten inte visas behöver IntelliTest hjälp med att skapa objekt och föra in dem i intressanta tillstånd för att uppnå maximal kodtäckning. IntelliTest kan använda reflektion för att skapa och initiera instanser på godtyckliga sätt, men det är vanligtvis inte önskvärt eftersom det kan försätta objektet i ett tillstånd som aldrig kan inträffa under normal programkörning. I stället förlitar sig IntelliTest på tips från användaren.
Synlighet
.NET har en detaljerad synlighetsmodell: typer, metoder, fält och andra medlemmar kan vara privata, offentliga, interna med mera.
När IntelliTest genererar tester försöker den endast utföra åtgärder (till exempel anropa konstruktorer, metoder och inställningsfält) som är lagliga när det gäller .NET-synlighetsregler inifrån kontexten för de genererade testerna.
Reglerna är följande:
Synlighet för interna medlemmar
- IntelliTest förutsätter att de genererade testerna har åtkomst till interna medlemmar som var synliga för den omslutande PexClass. .NET har InternalsVisibleToAttribute för att utöka synligheten för interna medlemmar till andra sammansättningar.
Synlighet för privata och familjemedlemmar (skyddade i C#) i PexClass
- IntelliTest placerar alltid de genererade testerna direkt i PexClass eller i en underklass. Därför förutsätter IntelliTest att det kan använda alla synliga familjemedlemmar (skyddade i C#).
- Om de genererade testerna placeras direkt i PexClass (vanligtvis med hjälp av partiella klasser) förutsätter IntelliTest att det också kan använda alla privata medlemmar i PexClass.
Synlighet för offentliga medlemmar
- IntelliTest förutsätter att den kan använda alla exporterade medlemmar som visas i kontexten för PexClass.
Parametriserade mocks
Hur testar jag en metod som har en parameter av en gränssnittstyp? Eller av en icke-förseglad klass? IntelliTest vet inte vilka implementeringar som ska användas senare när den här metoden anropas. Och kanske finns det inte ens en verklig implementering tillgänglig vid testtillfället.
Det konventionella svaret är att använda falska objekt med explicit beteende.
Ett simulerat objekt implementerar ett gränssnitt (eller utökar en icke-förseglad klass). Den representerar inte en verklig implementering, utan bara en genväg som tillåter körning av tester med hjälp av det falska objektet. Dess beteende definieras manuellt som en del av varje testfall där det används. Det finns många verktyg som gör det enkelt att definiera falska objekt och deras förväntade beteende, men det här beteendet måste fortfarande definieras manuellt.
I stället för hårdkodade värden i falska objekt kan IntelliTest generera värdena. På samma sätt som det möjliggör parametriserad enhetstestning aktiverar IntelliTest även parametriserade modeller.
Parametriserade mock-objekt har två olika exekveringslägen:
- välj: när du utforskar kod är parametriserade modeller en källa till ytterligare testindata, och IntelliTest försöker välja intressanta värden
- replay: när du kör ett tidigare genererat test beter sig parametriserade modeller som stubs med beteende (med andra ord fördefinierat beteende).
Använd PexChoose för att hämta värden för parametriserade mocks.
Strukturer
IntelliTests resonemang om struct-värden liknar hur det hanterar objekt.
Matriser och strängar
IntelliTest övervakar de utförda instruktionerna när det kör ett test och programmet under test. I synnerhet observeras när programmet är beroende av längden på en sträng eller en matris (och de lägre gränserna och längderna för en flerdimensionell matris). Den visar också hur programmet använder de olika elementen i en sträng eller matris. Den använder sedan en begränsningslösare för att avgöra vilka längder och elementvärden som kan leda till att testet och programmet som testas beter sig på intressanta sätt.
IntelliTest försöker minimera storleken på de matriser och strängar som krävs för att utlösa intressanta programbeteenden.
Hämta ytterligare indata
Den statiska klassen PexChoose kan användas för att hämta ytterligare indata till ett test och kan användas för att implementera parametriserade modeller.
Fick du feedback?
Publicera dina idéer och funktionsförfrågningar i Utvecklarcommunityn.