Uji parameterisasi di xUnit.net mirip dengan NUnit

107

Apakah ada cara dalam kerangka xUnit.net yang mirip dengan fitur NUnit berikut?

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

Ini akan menghasilkan 8 tes terpisah di 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"; }

Ini akan menghasilkan 5 pengujian terpisah dan secara otomatis membandingkan hasil ( Assert.Equal()).

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

Ini akan menghasilkan 6 tes kombinatorial. Tak ternilai.

Beberapa tahun yang lalu saya mencoba xUnit dan menyukainya tetapi tidak memiliki fitur ini. Tidak bisa hidup tanpa mereka. Apakah ada yang berubah?

UserControl
sumber
Panduan lengkap yang mengirimkan objek kompleks sebagai parameter ke Metode pengujian tipe kompleks dalam Pengujian unit
Iman Bahrampour

Jawaban:

139

xUnit menawarkan cara untuk menjalankan pengujian berparameter melalui sesuatu yang disebut teori data . Konsepnya setara dengan yang ditemukan di NUnit tetapi fungsionalitas yang Anda keluarkan tidak selengkap itu.

Berikut contohnya:

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

Dalam contoh ini xUnit akan menjalankan Should_format_the_currency_value_correctlypengujian sekali untuk setiap InlineDataAttributekali meneruskan nilai yang ditentukan sebagai argumen.

Teori data adalah titik perpanjangan yang dapat Anda gunakan untuk membuat cara baru untuk menjalankan pengujian berparameter Anda. Cara melakukannya adalah dengan membuat atribut baru yang memeriksa dan secara opsional bertindak berdasarkan argumen dan nilai kembalian dari metode pengujian.

Anda dapat menemukan contoh praktis yang baik bagaimana teori Data xUnit dapat diperpanjang di AutoFixture 's Autodata dan InlineAutoData teori.

Enrico Campidoglio
sumber
3
Tampaknya, tidak diperbolehkan menggunakan literal desimal sebagai parameter atribut.
Sergii Volchkov
1
@RubenBartelink tautan Anda tidak ditemukan. Buka di sini sebagai gantinya: blog.benhall.me.uk/2008/01/introduction-to-xunit-net-extensions
Ronnie Overby
9
Anda memerlukan xUnit.net: Extensions (Paket NuGet) atau [Theory]atribut tidak tersedia.
Daniel AA Pelsmaeker
4
Akan lebih bagus jika kerangka kerja pengujian unit .NET yang paling direkomendasikan memiliki beberapa dokumentasi ..
Isaac Kleinman
6
Google mengatakan jawaban SO Anda ADALAH dokumentasi xUnit.
nathanchere
55

Izinkan saya membuang satu sampel lagi di sini, kalau-kalau itu menghemat waktu seseorang.

[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);
}
Sevenate
sumber
Apakah Anda lupa tanda kurung tutup di baris ke-2?
cs0815
Berguna, terima kasih :)
Zeek2
21

Pada permintaan pertama Anda, Anda dapat mengikuti contoh yang ditemukan di sini .

Anda dapat membuat kelas statis yang berisi data yang diperlukan untuk kumpulan pengujian

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

Kemudian, dengan menggunakan atribut MemberData, tentukan pengujian seperti itu

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

atau jika Anda menggunakan C # 6.0,

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

Argumen pertama MemberDataAttribute memungkinkan Anda untuk menentukan anggota yang Anda gunakan sebagai sumber data, sehingga Anda memiliki fleksibilitas yang cukup saat digunakan kembali.

LewisM
sumber
13

Menurut artikel ini di xUnit Anda memiliki tiga opsi "parametrization":

  1. InlineData
  2. ClassData
  3. MemberData

Contoh InlineData

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

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

Contoh 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 },
    };
itim
sumber
12

Saya menemukan perpustakaan yang menghasilkan fungsionalitas yang setara dengan [Values]atribut NUnit yang disebut Xunit.Combinatorial :

Ini memungkinkan Anda untuk menentukan nilai tingkat parameter:

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

Atau Anda dapat secara implisit membuatnya mengetahui jumlah minimal pemanggilan untuk mencakup semua kemungkinan kombinasi:

[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
}
Adam
sumber
6

Saya mengambil semua jawaban di sini dan juga memanfaatkan TheoryData<,>tipe generik XUnit untuk memberi saya definisi data yang sederhana, mudah dibaca dan diketik untuk atribut 'MemberData' pada pengujian saya, sesuai contoh ini:

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

Tiga tes berjalan yang diamati dari penjelajah tes untuk 'Tes Pertama Saya'


NB Menggunakan VS2017 (15.3.3), C # 7, & XUnit 2.2.0 untuk .NET Core

Peter
sumber
Ini bagus.
Brett Rowberry