Par défaut, les tests des unités sont exécutés par ordre alphabétique. Quelqu'un connaît-il un moyen de définir l'ordre d'exécution? Existe-t-il un attribut pour cela?
Par défaut, les tests des unités sont exécutés par ordre alphabétique. Quelqu'un connaît-il un moyen de définir l'ordre d'exécution? Existe-t-il un attribut pour cela?
Réponses:
Vos tests unitaires doivent chacun pouvoir s'exécuter indépendamment et de manière autonome. S'ils satisfont à ce critère, l'ordre n'a pas d'importance.
Il y a des occasions cependant où vous voudrez exécuter certains tests en premier. Un exemple typique est dans une situation d'intégration continue où certains tests durent plus longtemps que d'autres. Nous utilisons l'attribut category pour pouvoir exécuter les tests qui utilisent le mocking avant les tests qui utilisent la base de données.
ie mettez ceci au début de vos tests rapides
[Category("QuickTests")]
Lorsque vous avez des tests qui dépendent de certaines conditions environnementales, considérez les attributs TestFixtureSetUp et TestFixtureTearDown , qui vous permettent de marquer les méthodes à exécuter avant et après vos tests.
Je tiens simplement à souligner que si la plupart des répondants ont supposé qu'il s'agissait de tests unitaires, la question ne précisait pas qu'ils l'étaient.
nUnit est un excellent outil qui peut être utilisé pour une variété de situations de test. Je peux voir les raisons appropriées pour vouloir contrôler l'ordre de test.
Dans ces situations, j'ai dû recourir à l'incorporation d'un ordre d'exécution dans le nom du test. Ce serait formidable de pouvoir spécifier l'ordre d'exécution à l'aide d'un attribut.
001_first_test
002_second_test
et ainsi de suite?
NUnit 3.2.0 a ajouté un OrderAttribute
, voir:
https://github.com/nunit/docs/wiki/Order-Attribute
Exemple:
public class MyFixture
{
[Test, Order(1)]
public void TestA() { ... }
[Test, Order(2)]
public void TestB() { ... }
[Test]
public void TestC() { ... }
}
Vouloir que les tests s'exécutent dans un ordre spécifique ne signifie pas que les tests sont dépendants les uns des autres - je travaille sur un projet TDD en ce moment, et étant un bon TDDer, je me suis moqué / écrasé de tout, mais cela ferait il est plus lisible si je pouvais spécifier l'ordre dans lequel les résultats des tests sont affichés - par thème plutôt que par ordre alphabétique. Jusqu'à présent, la seule chose à laquelle je puisse penser est d'ajouter a_ b_ c_ aux classes aux classes, aux espaces de noms et aux méthodes. (Pas sympa) Je pense qu'un attribut [TestOrderAttribute] serait bien - pas strictement suivi par le framework, mais un indice pour que nous puissions y parvenir
Indépendamment du fait que les tests dépendent ou non de l'ordre ... certains d'entre nous veulent simplement tout contrôler, de manière ordonnée.
Les tests unitaires sont généralement créés par ordre de complexité. Alors, pourquoi ne devraient-ils pas également être exécutés par ordre de complexité ou dans l'ordre dans lequel ils ont été créés?
Personnellement, j'aime voir les tests se dérouler dans l'ordre dans lequel je les ai créés. Dans TDD, chaque test successif sera naturellement plus complexe et prendra plus de temps à s'exécuter. Je préférerais voir le test plus simple échouer en premier car ce sera un meilleur indicateur de la cause de l'échec.
Mais, je peux aussi voir l'avantage de les exécuter dans un ordre aléatoire, surtout si vous voulez tester que vos tests n'ont aucune dépendance avec d'autres tests. Que diriez-vous d'ajouter une option pour tester les coureurs à "Exécuter les tests de manière aléatoire jusqu'à l'arrêt"?
Je teste avec Selenium sur un site web assez complexe et toute la suite de tests peut durer plus d'une demi-heure, et je ne suis pas encore près de couvrir toute l'application. Si je dois m'assurer que tous les formulaires précédents sont correctement remplis pour chaque test, cela ajoute beaucoup de temps, et pas seulement une petite quantité de temps, au test global. S'il y a trop de frais généraux à exécuter les tests, les gens ne les exécuteront pas aussi souvent qu'ils le devraient.
Donc, je les mets en ordre et je dépends des tests précédents pour avoir des zones de texte et autres complétés. J'utilise Assert.Ignore () lorsque les pré-conditions ne sont pas valides, mais je dois les faire fonctionner dans l'ordre.
J'aime vraiment la réponse précédente.
Je l'ai un peu changé pour pouvoir utiliser un attribut pour définir la plage de commande:
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
n'est plus pris en charge dans NUnit 3.
Je sais que c'est un article relativement ancien, mais voici une autre façon de garder votre test dans l'ordre SANS rendre les noms de test gênants. En utilisant l'attribut TestCaseSource et en faisant en sorte que l'objet que vous transmettez ait un délégué (Action), vous pouvez totalement non seulement contrôler l'ordre, mais également nommer le test ce qu'il est.
Cela fonctionne car, selon la documentation, les éléments de la collection renvoyés par la source de test s'exécuteront toujours dans l'ordre dans lequel ils sont répertoriés.
Voici une démo d'une présentation que je donne demain:
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
comme moyen d'exécuter des tests ordonnés est un coup de génie. Bien joué. J'ai adopté cette approche avec celle ci-dessous et ajouté quelques modifications supplémentaires pour la rendre plus facile à utiliser. Voir les liens dans ma réponse pour plus d'informations, mais l'idée sous-jacente vient de cette excellente réponse!
TestCaseSource
doit être statique, ce qui empêche l'utilisation de pattern. Dommage.
TestCaseSource
doit être un objet statique dans NUnit 3, sinon les tests ne s'exécuteront pas. Et vous ne pouvez pas créer d'objets dynamiques dans un objet statique. C'est pourquoi cela ne fonctionnera pas dans la v.3.
Je travaille avec des cas de test d'interface utilisateur de bout en bout Selenium WebDriver écrits en C #, qui sont exécutés à l'aide du framework NUnit. (Pas de cas unitaires en tant que tels)
Ces tests d'interface utilisateur dépendent certainement de l'ordre d'exécution, car d'autres tests doivent ajouter des données comme condition préalable. (Il n'est pas possible de suivre les étapes de chaque test)
Maintenant, après avoir ajouté le 10ème cas de test, je vois que NUnit veut s'exécuter dans cet ordre: Test_1 Test_10 Test_2 Test_3 ..
Donc je suppose que je dois trop alphabétiser les noms des cas de test pour l'instant, mais il serait bon d'avoir cette petite fonctionnalité de contrôle de l'ordre d'exécution ajoutée à NUnit.
Généralement, le test unitaire doit être indépendant, mais si vous le devez, vous pouvez nommer vos méthodes par ordre alphabétique, par exemple:
[Test]
public void Add_Users(){}
[Test]
public void Add_UsersB(){}
[Test]
public void Process_Users(){}
ou vous pouvez le faire ..
private void Add_Users(){}
private void Add_UsersB(){}
[Test]
public void Process_Users()
{
Add_Users();
Add_UsersB();
// more code
}
a_
b_
t1_
, à la t2_
place ou si vous comptez sur des personnages de fin faciles à manquer
Il existe de très bonnes raisons d'utiliser un mécanisme de commande de test. La plupart de mes propres tests utilisent de bonnes pratiques telles que la configuration / le démontage. D'autres nécessitent d'énormes quantités de configuration de données, qui peuvent ensuite être utilisées pour tester une gamme de fonctionnalités. Jusqu'à présent, j'ai utilisé de gros tests pour gérer ces tests d'intégration (Selenium Webdriver). Cependant, je pense que le post suggéré ci-dessus sur https://github.com/nunit/docs/wiki/Order-Attribute a beaucoup de mérite. Voici un exemple de pourquoi la commande serait extrêmement précieuse:
Ce temps d'attente de 10 minutes ralentit la suite de tests. Lorsque vous multipliez des délais de mise en cache similaires sur une multitude de tests, cela prend beaucoup de temps. L'ordonnancement des tests pourrait permettre de configurer les données en tant que «test» dès le début de la suite de tests, les tests reposant sur le buste du cache étant exécutés vers la fin du test.
Cette question est vraiment ancienne maintenant, mais pour les personnes qui peuvent y accéder en recherchant, j'ai pris les excellentes réponses de user3275462 et PvtVandals / Rico et les ai ajoutées à un référentiel GitHub avec certaines de mes propres mises à jour. J'ai également créé un article de blog associé avec des informations supplémentaires que vous pouvez consulter pour plus d'informations.
J'espère que cela vous sera utile à tous. De plus, j'aime souvent utiliser l'attribut Category pour différencier mes tests d'intégration ou d'autres tests de bout en bout de mes tests unitaires réels. D'autres ont souligné que les tests unitaires ne devraient pas avoir de dépendance d'ordre, mais que d'autres types de tests le font souvent, donc cela fournit un moyen agréable d'exécuter uniquement la catégorie de tests que vous souhaitez et de classer ces tests de bout en bout.
Je suis surpris que la communauté NUnit n'ait rien proposé, alors je suis allé créer quelque chose comme ça moi-même.
Je développe actuellement une bibliothèque open-source qui vous permet de commander vos tests avec NUnit. Vous pouvez commander des appareils de test et commander des «spécifications de test ordonnées» de la même manière.
La bibliothèque offre les fonctionnalités suivantes:
La bibliothèque est en fait inspirée de la façon dont MSTest teste l'ordre des .orderedtest
fichiers. Veuillez regarder un exemple ci-dessous.
[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
}
Si vous utilisez [TestCase]
, l'argument TestName
fournit un nom pour le test.
S'il n'est pas spécifié, un nom est généré en fonction du nom de la méthode et des arguments fournis.
Vous pouvez contrôler l'ordre d'exécution des tests comme indiqué ci-dessous:
[Test]
[TestCase("value1", TestName = "ExpressionTest_1")]
[TestCase("value2", TestName = "ExpressionTest_2")]
[TestCase("value3", TestName = "ExpressionTest_3")]
public void ExpressionTest(string v)
{
//do your stuff
}
Ici, j'ai utilisé le "ExpressionTest"
suffixe du nom de la méthode avec un nombre.
Vous pouvez utiliser tous les noms classés par ordre alphabétique, voir Attribut TestCase
Vous ne devez pas dépendre de l'ordre dans lequel le framework de test sélectionne les tests à exécuter. Les tests doivent être isolés et indépendants. En cela, ils ne devraient pas dépendre d'un autre test préparant le terrain pour eux ou nettoyant après eux. Ils doivent également produire le même résultat quel que soit l'ordre d'exécution des tests (pour un instantané donné du SUT)
J'ai fait un peu de recherche sur Google. Comme d'habitude, certaines personnes ont eu recours à des astuces sournoises (au lieu de résoudre le problème de testabilité / conception sous-jacent
Voir aussi: caractéristiques d'un bon test
En cas d'utilisation de TestCaseSource
la clé est la override string ToString
méthode, comment cela fonctionne:
Supposons que vous ayez la classe TestCase
public class TestCase
{
public string Name { get; set; }
public int Input { get; set; }
public int Expected { get; set; }
}
Et une liste de TestCases:
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
}
};
}
Maintenant, utilisons-le avec une méthode de test et voyons ce qui se passe:
[TestCaseSource(nameof(TestSource))]
public void MethodXTest(TestCase testCase)
{
var x = Power(testCase.Input);
x.ShouldBe(testCase.Expected);
}
Cela ne testera pas dans l'ordre et la sortie sera comme ceci:
Donc, si nous avons ajouté override string ToString
à notre classe comme:
public class TestCase
{
public string Name { get; set; }
public int Input { get; set; }
public int Expected { get; set; }
public override string ToString()
{
return Name;
}
}
Le résultat va changer et nous obtenons l'ordre et le nom du test comme:
Remarque: