2015-09-21 17 views
6

Ho un test (teoria) che è lento e un sacco di casi di test per questo. Quindi voglio che vengano eseguiti contemporaneamente.Come rendere xUnit per eseguire una teoria parallela?

ho creato un semplice esempio:

[Theory] 
[MyTestData] 
public void MyTheory(int num, int sleep) 
{ 
    Console.WriteLine("{0:HH:mm:ss.ffff} - Starting {1} - Sleeping {2}", DateTime.Now, num, sleep); 
    Thread.Sleep(sleep); 
    Console.WriteLine("{0:HH:mm:ss.ffff} - Finished {1} - Sleeping {2}", DateTime.Now, num, sleep); 
} 

[AttributeUsage(AttributeTargets.Method)] 
public class MyTestDataAttribute : DataAttribute 
{ 
    public override IEnumerable<object[]> GetData(MethodInfo testMethod) 
    { 
     yield return new object[2] { 1, 5000 }; 
     yield return new object[2] { 2, 2000 }; 
     yield return new object[2] { 3, 4000 }; 
    } 
} 

La riga di comando per eseguire il test:

"\packages\xunit.runner.console.2.0.0\tools\xunit.console" "\Projects\xUnitTest\xUnitTest\bin\Debug\xUnitTest.dll" -parallel all > xUnitResult.txt 

E il risultato:

xUnit.net console test runner(64-bit.NET 4.0.30319.42000) 
Copyright(C) 2015 Outercurve Foundation. 

Discovering: xUnitTest 
Discovered: xUnitTest 
Starting: xUnitTest 
21:55:39.0449 - Starting 2 - Sleeping 2000 
21:55:41.0627 - Finished 2 - Sleeping 2000 
21:55:41.0783 - Starting 1 - Sleeping 5000 
21:55:46.0892 - Finished 1 - Sleeping 5000 
21:55:46.0892 - Starting 3 - Sleeping 4000 
21:55:50.0989 - Finished 3 - Sleeping 4000 
Finished: xUnitTest 

=== TEST EXECUTION SUMMARY === 
    xUnitTest Total: 3, Errors: 0, Failed: 0, Skipped: 0, Time: 11,137s 

che è abbastanza serie. Sono sicuro che è possibile farlo parallelo.

+6

https://xunit.github.io/docs/running-tests-in-parallel.html –

+1

Btw, '[MemberData (nameof (MyTestData))]' è più pulito di creare un attributo personalizzato, a mio parere. –

risposta

5

Questo non è attualmente possibile a partire da xUnit 2.1. In base allo parallelization docs,

Per impostazione predefinita, ciascuna classe di test è una raccolta di test univoca. I test all'interno della stessa classe di test non verranno eseguiti in parallelo l'uno contro l'altro.

Quello che i documenti non fanno esplicitamente chiaro è:

  • la più piccola unità "parallelizzabile" in xUnit è una raccolta
  • non c'è modo per le prove nella stessa classe per essere in diversi collezioni

Per estensione, è impossibile avere teorie parallele perché le teorie non possono essere suddivise tra più classi.


Nel vostro caso, questo significa che avete almeno due opzioni:

  • refactoring del codice in prova in modo che tutto ciò che sta prendendo così tanto tempo è astratta distanza. Ad esempio, supponiamo di dover eseguire alcune logiche di business e quindi effettuare una chiamata al database. Se è possibile separare la logica aziendale verificabile in un'altra classe, è possibile eseguire la propria teoria (non in parallelo, ma in < 1 ms) e testare separatamente il codice di accesso ai dati lento.

  • Se si dispone di un numero sufficiente di casi di test, è sufficiente creare una nuova classe per ogni caso di test e utilizzare Fact anziché Theory. Puoi persino metterli tutti in un unico file. È più prolisso e perdi il fattore "cool" dell'uso delle teorie, ma otterrai un'esecuzione parallela.

3

Anche se non direttamente possibile con xUnit, è possibile aggirare il problema se necessario. Con gli svantaggi, come si deve definire manualmente il numero di esecuzioni parallele tramite le classi, quindi se si vuole parallelizzare su due thread, è necessario creare due classi.

public abstract class ParellelTheoryBase 
{ 
    public static List<int> testValues = new List<int> {1, 2, 3, 4, 5, 6}; 
} 

public class ParallelTheory_1of2 : ParellelTheoryBase 
{ 
    public static List<object[]> theoryData = testValues.Where((data, index) => index % 2 == 0).Select(data => new object[] { data }).ToList(); 

    [Theory] 
    [MemberData(nameof(theoryData))] 
    public void DoSomeLongRunningAddition(int data) 
    { 
     Assert.True(data < 7); 
     Thread.Sleep(5000); 
    } 
} 

public class ParallelTheory_2of2 : ParellelTheoryBase 
{ 
    public static List<object[]> theoryData = testValues.Where((data, index) => index % 2 == 1).Select(data => new object[] { data }).ToList(); 

    [Theory] 
    [MemberData(nameof(theoryData))] 
    public void DoSomeLongRunningAddition(int data) 
    { 
     Assert.True(data < 7); 
     Thread.Sleep(5000); 
    } 
} 

In questo esempio, ho definito la struttura in ParellelTheoryBase, che è una classe base per le classi di test attuali. Quindi, ParallelTheory_1of2 e ParallelTheory_2of2 ereditano da quella classe per accedere allo testValues.Ora, loutilizza questo theoryData per l'esecuzione del test e seleziona solo i dati pari o dispari (index % 2 == 1 o index % 2 == 0) dall'elenco.

Si fa prendere in Visual Studio Test Explorer: Visual Studio test explorer

e corre in parallelo:

[xUnit.net 00:00:00.3397963] Starting 
[xUnit.net 00:00:15.5696617] Finished 

questa potrebbe essere una soluzione in cui non è facile sapere in dati di test in anticipo quanto hai. Lo utilizzo, ad esempio, durante l'integrazione, testando un parser di file in cui l'input è qualsiasi file all'interno di una directory e i nuovi file aggiunti verranno raccolti automaticamente per i test.

Nel tuo esempio, penso che potresti facilmente modificare l'attributo MyTestData per accettare i parametri per totalCountParallels e currentIndex.

Problemi correlati