[c#] NUnit과 유사한 xUnit.net의 테스트 매개 변수화

xUnit.net 프레임 워크에 NUnit의 다음 기능과 유사한 수단이 있습니까?

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

NUnit GUI에서 8 개의 개별 테스트가 생성됩니다.

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

이렇게하면 5 개의 개별 테스트가 생성되고 결과가 자동으로 비교됩니다 ( Assert.Equal()).

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

이것은 6 개의 조합 테스트를 생성합니다. 아주 재미있는.

몇 년 전에 나는 xUnit을 사용해 보았고 그것을 좋아했지만 이러한 기능이 부족했습니다. 그들 없이는 살 수 없습니다. 변경된 사항이 있습니까?



답변

xUnit데이터 이론 이라는 것을 통해 매개 변수화 된 테스트 를 실행하는 방법을 제공합니다 . 이 개념은 NUnit에서 발견 된 것과 동일하지만 기본적으로 제공되는 기능은 완전하지 않습니다.

예를 들면 다음과 같습니다.

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

이 예제에서 xUnit은 지정된 값을 인수로 전달할 Should_format_the_currency_value_correctlyInlineDataAttribute마다 한 번씩 테스트 를 실행합니다 .

데이터 이론은 매개 변수화 된 테스트를 실행하는 새로운 방법을 만드는 데 사용할 수 있는 확장 성 지점 입니다. 이를 수행 하는 방법은 테스트 메서드의 인수 및 반환 값을 검사하고 선택적으로 작동 하는 새 속성만드는 것입니다 .

AutoFixtureAutoDataInlineAutoData 이론 에서 xUnit의 데이터 이론을 확장 할 수있는 방법에 대한 좋은 실용적인 예를 찾을 수 있습니다 .


답변

누군가에게 시간을 절약 할 수 있도록 여기에 샘플을 하나 더 던지겠습니다.

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


답변

첫 번째 요청시 여기에 있는 예를 따를 수 있습니다 .

테스트 모음에 필요한 데이터를 포함하는 정적 클래스를 생성 할 수 있습니다.

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

그런 다음 MemberData 속성을 사용하여 다음과 같이 테스트를 정의하십시오.

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

또는 C # 6.0을 사용하는 경우

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

MemberDataAttribute의 첫 번째 인수를 사용하면 데이터 소스로 사용하는 멤버를 정의 할 수 있으므로 재사용시 상당한 유연성을 갖게됩니다.


답변

xUnit 의이 기사 에 따르면 세 가지 “매개 변수화”옵션이 있습니다.

  1. InlineData
  2. ClassData
  3. MemberData

InlineData 예

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

ClassData 예

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 예

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


답변

Xunit.Combinatorial[Values] 이라는 NUnit의 속성 과 동등한 기능을 생성하는 라이브러리를 찾았 습니다 .

매개 변수 수준 값을 지정할 수 있습니다.

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

또는 가능한 모든 조합을 포함하는 최소 호출 수를 암시 적으로 파악하도록 할 수 있습니다.

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


답변

여기에 모든 답변을 포함하고 추가로 XUnit의 TheoryData<,>제네릭 유형을 사용하여이 예제에 따라 테스트의 ‘MemberData’속성에 대한 간단하고 읽기 쉽고 유형이 안전한 데이터 정의를 제공했습니다.

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

'My First Test'에 대한 테스트 탐색기에서 관찰 된 세 번의 테스트 실행


.NET Core 용 VS2017 (15.3.3), C # 7 및 XUnit 2.2.0을 사용하는 NB


답변