Kiểm tra tham số hóa trong xUnit.net tương tự như NUnit


106

Có phương tiện nào trong khuôn khổ xUnit.net tương tự như các tính năng sau của NUnit không?

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

Điều này sẽ tạo ra 8 bài kiểm tra riêng biệt trong NUnit GUI

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

Thao tác này sẽ tạo ra 5 bài kiểm tra riêng biệt và tự động so sánh kết quả ( Assert.Equal()).

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

Điều này sẽ tạo ra 6 bài kiểm tra tổ hợp. Vô giá.

Vài năm trước, tôi đã thử xUnit và yêu thích nó nhưng nó thiếu những tính năng này. Không thể sống thiếu chúng. Có gì đó thay đổi?


Hướng dẫn đầy đủ gửi các đối tượng phức tạp làm tham số cho Phương pháp kiểm tra các loại phức tạp trong Unit test
Iman Bahrampour

Câu trả lời:


138

xUnit cung cấp một cách để chạy các bài kiểm tra tham số hóa thông qua một thứ gọi là lý thuyết dữ liệu . Khái niệm này tương đương với khái niệm được tìm thấy trong NUnit nhưng chức năng bạn nhận được ra khỏi hộp không hoàn chỉnh.

Đây là một ví dụ:

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

Trong ví dụ này, xUnit sẽ chạy Should_format_the_currency_value_correctlythử nghiệm một lần cho InlineDataAttributemỗi lần chuyển giá trị được chỉ định làm đối số.

Lý thuyết dữ liệu là một điểm có thể mở rộng mà bạn có thể sử dụng để tạo ra những cách mới để chạy các bài kiểm tra tham số hóa của mình. Cách thực hiện điều này là bằng cách tạo các thuộc tính mới để kiểm tra và tùy ý hành động dựa trên các đối số và giá trị trả về của các phương thức thử nghiệm.

Bạn có thể tìm thấy một ví dụ thực tiễn tốt về cách lý thuyết dữ liệu xUnit có thể được mở rộng trong AutoFixture 's AutodataInlineAutoData lý thuyết.


3
Rõ ràng, không được phép sử dụng các ký tự thập phân làm tham số thuộc tính.
Sergii Volchkov

1
@RubenBartelink không tìm thấy liên kết của bạn. Thay vào đó hãy truy cập vào đây: blog.benhall.me.uk/2008/01/introduction-to-xunit-net-extensions
Ronnie Overby

9
Bạn sẽ cần xUnit.net: Extensions (NuGet Package) hoặc nếu không thì [Theory]thuộc tính này không khả dụng.
Daniel AA Pelsmaeker

4
Nó sẽ là tuyệt vời nếu nhất-khuyến khuôn khổ kiểm tra đơn vị NET có một số tài liệu ..
Isaac Kleinman

6
Google cho biết câu trả lời SO của bạn LÀ tài liệu xUnit.
nathanchere

55

Hãy để tôi ném thêm một mẫu ở đây, đề phòng nó tiết kiệm thời gian cho ai đó.

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

Bạn quên dấu ngoặc đóng ở dòng thứ 2?
cs0815,

Hữu ích, cảm ơn :)
Zeek2

21

Đối với yêu cầu đầu tiên của bạn, bạn có thể làm theo các ví dụ được tìm thấy ở đây .

Bạn có thể tạo một lớp tĩnh chứa dữ liệu cần thiết cho một bộ sưu tập các bài kiểm tra

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

Sau đó, sử dụng thuộc tính MemberData, xác định bài kiểm tra như vậy

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

hoặc nếu bạn đang sử dụng C # 6.0,

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

Đối số đầu tiên của MemberDataAttribute cho phép bạn xác định thành viên mà bạn sử dụng làm nguồn dữ liệu, vì vậy bạn có thể sử dụng lại một cách linh hoạt.


13

Theo bài viết này trong xUnit, bạn có ba tùy chọn "tham số hóa":

  1. InlineData
  2. ClassData
  3. Dữ liệu thành viên

Ví dụ về InlineData

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

Ví dụ về 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)
}

Ví dụ về dữ liệu thành viên

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

12

Tôi đã tìm thấy một thư viện tạo ra chức năng tương đương với [Values]thuộc tính của NUnit được gọi là Xunit .

Nó cho phép bạn chỉ định các giá trị cấp tham số:

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

Hoặc bạn có thể ngầm hiểu để nó tìm ra số lượng lệnh gọi tối thiểu để bao gồm tất cả các kết hợp có thể có:

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

6

Tôi đã điền vào tất cả các câu trả lời ở đây và sử dụng thêm các TheoryData<,>kiểu chung của XUnit để cung cấp cho tôi các định nghĩa dữ liệu an toàn, đơn giản, dễ đọc và nhập cho thuộc tính 'MemberData' trong bài kiểm tra của tôi, theo ví dụ này:

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

Ba lần chạy thử nghiệm được quan sát từ trình khám phá thử nghiệm cho 'Thử nghiệm đầu tiên của tôi'


NB Sử dụng VS2017 (15.3.3), C # 7 và XUnit 2.2.0 cho .NET Core


Cái này thật đáng yêu.
Brett Rowberry
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.