我正在建立一个基于.Net Core的硒测试框架,团队决定使用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);
}
}
我在注册此密码时遇到问题,或者我什至没有正确注册它。就示例而言,我发现了实际的消息接收器,但也发现了我不确定如何使用的实际测试状态数据。
答案 0 :(得分:1)
我没有使用TestNG,但是我做了一些快速阅读,并且认为我明白你在追求什么。
为了演示,我实现了一个非常基本的概念验证xUnit IMessageSink
。
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还演示了一种将不同事件类型分配给各个处理程序的可能方法。
我已经更新了MyMessageSink
的实现(上面),以演示如何收听ITestPassed
消息。我还更新了该代码段中嵌入的链接-先前的链接是有关实现的,但是我们确实应该使用这些抽象。
if (message is IMessageType)
模式非常粗糙,如果您想收听许多不同的消息类型,则无法很好地扩展。由于我不知道您的需求,因此我只介绍了可能可行的最简单的方法-希望您可以对其进行改进/扩展以满足您的需求。