首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XUnit.net在运行后立即捕获每个测试的结果。

XUnit.net在运行后立即捕获每个测试的结果。
EN

Stack Overflow用户
提问于 2015-04-21 16:51:04
回答 1查看 3.9K关注 0票数 7

我试图使用XUnit.net作为自定义的本地测试调度程序的替代品。国产调度程序的一个特点是,对于长期运行的测试,它会在测试通过/失败后将测试结果(pass/fails,以及导致失败的异常)输出到数据库。

因为可能有大量长时间运行的测试,这对于查看运行过程中的测试进度非常有用(不要等到看到所有测试结果时才能看到完整的测试通过,因为完整的测试通过可能需要时间)。

XUnit.net源代码在这里:https://github.com/xunit/xunit

我看了一下BeforeAfterTestAttribute,但是"After“方法不能访问测试结果,只允许访问测试方法。我想要类似的东西,但也可以访问测试结果,这样我就可以立即向数据库报告结果(而不必等待整个测试套件完成)。

从源代码来看,唯一能够访问实际测试结果的是TestRunner,但据我所知,测试运行程序没有可扩展性模型。

我想出的一个可能的解决办法是:

代码语言:javascript
复制
[Fact]
TestMethod()
{
    //This method takes a lambda, handles exceptions, uploads to my
    //database, and then rethrows.
    RunTestWithExtraLogging(() => 
    {
        //Actual test goes here
    }
}

但是,上面的解决方案并不理想,因为它要求每个测试的作者调用"RunTestWithExtraLogging“方法。

PS:我愿意考虑一个不同的测试框架(除了xUnit.net),如果它支持这个.

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-04-21 17:07:26

是的,我相信你需要创造你自己的跑步者。下面提供了一个简单的示例,说明如何做到这一点(您需要在TestMethodRunnerCallback方法中添加所需的逻辑:

代码语言:javascript
复制
namespace MyTestRunner
{
    using System;
    using System.Linq;
    using Xunit;        

    public class Program
    {
        public static int Main(string[] args)
        {
            var testAssembly = TestAssemblyBuilder.Build(
                new ExecutorWrapper(args[0], null, false));

            var tests = testAssembly.EnumerateTestMethods(x =>  x
                .DisplayName
                .ToLowerInvariant();

            var testMethods = (args.Length > 1 && !string.IsNullOrEmpty(args[1])
                ? tests.Contains(args[1].ToLowerInvariant())).ToList()
                : tests.ToList();

            if (testMethods.Count == 0)
                return 0;

            var runnerCallback = new TestMethodRunnerCallback();
            testAssembly.Run(testMethods, runnerCallback);

            return runnerCallback.FailedCount;
        }

        public class TestMethodRunnerCallback : ITestMethodRunnerCallback
        {
            public int FailedCount { get; private set; }

            public void AssemblyFinished(TestAssembly testAssembly, int total, int failed, int skipped, double time)
            {
                FailedCount = failed;
            }

            public void AssemblyStart(TestAssembly testAssembly)
            {
            }

            public bool ClassFailed(TestClass testClass, string exceptionType, string message, string stackTrace)
            {
                return true;
            }

            public void ExceptionThrown(TestAssembly testAssembly, Exception exception)
            {
            }

            public bool TestFinished(TestMethod testMethod)
            {
                return true;
            }

            public bool TestStart(TestMethod testMethod)
            {
                return true;
            }
        }
    }
}

编辑:--似乎在xUnit.net 2.0中,TestAssemblyBuilder已经被XunitFrontController取代了。下面的代码片段显示了如何在测试运行时捕获测试通过的结果:

代码语言:javascript
复制
public class Program
{
    public static void Main(string[] args)
    {
        string assemblyPath = @"path";
        XunitFrontController controller = new XunitFrontController(
            assemblyPath);

        TestAssemblyConfiguration assemblyConfiguration = new TestAssemblyConfiguration();

        ITestFrameworkDiscoveryOptions discoveryOptions = TestFrameworkOptions.ForDiscovery(assemblyConfiguration);
        ITestFrameworkExecutionOptions executionOptions = TestFrameworkOptions.ForExecution(assemblyConfiguration);

        IMessageSink messageSink = new CustomTestMessageVisitor<ITestMessage>();

        Console.WriteLine("Running tests");

        controller.RunAll(
            messageSink: messageSink,
            discoveryOptions: discoveryOptions,
            executionOptions: executionOptions);
    }
}

public class CustomTestMessageVisitor<T> : TestMessageVisitor<T> where T : ITestMessage
{
    protected override bool Visit(ITestFinished message)
    {
        Console.WriteLine("Test {0} finished.",
            message.Test.DisplayName);
        return true;
    }

    protected override bool Visit(ITestPassed message)
    {
        Console.WriteLine("Test {0} passed", message.Test.DisplayName);
        return true;
    }

    protected override bool Visit(ITestFailed message)
    {
        StringBuilder stringBuilder = new StringBuilder();
        foreach (string exceptionType in message.ExceptionTypes)
        {
            stringBuilder.AppendFormat("{0}, ", exceptionType);
        }

        Console.WriteLine("Test {0} failed with {1}", 
            message.Test.DisplayName, 
            stringBuilder.ToString());
        return true;
    }
}
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29778512

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档