【问题标题】:C# xUnit Test listenersC# xUnit 测试监听器
【发布时间】:2019-07-18 22:45:02
【问题描述】:

我正在构建一个基于 .Net Core 的 selenium 测试框架,团队决定使用 xUnit。一切顺利,一切顺利,但有一段时间以来,我们一直在尝试复制 Java TestNG 侦听器的功能,但运气不佳。

我一直在挖掘 xunit git repo 并发现一些使用诸如ITestListener 之类的接口的实例。在深入挖掘之后,我发现这些监听器来自一个名为 TestDriven.Framework 的包,我想知道如何使用使用这些接口创建的测试监听器?

到目前为止,这是我的简单测试监听器,当测试失败时应该写一些东西:

public class Listener
{
    readonly int totalTests;

    public Listener(ITestListener listener, int totalTests)
    {
        this.totalTests = totalTests;
        TestListener = listener;
        TestRunState = TestRunState.NoTests;
    }

    public ITestListener TestListener { get; private set; }
    public TestRunState TestRunState { get; set; }

    public void onTestFail(ITestFailed args)
    {
        Console.WriteLine(args.Messages);
    }

}

现在,我知道您可以在拆卸钩子中执行此操作,但请记住,这只是一个简单的示例,我想到的是更复杂的东西。所以准确地说,我将在哪里/如何注册测试以使用这个监听器?在 Java TestNg 中我会使用 @Listeners,但在 C# 中我不太确定。

编辑 1 所以该示例工作并设法将其添加到我自己的项目结构中,但是当我尝试使用它时

    class TestPassed : TestResultMessage, ITestPassed
{
    /// <summary>
    /// Initializes a new instance of the <see cref="TestPassed"/> class.
    /// </summary>
    public TestPassed(ITest test, decimal executionTime, string output)
        : base(test, executionTime, output) {
        Console.WriteLine("Execution time was an awesome " + executionTime);
    }
}

我在注册这个时遇到了问题,或者我什至注册正确。就示例而言,我找到了实际的消息接收器,但也找到了我不确定如何使用的实际测试状态数据。

【问题讨论】:

  • 所以您在编辑 1 中的目标是收听“测试通过”消息?我将更新我的答案以证明...
  • 是的,我的总体目标是能够根据不同的测试状态和测试事件做一些事情。使用您的示例,我可以抽象出粗略的 if/else 方法并实现更好的方法。如果您愿意,您可以使用更好的示例为未来的人更新示例,显示更多测试状态,例如通过、跳过、失败、开始、完成等等。一般的例子是相同的使用接口ITestFailedITestSkipped等等

标签: c# .net selenium xunit xunit.net


【解决方案1】:

我没有使用过 TestNG,但我做了一些快速阅读,我认为我知道你在追求什么。

为了演示,我创建了 xUnit [IMessageSink] 接口 (https://github.com/xunit/abstractions.xunit/blob/master/src/xunit.abstractions/Messages/BaseInterfaces/IMessageSink.cs) 的一个非常基本的概念验证实现。

public class MyMessageSink : IMessageSink
{
    public bool OnMessage(IMessageSinkMessage message)
    {
        // Do what you want to in response to events here.
        // 
        // Each event has a corresponding implementation of IMessageSinkMessage.
        // See examples here: https://github.com/xunit/abstractions.xunit/tree/master/src/xunit.abstractions/Messages
        if (message is ITestPassed)
        {
            // Beware that this message won't actually appear in the Visual Studio Test Output console.
            // It's just here as an example. You can set a breakpoint to see that the line is hit.
            Console.WriteLine("Execution time was an awesome " + ((ITestPassed)message).ExecutionTime);
        }

        // Return `false` if you want to interrupt test execution.
        return true;
    }
}

然后通过IRunnerReporter注册接收器:

public class MyRunnerReporter : IRunnerReporter
{
    public string Description => "My custom runner reporter";

    // Hard-coding `true` means this reporter will always be enabled.
    //
    // You can also implement logic to conditional enable/disable the reporter.
    // Most reporters based this decision on an environment variable.
    // Eg: https://github.com/xunit/xunit/blob/cbf28f6d911747fc2bcd64b6f57663aecac91a4c/src/xunit.runner.reporters/TeamCityReporter.cs#L11
    public bool IsEnvironmentallyEnabled => true;
        
    public string RunnerSwitch => "mycustomrunnerreporter";

    public IMessageSink CreateMessageHandler(IRunnerLogger logger)
    {
        return new MyMessageSink();
    }
}

要使用我的示例代码,只需将类复制到您的测试项目中(您还需要添加对xunit.runner.utility NuGet 包的引用)。 xUnit 框架会自动发现IRunnerReporter——无需显式注册任何内容。

如果这看起来方向正确,您可以在 xUnit 源代码中找到更多信息。所有涉及的接口都有详细的文档记录。 xunit.runner.reporters namespace 中有一些现有的实现。 AssemblyRunner.cs 还演示了一种将不同事件类型分派给各个处理程序的可能方法。

编辑 1

我更新了MyMessageSink(上图)的实现,以演示您如何收听ITestPassed 消息。我还更新了嵌入在该代码 sn-p 中的链接——之前的链接指向实现,但我们应该真正使用这些抽象。

if (message is IMessageType) 模式非常粗糙,如果您想监听许多不同的消息类型,则无法很好地扩展。由于我不知道您的需求,所以我只选择了可能可行的最简单的方法——希望您可以改进/扩展它以满足您的需求。

【讨论】:

  • 所以我基本上只是运行测试,它会自动发现消息接收器?
  • 是的。我不知道IRunnerReporter 可以在哪里的确切规则,但我把我的放在测试项目的根目录中,它就可以工作了。
  • 抱歉,不小心编辑了您的答案而不是我的问题。忽略编辑
  • 您是否曾经使用经典的 .net 进行过这项工作?以 net461 为目标的同一项目不会加载 IRunnerReporter。
  • @J.D.Cain 我不记得我测试过的具体是哪个 .NET 版本——自从我开始研究它已经一年多了。我不知道有什么会阻止它在 .NET 4.6 上运行。您可能会在 console 或 msbuild 测试运行器的源代码中找到答案。如果您需要更多帮助,我建议您使用代码示例提出一个新问题。
猜你喜欢
  • 1970-01-01
  • 2014-05-12
  • 1970-01-01
  • 1970-01-01
  • 2018-06-13
  • 1970-01-01
  • 2018-03-17
  • 2019-12-31
  • 2014-11-16
相关资源
最近更新 更多