wake-up-neo.com

Testparametrierung in xUnit.net ähnlich NUnit

Gibt es Mittel im xUnit.net-Framework, die den folgenden Funktionen von NUnit ähneln?

[Test, TestCaseSource("CurrencySamples")]
public void Format_Currency(decimal value, string 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
}

Dadurch werden 8 separate Tests in der NUnit-GUI generiert

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

Dadurch werden 5 separate Tests generiert und die Ergebnisse automatisch verglichen (Assert.Equal()).

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

Dies erzeugt 6 kombinatorische Tests. Unbezahlbar.

Vor ein paar Jahren habe ich xUnit ausprobiert und war begeistert, aber es fehlten diese Funktionen. Kann nicht ohne sie leben. Hat sich etwas geändert?

89
UserControl

xUnit bietet die Möglichkeit, parametrisierte Tests durch sogenannte Datentheorien . Das Konzept entspricht dem in NUnit, aber die Funktionalität, die Sie sofort erhalten, ist nicht so vollständig.

Hier ist ein Beispiel:

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

In diesem Beispiel führt xUnit den Should_format_the_currency_value_correctly - Test einmal pro InlineDataAttribute durch, wenn der angegebene Wert als Argument übergeben wird.

Datentheorien sind ein Erweiterbarkeitspunkt, mit dem Sie neue Möglichkeiten zum Ausführen Ihrer parametrisierten Tests erstellen können. Dies geschieht durch Erstellen neuer Attribute , die die Argumente und den Rückgabewert der Testmethoden überprüfen und optional darauf reagieren.

Ein gutes praktisches Beispiel dafür, wie xUnits Datentheorien erweitert werden können, finden Sie in AutoFixtureAutoData und InlineAutoData Theorien.

124

Lassen Sie mich hier noch eine Probe werfen, für den Fall, dass jemand etwas Zeit spart.

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

Folgen Sie bei Ihrer ersten Anfrage den Beispielen hier .

Sie können eine statische Klasse erstellen, die die Daten enthält, die für eine Sammlung von Tests erforderlich sind

using System.Collections.Generic;

namespace PropertyDataDrivenTests
{
    public static class DemoPropertyDataSource
    {
        private static readonly List<object[]> _data = new List<object[]>
            {
                new object[] {1, true},
                new object[] {2, false},
                new object[] {-1, false},
                new object[] {0, false}
            };

        public static IEnumerable<object[]> TestData
        {
            get { return _data; }
        }
    }
}

Definieren Sie dann den Test mithilfe des Attributs MemberData als solchen

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);
    }
}

oder wenn Sie C # 6.0 verwenden,

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

Mit dem ersten Argument von MemberDataAttribute können Sie das Element definieren, das Sie als Datenquelle verwenden, sodass Sie bei der Wiederverwendung ein angemessenes Maß an Flexibilität haben.

18
LewisM

Ich habe eine Bibliothek gefunden, die die gleiche Funktionalität bietet wie NUnits [Values] Attribut namens Xunit.Combinatorial :

Hier können Sie Werte auf Parameterebene angeben:

[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
}

Oder Sie können implizit die minimale Anzahl von Aufrufen ermitteln lassen, um alle möglichen Kombinationen abzudecken:

[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
}
9
Adam

Laut dieser Artikel in xUnit haben Sie drei "Parametrisierungs" -Optionen:

  1. InlineData
  2. ClassData
  3. MemberData

InlineData-Beispiel

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

ClassData-Beispiel

public class BarTestData : IEnumerable<object[]>
{
    public IEnumerator<object[]> 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-Beispiel

[Theory]
[MemberData(nameof(BazTestData))]
public void BazTest(int value1, int value2)
{
    Assert.True(value1 + value2 < 7)
}

public static IEnumerable<object[]> BazTestData => new List<object[]>
    {
        new object[] { 1, 2 },
        new object[] { -4, -6 },
        new object[] { 2, 4 },
    };
8
itim

Ich habe hier alle Antworten berücksichtigt und zusätzlich XUnits TheoryData<,> generische Typen, um mir einfache, leicht zu lesende und sichere Datendefinitionen für das Attribut 'MemberData' in meinem Test zu geben, wie im folgenden Beispiel dargestellt:

/// must be public & static for MemberDataAttr to use
public static TheoryData<int, bool, string> DataForTest1 = new TheoryData<int, bool, string> {
    { 1, true, "First" },
    { 2, false, "Second" },
    { 3, true, "Third" }
};

[Theory(DisplayName = "My First Test"), MemberData(nameof(DataForTest1))]
public void Test1(int valA, bool valB, string valC)
{
    Debug.WriteLine($"Running {nameof(Test1)} with values: {valA}, {valB} & {valC} ");
}

Three tests runs observed from test Explorer for 'My First Test'


Hinweis: Verwenden von VS2017 (15.3.3), C # 7 und XUnit 2.2.0 für .NET Core
6
Peter