Panoramica di Microsoft IntelliTest

IntelliTest consente di trovare tempestivamente i bug e riduce i costi di manutenzione dei test. Grazie a un approccio automatizzato e trasparente, IntelliTest è in grado di generare un gruppo di test candidato per il codice .NET. La generazione del gruppo di test può essere definita ulteriormente mediante la specifica di proprietà di correttezza. IntelliTest sviluppa anche il gruppo di test in modo automatico seguendo l'evoluzione del codice sottoposto a test.

Nota

IntelliTest è disponibile solo in Enterprise Edition. È supportato per il codice C# destinato a .NET Framework. Per il supporto di .NET 6 con IntelliTest, installare la versione di anteprima di Visual Studio Enterprise e vedere l'annuncio .

Test di caratterizzazione IntelliTest consente di determinare il comportamento del codice in termini di un gruppo di unit test tradizionali. Questo gruppo di test può essere usato come gruppo di regressione e contribuire a ridurre la complessità associata al refactoring di codice legacy o poco noto.

Generazione guidata di input di test IntelliTest usa un approccio di analisi del codice aperto e risoluzione vincoli per generare automaticamente valori di input di test precisi, in genere senza richiedere l'intervento dell'utente. Per i tipi di oggetto complessi genera automaticamente factory. È possibile orientare la generazione di input di test estendendo e configurando le factory per soddisfare esigenze specifiche. Le proprietà di correttezza specificate come asserzioni nel codice vengono usate automaticamente per guidare ulteriormente la generazione di input di test.

Integrazione nell'IDE IntelliTest è completamente integrato nell'IDE di Visual Studio. Tutte le informazioni raccolte durante la generazione del gruppo di test (ad esempio gli input generati automaticamente, l'output del codice, i test case generati e il loro stato pass o fail) vengono visualizzate nell'IDE di Visual Studio. È possibile alternare facilmente tra la correzione del codice e una nuova esecuzione di IntelliTest senza chiudere l'IDE di Visual Studio. I test possono essere salvati nella soluzione come progetto unit test e vengono rilevati automaticamente in seguito da Esplora test di Visual Studio.

Integrare le procedure di test esistenti È possibile usare IntelliTest per integrare le procedure di test già applicate.

Per testare:

  • Algoritmi su dati primitivi o matrici di dati primitivi:
  • Algoritmi su dati complessi, ad esempio il compilatore:
    • far generare a IntelliTest una rappresentazione astratta dei dati, quindi sottoporla all'algoritmo
    • far creare istanze a IntelliTest mediante la creazione oggetti personalizzata e gli invariant di dati, quindi chiamare l'algoritmo
  • Contenitori di dati:
  • Una codebase esistente:

Hello World di IntelliTest

IntelliTest trova gli input rilevanti per il programma testato, il che significa che è possibile usarlo per generare la famosa stringa Hello World! . A tale scopo è necessario aver creato un progetto di test C# basato su MSTest e avere aggiunto un riferimento a Microsoft.Pex.Framework. Se si usa un framework di test diverso, creare una libreria di classi C# e fare riferimento alla documentazione del framework di test su come configurare il progetto.

Nell'esempio seguente vengono creati due vincoli sul parametro denominato value in modo che IntelliTest generi la stringa richiesta:

using System;
using Microsoft.Pex.Framework;
using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public partial class HelloWorldTest {
    [PexMethod]
    public void HelloWorld([PexAssumeNotNull]string value) {
        if (value.StartsWith("Hello")
            && value.EndsWith("World!")
            && value.Contains(" "))
            throw new Exception("found it!");
    }
}

Dopo la compilazione e l'esecuzione IntelliTest genera un set di test come il seguente:

  1. ""
  2. "\0\0\0\0\0"
  3. "Salve"
  4. "\0\0\0\0\0\0"
  5. "Hello\0"
  6. "Hello\0\0"
  7. "Hello\0World!"
  8. "Hello World!"

Nota

Per i problemi di compilazione, provare a sostituire i riferimenti a Microsoft.VisualStudio.TestPlatform.TestFramework e Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions con un riferimento a Microsoft.VisualStudio.QualityTools.UnitTestFramework.

Leggere Generare unit test con IntelliTest per capire dove vengono salvati i test generati. Il codice di test generato deve includere un test come il seguente:

[TestMethod]
[PexGeneratedBy(typeof(global::HelloWorldTest))]
[PexRaisedException(typeof(Exception))]
public void HelloWorldThrowsException167()
{
    this.HelloWorld("Hello World!");
}

È facile!

Risorse aggiuntive:

Attributi importanti

using Microsoft.Pex.Framework;

[..., PexClass(typeof(Foo))]
public partial class FooTest {
    [PexMethod]
    public void Bar([PexAssumeNotNull]Foo target, int i) {
        target.Bar(i);
    }
}
[assembly: PexAssemblyUnderTest("MyAssembly")] // also instruments "MyAssembly"
[assembly: PexInstrumentAssembly("Lib")]

Classi helper statiche importanti

  • PexAssume valuta i presupposti (filtro di input)
  • PexAssert valuta le asserzioni
  • PexChoose genera nuove scelte (input aggiuntivi)
  • PexObserve registra i valori in tempo reale nei test generati
[PexMethod]
void StaticHelpers(Foo target) {
    PexAssume.IsNotNull(target);

    int i = PexChoose.Value<int>("i");
    string result = target.Bar(i);

    PexObserve.ValueForViewing<string>("result", result);
    PexAssert.IsNotNull(result);
}

Limiti

In questa sezione vengono descritte le limitazioni di IntelliTest:

Non determinismo

IntelliTest presuppone che il programma analizzato sia deterministico. In caso contrario, IntelliTest scorre fino a raggiungere un limite di esplorazione.

IntelliTest considera un programma non determistico se si basa su input che IntelliTest non può controllare.

IntelliTest controlla gli input specificati a unit test con parametri e ottenuti da PexChoose. In tal senso, i risultati delle chiamate a codice non gestito o nonstrumentato vengono considerati anche "input" al programma instrumentato, ma IntelliTest non può controllarli. Se il flusso di controllo del programma dipende da valori specifici provenienti da queste origini esterne, IntelliTest non può "indirizzare" il programma verso aree rilevate in precedenza.

Il programma è considerato non deterministico anche quando i valori provenienti da origini esterne cambiano alla successiva esecuzione del programma stesso. In questi casi IntelliTest non mantiene il controllo dell'esecuzione del programma e la ricerca diventa inefficiente.

A volte non è ovvio quando questo accade. Vedi gli esempi seguenti:

  • Il risultato del metodo GetHashCode() viene fornito dal codice non gestito e non è prevedibile.
  • La classe System.Random usa l'ora di sistema corrente per specificare valori realmente casuali.
  • La classe System.DateTime fornisce l'ora corrente, che non è sotto il controllo di IntelliTest.

Concorrenza

IntelliTest non gestisce programmi multithreading.

Codice nativo

IntelliTest non riconosce il codice nativo, ad esempio le istruzioni x86 chiamate tramite P/Invoke. Non è in grado di tradurre le chiamate di questo tipo in vincoli che possono essere passati al risolutore di vincoli. Anche nel caso del codice .NET IntelliTest può analizzare solo il codice che ha instrumentato. IntelliTest non è in grado di instrumentare determinate parti di mscorlib, inclusa la libreria di reflection. DynamicMethod non può essere instrumentato.

Come soluzione alternativa è consigliabile configurare una modalità di test in cui tali metodi risiedono in tipi in un assembly dinamico. Tuttavia, anche se alcuni metodi non sono strutturati, IntelliTest tenta di coprire la maggior parte del codice instrumentato possibile.

Piattaforma

IntelliTest è supportato solo su .NETFramework X86 a 32 bit.

Lingua

In linea di principio IntelliTest può analizzare programmi .NET arbitrari, scritti in qualsiasi linguaggio .NET. Tuttavia in Visual Studio IntelliTest supporta solo C#.

Ragionamento simbolico

IntelliTest usa un risolutore di vincoli automatico per determinare quali valori sono rilevanti per il test e il programma sottoposto a test. Tuttavia le capacità del risolutore di vincoli sono e saranno sempre limitate.

Analisi dello stack non corrette

Poiché IntelliTest rileva e "rigenera" le eccezioni in ogni metodo instrumentato, i numeri di riga nelle tracce dello stack non saranno corretti. Questa è una limitazione intrinseca dell'istruzione "rethrow".