C# xUnit 测试监听器。

7
我正在基于.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#中我不太确定。

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

我在注册这个项目时遇到了麻烦,也不确定是否正确地注册了它。就示例而言,我已经找到了实际的消息接收器,但也找到了实际的测试状态数据,我不太确定该如何使用。


你在Edit 1中的目标是监听“测试通过”的消息吗?我会更新我的答案来演示... - xander
是的,我的总体目标是能够基于不同的测试状态和测试事件执行一些操作。使用您的示例,我可以抽象出粗略的if / else方法并实现更好的方式。如果您愿意,您可以更新示例,为未来的人展示更多测试状态,例如passed、skipped、failed、started、finished等等。通用示例相同,使用接口 ITestFailed ITestSkipped 等。 - Nick
1个回答

6

我没有使用过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注册该sink:

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 命名空间 中有一些现有的实现。 AssemblyRunner.cs 还演示了将不同事件类型分派到各个处理程序的一种可能方法。
编辑 1
我已更新 MyMessageSink 的实现(上面),以演示如何监听 ITestPassed 消息。我还更新了嵌入在该代码片段中的链接--之前的链接是针对实现的,但我们应该确实使用这些抽象。 if (message is IMessageType) 模式相当简单粗暴,如果要监听许多不同的消息类型,它将不会很好地扩展。由于我不知道您的需求,我只使用了可能起作用的最简单的方法--希望它足以使您改进/扩展它以适应您的需求。

那我基本上只需运行测试程序,自动发现消息接收器就行了? - Nick
抱歉,我不小心编辑了你的答案而不是我的问题。请忽略这个编辑。 - Nick
@xander,你在这里给出了一个很棒的答案,我认为我能够使用它。但是我对这句话有些困惑:“所涉及的所有接口都有良好的文档记录。” 网站https://xunit.net在让我开始使用XUnit方面做得非常好,但是当我尝试寻找像这样的问题的答案时,我无法在网上找到任何API文档,也没有https://github.com/xunit/xunit上的Wiki页面。我认为代码中的文档会通过文档生成工具运行,并在某个地方发布在线上。我错过了什么? - John Chesshir
1
我指的是源代码中包含的XML注释。Visual Studio将它们呈现为工具提示,并在“F12”进入方法/类/接口定义后显示它们在反编译的代码中。这只是我的解释,但似乎xUnit维护者选择主要在线记录意图,并仅在代码中记录实现细节。这样可以节省他们在维护网站方面的大量开销,同时确保我们始终查看正在运行的代码的确切版本的文档。 - xander
在我看来,只有当xunit运行器就位时,自动发现才能正常工作。例如,当从Rider运行测试时,IRunnerReporter将被忽略... 有人找到了让它在Rider中工作的方法吗? - vmachacek
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接