Тестовая параметризация в xUnit.net похожа на NUnit
Есть ли какие-либо средства в инфраструктуре 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
}
Это приведет к созданию 8 отдельных тестов в графическом интерфейсе NUnit
[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 и любил его, но ему не хватало этих функций. Не может жить без них. Что-то изменилось?
Ответы
Ответ 1
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_correctly
один раз для каждого InlineDataAttribute
, каждый раз передавая указанное значение в качестве аргумента.
Теории данных - это точка расширяемости, которую вы можете использовать для создания новых способов запуска ваших параметризованных тестов. То, как это делается, - это создание новых атрибутов, которые проверяют и опционально действуют на аргументы и возвращают значения методов тестирования.
Вы можете найти хороший практический пример того, как теории данных xUnit могут быть расширены в AutoFixture AutoData и InlineAutoData.
Ответ 2
Позвольте мне бросить еще один образец здесь, на случай, если кому-то это поможет.
[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);
}
Ответ 3
По первому запросу вы можете следовать приведенным примерам здесь.
Вы можете построить статический класс, содержащий данные, необходимые для коллекции тестов
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);
}
}
или если вы используете С# 6.0,
[Theory]
[MemberData(nameof(PropertyDataDrivenTests.TestData), MemberType = typeof(DemoPropertyDataSource))]
Первый аргумент MemberDataAttribute позволяет вам определить член, который вы используете в качестве источника данных, поэтому у вас есть достаточная гибкость при повторном использовании.
Ответ 4
Я нашел библиотеку, которая создает эквивалентную функциональность для атрибута NUnit [Values]
, называемого Xunit.Combinatorial:
Он позволяет указать значения уровня параметра:
[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
}
Ответ 5
Я взял на себя все ответы здесь и дополнительно использовал 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} ");
}
![Три тестовых прогона, наблюдаемых в тестовом проводнике для]()
<ч/" > NB Использование VS2017 (15.3.3), С# 7 и XUnit 2.2.0 для .NET Core