2012-02-02 9 views
67

Esistono mezzi nel framework xUnit.net simili alle seguenti funzionalità di NUnit?Parametrizzazione del test in xUnit.net simile a 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 
} 

Questo genererà 8 prove separate in 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"; } 

Questo genererà 5 prove distinte e confronta i risultati automaticamente (Assert.Equal()).

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

Questo genererà 6 test combinatori. Inestimabile.

Pochi anni fa ho provato xUnit e l'ho adorato ma mancava di queste funzionalità. Non posso vivere senza di loro. Qualcosa è cambiato?

risposta

90

xUnit offre un modo per eseguire i test con parametri attraverso qualcosa chiamato teorie dati. Il concetto è equivalente a quello trovato in NUnit, ma la funzionalità che si ottiene fuori dagli schemi non è completa.

Ecco un esempio:

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

In questo esempio xUnit eseguirà il test Should_format_the_currency_value_correctly volta per ogni InlineDataAttribute ogni volta che passa il valore specificato come argomento.

Le teorie di dati sono un punto di estensibilità che è possibile utilizzare per creare nuovi modi per eseguire i test parametrizzati. Il modo in cui questo viene fatto è da creando nuovi attributi che ispezionano e opzionalmente agiscono sugli argomenti e restituiscono il valore dei metodi di test.

È possibile trovare un buon esempio pratico di come le teorie dei dati di xUnit possono essere estese nelle teorie AutoData e InlineAutoDataAutoFixture.

+3

a quanto pare, è [non consentito] (http://stackoverflow.com/questions/507528/use -decimal-values-as-attribute-params-in-c) da utilizzare valori letterali decimali come parametri degli attributi. –

+1

@RubenBartelink il tuo link non è stato trovato. Vai qui invece: http://blog.benhall.me.uk/2008/01/introduction-to-xunit-net-extensions/ –

+9

Avrai bisogno di _xUnit.net: Extensions_ (pacchetto NuGet) o altrimenti il ​​'[ L'attributo teoria] 'non è disponibile. – Virtlink

34

Lasciami fare un altro esempio qui, nel caso in cui si risparmia un po 'di tempo a qualcuno.

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

Hai dimenticato una parentesi di chiusura nella seconda linea? – cs0815

+0

@csetzkorn hai ragione, grazie! – Sevenate

10

Sulla prima richiesta, è possibile seguire gli esempi trovati here.

È possibile costruire una classe statica che contiene i dati necessari per una raccolta di test

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

Quindi, utilizzando l'attributo MemberData, definire il test in quanto tale

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 se siete utilizzando C# 6.0,

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

Il primo argomento di MemberDataAttribute consente di d Valuta il membro che utilizzi come origine dati, in modo da avere una buona dose di flessibilità sul riutilizzo.

3

ho trovato una libreria che produce funzionalità equivalente all'attributo [Values] di NUnit chiamato Xunit.Combinatorial:

Esso consente di specificare i valori a livello di parametri:

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

Oppure si può implicitamente averlo capire il minimo numero di invocazioni per coprire tutte le possibili combinazioni:

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

Ho preso a bordo tutte le risposte qui a ND uso in aggiunta fatta di TheoryData<,> tipi generici di xUnit di darmi semplice, facile da leggere e definizioni dei dati di sicurezza di tipo per l'attributo 'MemberData' sulla mia prova, come da questo esempio:

/// 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 Utilizzando VS2017 (15.3.3), C# 7, & xUnit 2.2.0 for .NET Nucleo