Test de paramétrage dans xUnit.net similaire à NUnit

Y at-il des moyens dans le framework xUnit.net similaires aux fonctionnalités suivantes de NUnit?

[Test, TestCaseSource("CurrencySamples")] public void Format_Currency(decimal value, ssortingng expected){} static object[][] CurrencySamples = new object[][] { new object[]{ 0m, "0,00"}, new object[]{ 0.0004m, "0,00"}, new object[]{ 5m, "5,00"}, new object[]{ 5.1m, "5,10"}, new object[]{ 5.12m, "5,12"}, new object[]{ 5.1234m, "5,12"}, new object[]{ 5.1250m, "5,13"}, // round new object[]{ 5.1299m, "5,13"}, // round } 

Cela générera 8 tests distincts dans l’interface graphique de NUnit

 [TestCase((ssortingng)null, Result = "1")] [TestCase("", Result = "1")] [TestCase(" ", Result = "1")] [TestCase("1", Result = "2")] [TestCase(" 1 ", Result = "2")] public ssortingng IncrementDocNumber(ssortingng lastNum) { return "some"; } 

Cela générera 5 tests distincts et comparera automatiquement les résultats ( Assert.Equal() ).

 [Test] public void StateTest( [Values(1, 10)] int input, [Values(State.Initial, State.Rejected, State.Stopped)] DocumentType docType ){} 

Cela générera 6 tests combinatoires. Inestimable.

Il y a quelques années, j’ai essayé xUnit et je l’ai aimé, mais il manquait ces fonctionnalités. Je ne peux pas vivre sans eux Quelque chose a changé?

xUnit offre un moyen d’exécuter des tests paramétrés à l’ aide de théories de données . Le concept est équivalent à celui trouvé dans NUnit, mais les fonctionnalités que vous obtenez ne sont pas aussi complètes.

Voici un exemple:

 [Theory] [InlineData("Foo")] [InlineData(9)] [InlineData(true)] public void Should_be_assigned_different_values(object value) { Assert.NotNull(value); } 

Dans cet exemple, xUnit exécutera le test Should_format_the_currency_value_correctly une fois pour chaque InlineDataAtsortingbute passant chaque fois la valeur spécifiée en argument.

Les théories de données constituent un point d’extensibilité que vous pouvez utiliser pour créer de nouveaux moyens d’exécuter vos tests paramétrés. La façon dont cela se fait est en créant de nouveaux atsortingbuts qui inspectent et éventuellement agissent sur les arguments et la valeur de retour des méthodes de test.

Vous pouvez trouver un bon exemple pratique de la manière dont les théories de données de xUnit peuvent être étendues dans les théories AutoData et InlineAutoData d’AutoFixture .

Permettez-moi de jeter un autre échantillon ici, juste au cas où cela permettrait de gagner du temps pour quelqu’un.

 [Theory] [InlineData("goodnight moon", "moon", true)] [InlineData("hello world", "hi", false)] public void Contains(ssortingng input, ssortingng sub, bool expected) { var actual = input.Contains(sub); Assert.Equal(expected, actual); } 

Sur votre première demande, vous pouvez suivre les exemples trouvés ici .

Vous pouvez construire une classe statique contenant les données nécessaires à une collection de tests

 using System.Collections.Generic; namespace PropertyDataDrivenTests { public static class DemoPropertyDataSource { private static readonly List _data = new List { new object[] {1, true}, new object[] {2, false}, new object[] {-1, false}, new object[] {0, false} }; public static IEnumerable TestData { get { return _data; } } } } 

Ensuite, en utilisant l’atsortingbut MemberData, définissez le test en tant que tel

 public class TestFile1 { [Theory] [MemberData("TestData", MemberType = typeof(DemoPropertyDataSource))] public void SampleTest1(int number, bool expectedResult) { var sut = new CheckThisNumber(1); var result = sut.CheckIfEqual(number); Assert.Equal(result, expectedResult); } } 

ou si vous utilisez C # 6.0,

 [Theory] [MemberData(nameof(PropertyDataDrivenTests.TestData), MemberType = typeof(DemoPropertyDataSource))] 

Le premier argument de MemberDataAtsortingbute vous permet de définir le membre que vous utilisez en tant que source de données. Vous disposez donc d’une grande souplesse en matière de réutilisation.

J’ai trouvé une bibliothèque qui produit des fonctionnalités équivalentes à l’atsortingbut [Values] de NUnit appelé Xunit.Combinatorial :

Il vous permet de spécifier des valeurs au niveau des parameters:

 [Theory, CombinatorialData] public void CheckValidAge([CombinatorialValues(5, 18, 21, 25)] int age, bool friendlyOfficer) { // This will run with all combinations: // 5 true // 18 true // 21 true // 25 true // 5 false // 18 false // 21 false // 25 false } 

Ou vous pouvez implicitement déterminer le nombre minimal d’invocations pour couvrir toutes les combinaisons possibles:

 [Theory, PairwiseData] public void CheckValidAge(bool p1, bool p2, bool p3) { // Pairwise generates these 4 test cases: // false false false // false true true // true false true // true true false } 

J’ai pris en compte toutes les réponses ici et j’ai TheoryData<,> les types génériques de XUnit TheoryData<,> pour me donner des définitions de données sécurisées simples et faciles à lire pour l’atsortingbut ‘MemberData’ lors de mon test, comme dans cet exemple:

 /// must be public & static for MemberDataAttr to use public static TheoryData DataForTest1 = new TheoryData { { 1, true, "First" }, { 2, false, "Second" }, { 3, true, "Third" } }; [Theory(DisplayName = "My First Test"), MemberData(nameof(DataForTest1))] public void Test1(int valA, bool valB, ssortingng valC) { Debug.WriteLine($"Running {nameof(Test1)} with values: {valA}, {valB} & {valC} "); } 

Trois tests ont été observés à partir de l'explorateur de tests pour «Mon premier test»


NB: Utilisation de VS2017 (15.3.3), C # 7 et XUnit 2.2.0 pour .NET Core

Selon cet article dans xUnit, vous avez trois options de “paramétrage”:

  1. InlineData
  2. ClassData
  3. MemberData

Exemple InlineData

 [Theory] [InlineData(1, 2)] [InlineData(-4, -6)] [InlineData(2, 4)] public void FooTest(int value1, int value2) { Assert.True(value1 + value2 < 7) } 

Exemple ClassData

 public class BarTestData : IEnumerable { public IEnumerator GetEnumerator() { yield return new object[] { 1, 2 }; yield return new object[] { -4, -6 }; yield return new object[] { 2, 4 }; } IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } [Theory] [ClassData(typeof(BarTestData))] public void BarTest(int value1, int value2) { Assert.True(value1 + value2 < 7) } 

MemberData exemple

 [Theory] [MemberData(nameof(BazTestData))] public void BazTest(int value1, int value2) { Assert.True(value1 + value2 < 7) } public static IEnumerable BazTestData => new List { new object[] { 1, 2 }, new object[] { -4, -6 }, new object[] { 2, 4 }, };