xUnit - 显示理论成员数据的测试名称(TestCase)

时间:2017-10-14 20:43:14

标签: c# asp.net .net asp.net-core xunit

我一直在使用NUnit进行测试,而且我非常喜欢测试用例。在NUnit中,您可以使用TestCaseData类中的SetName函数轻松地在测试用例中设置每个测试名称。

xUnit是否具有类似的功能?

目前我只能在测试资源管理器中看到一个测试,即使我在测试用例中有6个测试。

xUnit test

public class LogHandler : TestBase
{
    private ILogger _logger;

    public LogHandler()
    {
        //Arrange
        LogAppSettings logAppSettings = GetAppSettings<LogAppSettings>("Log");

        IOptions<LogAppSettings> options = Options.Create(logAppSettings);

        LogService logService = new LogService(new Mock<IIdentityService>().Object, options);

        LogProvider logProvider = new LogProvider(logService);

        _logger = logProvider.CreateLogger(null);
    }

    public static IEnumerable<object[]> TestCases => new[]
    {
        new object[] { LogLevel.Critical,
            new EventId(),
            new Exception(),
            1 },
        new object[] { LogLevel.Error,
            new EventId(),
            new Exception(),
            1 },
        new object[] { LogLevel.Warning,
            new EventId(),
            new Exception(),
            0 },
        new object[] { LogLevel.Information,
            new EventId(),
            new Exception(),
            0 },
        new object[] { LogLevel.Debug,
            new EventId(),
            new Exception(),
            0 },
        new object[] { LogLevel.Trace,
            new EventId(),
            new Exception(),
            0 },
        new object[] { LogLevel.None,
            new EventId(),
            new Exception(),
            0 }
    };

    [Theory, MemberData(nameof(TestCases))]
    public void Test(LogLevel logLevel, EventId eventId, Exception exception, int count)
    {
        //Act
        _logger.Log<object>(logLevel, eventId, null, exception, null);

        //Assert
        int exceptionCount = Database.Exception.Count();

        Assert.Equal(exceptionCount, count);
    }
}

xUnit测试窗口

enter image description here

这里应该进行6次测试,而不是一次! (忽略GetOrganisationStatuses)。

NUnit测试用例

public static IEnumerable TestDatabaseCases
{
    get
    {
        yield return new TestCaseData(LogLevel.Critical,
            new EventId(1),
            new Exception("Exception"),
            0,
            1).SetName("InsertException_Should_Insert_When_LogLevel_Critical");

        yield return new TestCaseData(LogLevel.Error,
            new EventId(1),
            new Exception("Exception"),
            0,
            1).SetName("InsertException_Should_Insert_When_LogLevel_Error");

        yield return new TestCaseData(LogLevel.Warning,
            new EventId(1),
            new Exception("Exception"),
            0,
            0).SetName("InsertException_Should_Not_Insert_When_LogLevel_Warning");

        yield return new TestCaseData(LogLevel.Information,
            new EventId(1),
            new Exception("Exception"),
            0,
            0).SetName("InsertException_Should_Not_Insert_When_LogLevel_Information");

        yield return new TestCaseData(LogLevel.Debug,
            new EventId(1),
            new Exception("Exception"),
            0,
            0).SetName("InsertException_Should_Not_Insert_When_LogLevel_Debug");
    }
}

NUnit测试窗口

enter image description here

这就是我想要的xUnit!

我如何在xUnit中为测试用例中的每个测试设置一个名称?

3 个答案:

答案 0 :(得分:6)

  

目前我只能在测试资源管理器中看到一个测试,即使我在测试用例中有6个测试。

这是因为xUnit.net不会将您的测试数据视为可序列化的。请参阅此问题:https://github.com/xunit/xunit/issues/1473

显着的细节是:

  

简短回答

     

如果你的某些理论数据不能被xUnit.net“序列化”,那么   它不能封装到测试用例的序列化中   我们需要为Visual Studio测试运行器做。

     

答案很长

     

在Visual Studio测试运行器中,可以在一个测试用例中发现测试用例   过程,并在另一个执行。因此,测试用例必须能够   变成一个不合格的字符串表示(又名,   “序列化”)以便运行。我们也可以在测试中序列化   方法级别,因为这只涉及知道类型和方法   名称(两个字符串)。当你开始将数据放入混合中时,我们需要   确保我们知道如何序列化这些数据;如果我们不能序列化   理论数据的 所有 ,然后我们必须回归到一个方法(我们知道我们可以序列化)。

完整的答案包含更多细节。

  

在NUnit中,您可以使用TestCaseData类中的SetName函数轻松地在测试用例中设置每个测试名称。

     

xUnit是否具有类似的功能?

目前还没有。

答案 1 :(得分:1)

实际上有一个工作解决方案需要一些管道代码,这些代码可以在未更改的测试中使用。它需要实现自定义TheoryAttribute,自定义TheoryDiscoverer和自定义TestCase类。整个解决方案在此回购DjvuNet/DjvuNet.Shared.Tests的MIT许可下可用。

具有实现的必需文件是: DjvuTheoryAttributeDjvuTheoryDiscovererDjvuNamedDataRowTestCaseDjvuDataRowTestCase

用法很简单:编译上面的文件,将它们直接包含在测试程序集中或作为单独的程序集,并在代码follows中使用它们:

    [DjvuTheory]
    [ClassData(typeof(DjvuJsonDataSource))]
    public void DirmChunk_Theory(DjvuJsonDocument doc, int index)
    {
        int pageCount = 0;
        using (DjvuDocument document = DjvuNet.Tests.Util.GetTestDocument(index, out pageCount))
        {
            DjvuNet.Tests.Util.VerifyDjvuDocument(pageCount, document);
            DjvuNet.Tests.Util.VerifyDjvuDocumentCtor(pageCount, document);

            // DirmChunk is present only in multi page documents
            // in which root form is of DjvmChunk type
            if (document.RootForm.ChunkType == ChunkType.Djvm)
            {
                DirmChunk dirm = ((DjvmChunk)document.RootForm).Dirm;

                Assert.NotNull(dirm);

                Assert.True(dirm.IsBundled ? doc.Data.Dirm.DocumentType == "bundled" : doc.Data.Dirm.DocumentType == "indirect");

                var components = dirm.Components;
                Assert.Equal<int>(components.Count, doc.Data.Dirm.FileCount);
            }
        }
    }

其中一个理论函数参数在xUnit中不可序列化,但尽管理论测试将单独显示并编号。如果理论函数的第一个参数是字符串类型,它将被用作测试的名称,除了作为函数调用的参数。

这个想法归功于其他开发人员 - 我必须找到他的代码的链接 - 但它是从头开始为DjvuNet项目重新实现的。

答案 2 :(得分:-1)

这对我有用:

public class TestScenario
{
...
    public override string ToString()
    {
        return $"Role: {Role}...";
    }
}
    [Theory]
    [ClassData(typeof(MyProvider))]
    public void TestScenarios(TestScenario scenaro)
    {
        TestScenarioInternal(scenaro);

    }