Per impostazione predefinita, i test nunit vengono eseguiti in ordine alfabetico. Qualcuno sa come impostare l'ordine di esecuzione? Esiste un attributo per questo?
Per impostazione predefinita, i test nunit vengono eseguiti in ordine alfabetico. Qualcuno sa come impostare l'ordine di esecuzione? Esiste un attributo per questo?
Risposte:
Ciascuno dei tuoi unit test dovrebbe essere in grado di essere eseguito in modo indipendente e autonomo. Se soddisfano questo criterio, l'ordine non ha importanza.
Tuttavia, ci sono occasioni in cui vorresti prima eseguire determinati test. Un tipico esempio è in una situazione di integrazione continua in cui alcuni test sono più in esecuzione di altri. Usiamo l'attributo category in modo da poter eseguire i test che usano il mocking prima dei test che usano il database.
cioè mettilo all'inizio dei tuoi test rapidi
[Category("QuickTests")]
Se sono presenti test che dipendono da determinate condizioni ambientali, considera gli attributi TestFixtureSetUp e TestFixtureTearDown , che consentono di contrassegnare i metodi da eseguire prima e dopo i test.
Voglio solo sottolineare che mentre la maggior parte degli intervistati pensava che si trattasse di test unitari, la domanda non specificava che lo fossero.
nUnit è un ottimo strumento che può essere utilizzato per una varietà di situazioni di test. Riesco a vedere le ragioni appropriate per voler controllare l'ordine di prova.
In quelle situazioni ho dovuto ricorrere a incorporare un ordine di esecuzione nel nome del test. Sarebbe fantastico poter specificare l'ordine di esecuzione utilizzando un attributo.
001_first_test
002_second_test
e così via?
NUnit 3.2.0 ha aggiunto un file OrderAttribute
, vedere:
https://github.com/nunit/docs/wiki/Order-Attribute
Esempio:
public class MyFixture
{
[Test, Order(1)]
public void TestA() { ... }
[Test, Order(2)]
public void TestB() { ... }
[Test]
public void TestC() { ... }
}
Volere che i test vengano eseguiti in un ordine specifico non significa che i test dipendano l'uno dall'altro: al momento sto lavorando a un progetto TDD ed essendo un bravo TDDer ho deriso / stubbato tutto, ma sarebbe è più leggibile se potessi specificare l'ordine di visualizzazione dei risultati dei test - tematicamente invece che alfabeticamente. Finora l'unica cosa a cui posso pensare è anteporre a_ b_ c_ alle classi a classi, spazi dei nomi e metodi. (Non carino) Penso che un attributo [TestOrderAttribute] sarebbe carino - non strettamente seguito dal framework, ma un suggerimento in modo che possiamo ottenere questo risultato
Indipendentemente dal fatto che i test dipendano o meno dall'ordine ... alcuni di noi vogliono semplicemente controllare tutto, in modo ordinato.
Gli unit test vengono generalmente creati in ordine di complessità. Quindi, perché non dovrebbero essere eseguiti anche in ordine di complessità o nell'ordine in cui sono stati creati?
Personalmente, mi piace vedere i test eseguiti nell'ordine in cui li ho creati. In TDD, ogni test successivo sarà naturalmente più complesso e richiederà più tempo per essere eseguito. Preferirei vedere il test più semplice fallire prima in quanto sarà un indicatore migliore della causa del fallimento.
Ma posso anche vedere il vantaggio di eseguirli in ordine casuale, soprattutto se vuoi verificare che i tuoi test non abbiano dipendenze da altri test. Che ne dici di aggiungere un'opzione per testare i corridori a "Esegui test in modo casuale fino all'arresto"?
Sto testando con Selenium su un sito web abbastanza complesso e l'intera suite di test può essere eseguita per più di mezz'ora, e non sono ancora vicino a coprire l'intera applicazione. Se devo assicurarmi che tutti i moduli precedenti siano compilati correttamente per ogni test, questo aggiunge molto tempo, non solo una piccola quantità di tempo, al test complessivo. Se c'è troppo sovraccarico per eseguire i test, le persone non li eseguiranno tutte le volte che dovrebbero.
Quindi, li metto in ordine e dipendo dai test precedenti per avere caselle di testo e simili completati. Uso Assert.Ignore () quando le pre-condizioni non sono valide, ma ho bisogno che vengano eseguite in ordine.
Mi piace molto la risposta precedente.
L'ho modificato un po 'per poter utilizzare un attributo per impostare l'intervallo di ordini:
namespace SmiMobile.Web.Selenium.Tests
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using NUnit.Framework;
public class OrderedTestAttribute : Attribute
{
public int Order { get; set; }
public OrderedTestAttribute(int order)
{
Order = order;
}
}
public class TestStructure
{
public Action Test;
}
class Int
{
public int I;
}
[TestFixture]
public class ControllingTestOrder
{
private static readonly Int MyInt = new Int();
[TestFixtureSetUp]
public void SetUp()
{
MyInt.I = 0;
}
[OrderedTest(0)]
public void Test0()
{
Console.WriteLine("This is test zero");
Assert.That(MyInt.I, Is.EqualTo(0));
}
[OrderedTest(2)]
public void ATest0()
{
Console.WriteLine("This is test two");
MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(2));
}
[OrderedTest(1)]
public void BTest0()
{
Console.WriteLine("This is test one");
MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(1));
}
[OrderedTest(3)]
public void AAA()
{
Console.WriteLine("This is test three");
MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(3));
}
[TestCaseSource(sourceName: "TestSource")]
public void MyTest(TestStructure test)
{
test.Test();
}
public IEnumerable<TestCaseData> TestSource
{
get
{
var assembly =Assembly.GetExecutingAssembly();
Dictionary<int, List<MethodInfo>> methods = assembly
.GetTypes()
.SelectMany(x => x.GetMethods())
.Where(y => y.GetCustomAttributes().OfType<OrderedTestAttribute>().Any())
.GroupBy(z => z.GetCustomAttribute<OrderedTestAttribute>().Order)
.ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());
foreach (var order in methods.Keys.OrderBy(x => x))
{
foreach (var methodInfo in methods[order])
{
MethodInfo info = methodInfo;
yield return new TestCaseData(
new TestStructure
{
Test = () =>
{
object classInstance = Activator.CreateInstance(info.DeclaringType, null);
info.Invoke(classInstance, null);
}
}).SetName(methodInfo.Name);
}
}
}
}
}
}
OrderedTest
non è più supportato in NUnit 3.
So che questo è un post relativamente vecchio, ma ecco un altro modo per mantenere il tuo test in ordine SENZA rendere i nomi dei test imbarazzanti. Utilizzando l'attributo TestCaseSource e facendo in modo che l'oggetto che passi abbia un delegato (Action), puoi non solo controllare totalmente l'ordine, ma anche nominare il test di cosa si tratta.
Questo funziona perché, secondo la documentazione, gli elementi nella raccolta restituiti dall'origine del test verranno sempre eseguiti nell'ordine in cui sono elencati.
Ecco una demo di una presentazione che farò domani:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
namespace NUnitTest
{
public class TestStructure
{
public Action Test;
}
class Int
{
public int I;
}
[TestFixture]
public class ControllingTestOrder
{
private static readonly Int MyInt= new Int();
[TestFixtureSetUp]
public void SetUp()
{
MyInt.I = 0;
}
[TestCaseSource(sourceName: "TestSource")]
public void MyTest(TestStructure test)
{
test.Test();
}
public IEnumerable<TestCaseData> TestSource
{
get
{
yield return new TestCaseData(
new TestStructure
{
Test = () =>
{
Console.WriteLine("This is test one");
MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(1));
}
}).SetName(@"Test One");
yield return new TestCaseData(
new TestStructure
{
Test = () =>
{
Console.WriteLine("This is test two");
MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(2));
}
}).SetName(@"Test Two");
yield return new TestCaseData(
new TestStructure
{
Test = () =>
{
Console.WriteLine("This is test three");
MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(3));
}
}).SetName(@"Test Three");
}
}
}
}
TestCaseSource
come un modo per eseguire test ordinati è un colpo di genio. Molto bene. Ho adottato questo approccio insieme a quello di seguito e ho aggiunto alcune modifiche aggiuntive per renderlo più facile da usare. Vedi i link nella mia risposta per ulteriori informazioni, ma l'idea di fondo è da questa ottima risposta!
TestCaseSource
deve essere statica, il che preclude l'utilizzo di pattern. Bummer.
TestCaseSource
deve essere un oggetto statico in NUnit 3, altrimenti i test non verranno eseguiti. E non puoi creare oggetti dinamici all'interno di un oggetto statico. Ecco perché non funzionerà in v. 3.
Sto lavorando con i test case dell'interfaccia utente end-to-end Selenium WebDriver scritti in C #, che vengono eseguiti utilizzando il framework NUnit. (Non casi unitari in quanto tali)
Questi test dell'interfaccia utente dipendono certamente dall'ordine di esecuzione, poiché altri test devono aggiungere alcuni dati come condizione preliminare. (Non è possibile eseguire i passaggi in ogni test)
Ora, dopo aver aggiunto il decimo scenario di test, vedo che NUnit vuole essere eseguito in questo ordine: Test_1 Test_10 Test_2 Test_3 ..
Quindi immagino di dover alfabetizzare troppo i nomi dei casi di test per ora, ma sarebbe bene avere questa piccola funzione di controllo dell'ordine di esecuzione aggiunta a NUnit.
Di solito Unit Test dovrebbe essere indipendente, ma se è necessario, è possibile denominare i metodi in ordine alfabetico es:
[Test]
public void Add_Users(){}
[Test]
public void Add_UsersB(){}
[Test]
public void Process_Users(){}
oppure puoi farlo ..
private void Add_Users(){}
private void Add_UsersB(){}
[Test]
public void Process_Users()
{
Add_Users();
Add_UsersB();
// more code
}
a_
b_
t1_
, t2_
invece o ti affidi a caratteri finali facili da perdere
Ci sono ottime ragioni per utilizzare un meccanismo di ordinazione dei test. La maggior parte dei miei test utilizza buone pratiche come installazione / smontaggio. Altri richiedono enormi quantità di configurazione dei dati, che possono quindi essere utilizzati per testare una serie di funzionalità. Fino ad ora, ho utilizzato test di grandi dimensioni per gestire questi test di integrazione (Selenium Webdriver). Tuttavia, penso che il post suggerito sopra su https://github.com/nunit/docs/wiki/Order-Attribute abbia molto merito. Ecco un esempio del motivo per cui ordinare sarebbe estremamente prezioso:
Questo tempo di attesa di 10 minuti rallenta la suite di test. Quando si moltiplicano ritardi di memorizzazione nella cache simili in una moltitudine di test, si consuma molto tempo. Ordinare i test potrebbe consentire di eseguire la configurazione dei dati come un "Test" all'inizio della suite di test, con i test che si basano sul busting della cache eseguiti verso la fine dell'esecuzione del test.
Questa domanda è davvero vecchia ora, ma per le persone che potrebbero raggiungerla dalla ricerca, ho preso le eccellenti risposte da user3275462 e PvtVandals / Rico e le ho aggiunte a un repository GitHub insieme ad alcuni dei miei aggiornamenti. Ho anche creato un post sul blog associato con alcune informazioni aggiuntive che puoi guardare per maggiori informazioni.
Spero che questo sia utile per tutti voi. Inoltre, spesso mi piace utilizzare l'attributo Category per differenziare i miei test di integrazione o altri test end-to-end dai miei unit test effettivi. Altri hanno sottolineato che gli unit test non dovrebbero avere una dipendenza dall'ordine, ma altri tipi di test spesso lo fanno, quindi questo fornisce un bel modo per eseguire solo la categoria di test che desideri e anche ordinare quei test end-to-end.
Sono sorpreso che la comunità di NUnit non abbia escogitato nulla, quindi sono andato a creare qualcosa di simile da solo.
Attualmente sto sviluppando una libreria open source che ti consente di ordinare i tuoi test con NUnit. È possibile ordinare apparecchiature di prova e ordinare "specifiche di prova ordinate" allo stesso modo.
La libreria offre le seguenti funzionalità:
La libreria è effettivamente ispirata al modo in cui MSTest esegue i test di ordinamento con i .orderedtest
file. Si prega di guardare un esempio di seguito.
[OrderedTestFixture]
public sealed class MyOrderedTestFixture : TestOrderingSpecification {
protected override void DefineTestOrdering() {
TestFixture<Fixture1>();
OrderedTestSpecification<MyOtherOrderedTestFixture>();
TestFixture<Fixture2>();
TestFixture<Fixture3>();
}
protected override bool ContinueOnError => false; // Or true, if you want to continue even if a child test fails
}
Se stai usando [TestCase]
, l'argomento TestName
fornisce un nome per il test.
Se non specificato, viene generato un nome in base al nome del metodo e agli argomenti forniti.
È possibile controllare l'ordine di esecuzione del test come indicato di seguito:
[Test]
[TestCase("value1", TestName = "ExpressionTest_1")]
[TestCase("value2", TestName = "ExpressionTest_2")]
[TestCase("value3", TestName = "ExpressionTest_3")]
public void ExpressionTest(string v)
{
//do your stuff
}
Qui ho usato il "ExpressionTest"
suffisso del nome del metodo con un numero.
È possibile utilizzare qualsiasi nome in ordine alfabetico, vedere Attributo TestCase
Non dovresti dipendere dall'ordine in cui il framework di test seleziona i test per l'esecuzione.I test dovrebbero essere isolati e indipendenti. In quanto non dovrebbero dipendere da altri test che preparano il terreno per loro o che puliscono dopo di loro. Dovrebbero anche produrre lo stesso risultato indipendentemente dall'ordine di esecuzione dei test (per una data istantanea del SUT)
Ho cercato su Google. Come al solito, alcune persone hanno fatto ricorso a trucchi subdoli (invece di risolvere il problema di testabilità / progettazione sottostante
Vedi anche: caratteristiche di un buon test
In caso di utilizzo TestCaseSource
della chiave è override string ToString
metodo, come funziona:
Supponi di avere la classe TestCase
public class TestCase
{
public string Name { get; set; }
public int Input { get; set; }
public int Expected { get; set; }
}
E un elenco di casi di prova:
private static IEnumerable<TestCase> TestSource()
{
return new List<TestCase>
{
new TestCase()
{
Name = "Test 1",
Input = 2,
Expected = 4
},
new TestCase()
{
Name = "Test 2",
Input = 4,
Expected = 16
},
new TestCase()
{
Name = "Test 3",
Input = 10,
Expected = 100
}
};
}
Ora usiamolo con un metodo di test e vediamo cosa succede:
[TestCaseSource(nameof(TestSource))]
public void MethodXTest(TestCase testCase)
{
var x = Power(testCase.Input);
x.ShouldBe(testCase.Expected);
}
Questo non verrà testato in ordine e l'output sarà come questo:
Quindi se aggiungessimo override string ToString
alla nostra classe come:
public class TestCase
{
public string Name { get; set; }
public int Input { get; set; }
public int Expected { get; set; }
public override string ToString()
{
return Name;
}
}
Il risultato cambierà e otteniamo l'ordine e il nome del test come:
Nota: