Pregunta Parametrización de prueba en xUnit.net similar a NUnit


¿Hay algún medio en el marco xUnit.net similar a las siguientes características de 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
}

Esto generará 8 pruebas separadas en 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"; }

Esto generará 5 pruebas separadas y automáticamente comparará los resultados (Assert.Equal())

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

Esto generará 6 pruebas combinatorias. No tiene precio.

Hace algunos años, probé xUnit y me encantó, pero carecía de estas características. No puedo vivir sin ellos ¿Ha cambiado algo?


75
2018-02-02 10:07


origen


Respuestas:


xUnit ofrece una forma de correr pruebas parametrizadas a través de algo llamado teorías de datos. El concepto es equivalente al que se encuentra en NUnit, pero la funcionalidad que obtienes de la caja no es tan completa.

Aquí hay un ejemplo:

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

En este ejemplo, xUnit ejecutará Should_format_the_currency_value_correctly prueba una vez por cada InlineDataAttribute cada vez que pasa el valor especificado como argumento.

Las teorías de datos son una punto de extensibilidad que puede usar para crear nuevas formas de ejecutar sus pruebas parametrizadas. La forma en que esto se hace es por creando nuevos atributos que inspeccionan y opcionalmente actúan sobre los argumentos y el valor de retorno de los métodos de prueba.

Puede encontrar un buen ejemplo práctico de cómo se pueden extender las teorías de datos de xUnit en AutoFixturees AutoData y InlineAutoData teorías


100
2018-02-02 10:21



Déjame arrojar una muestra más aquí, en caso de que ahorre algo de tiempo a alguien.

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

39
2018-04-11 00:48



En su primera solicitud, puede seguir los ejemplos encontrados aquí.

Puede construir una clase estática que contenga los datos necesarios para una colección de pruebas

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

Luego, utilizando el atributo MemberData, defina la prueba como tal

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

o si estás usando C # 6.0,

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

El primer argumento de MemberDataAttribute le permite definir el miembro que utiliza como fuente de datos, por lo que tiene una buena cantidad de flexibilidad en la reutilización.


13
2017-12-19 13:03



Encontré una biblioteca que produce una funcionalidad equivalente a la de NUnit [Values] atributo llamado Xunit.Combinatorial:

Le permite especificar valores de nivel de parámetro:

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

O implícitamente puede deducir el número mínimo de invocaciones para cubrir todas las combinaciones posibles:

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

4
2018-05-14 21:23



Tomé todas las respuestas aquí y también hice uso de XUnit TheoryData<,> tipos genéricos para darme definiciones simples, fáciles de leer y tipo de datos seguros para el atributo 'MemberData' en mi prueba, según este ejemplo:

/// 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'


NB Usar VS2017 (15.3.3), C # 7 y XUnit 2.2.0 para .NET Core


3
2017-09-05 09:23



De acuerdo a Este artículo en xUnit tiene tres opciones de "parametrización":

  1. InlineData
  2. ClassData
  3. MemberData

Ejemplo de InlineData

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

Ejemplo de 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)
}

Ejemplo de 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 },
    };

1
2017-07-04 11:25