测试失败时,XUnit输出更多信息

时间:2019-04-07 23:35:25

标签: c# unit-testing xunit.net

有人知道XUnit测试失败时如何向输出中添加其他信息吗?我认为这将是一件有用的事情。例如,我正在处理测试文件,我想看看哪个失败了。

This Question具有有关使用ITestOutputHelper的信息,但这仅用于在成功运行测试期间打印信息。

2 个答案:

答案 0 :(得分:0)

如果您要让xUnit将结果写入xml文件,例如,通过在命令行中告诉xUnit编写XML结果文件,则可以对XML文件中的结果进行后处理,以获取有关失败的更多详细信息,只需一点C#代码(或插入您喜欢的语言代替C#,例如Python,Java等。

尽管问题似乎在于哪个测试用例失败,对于数据驱动的测试还是在给定输入文件的情况下进行的测试,但是写入XML结果文件的任何内容都是公平的,并且可用于此方法。因此,如果引发了故障异常,并且您有测试用例标识信息可用于包含在异常中,则应将其捕获到XML结果文件中。

这是一些用C#进行此操作的代码示例。此代码的局限性在于,它只希望XML中“ assemblies”节点下有一个程序集。

public void ReadResultsXmlFile(string testResultsXmlFile)
{
    using (MyXmlTextReader = new XmlTextReader(testResultsXmlFile))
    {
        testResultXmlDocument = new XmlDocument();
        testResultXmlDocument.Load(MyXmlTextReader); // suppose that myXmlString contains "<Names>...</Names>"
        XmlNode xnAssembliesHeader = testResultXmlDocument.SelectSingleNode("/assemblies");
        TestRunDateTime = xnAssembliesHeader.Attributes.GetNamedItem("timestamp").Value;
        XmlNodeList xnAssemblyList = testResultXmlDocument.SelectNodes("/assemblies/assembly");
        foreach (XmlNode assembly in xnAssemblyList)
        {
            XmlNodeList xnTestList = testResultXmlDocument.SelectNodes(
                "/assemblies/assembly/collection/test");
            foreach (XmlNode test in xnTestList)
            {
                TestName = test.Attributes.GetNamedItem("name").Value;
                TestDuration = test.Attributes.GetNamedItem("time").Value;
                PassOrFail = test.Attributes.GetNamedItem("result").Value;
                // Failed test, get the failure information
                if (!(PassOrFail == "Pass"))
                {
                    Passed = false;
                    XmlNode failureData = test.SelectSingleNode("failure");
                    FailureText = failureData.InnerText;
                    StackTrace = failureData.SelectSingleNode("stack-trace").InnerText;
                    FailureMessage = failureData.SelectSingleNode("message").InnerText;
                    Console.WriteLine("Test: {0} Result: {1}  Error: {2}  StackTrace: {3}", TestName, PassOrFail, FailureMessage, FailureStackTrace);
                }
                else
                {
                    Passed = true;
                }
                Console.WriteLine("Test: {0} Result: {1}  Elapsed: {2}", TestName, PassOrFail, TestDuration);
            }
        }
    }
}

大约需要这些声明,例如作为同一个课程的一部分:

public class MyTestAssembly
{
    public string TestName { get; set; }
    public string PassOrFail { get; set; }
    public bool Passed { get; set; }
    public string TestOutcome { get; set; }
    public string AlertLevel { get; set; }  // None, Warning, Alert
    public string AssemblyName { get; set; }
    public string AssemblyPath { get; set; }
    public string TestRunDateTime { get; set; }
    public TimeSpan testDuration;
    public string TestDuration { get; set; }
    public DateTime TestStartTime { get; set; }
    public DateTime TestStopTime { get; set; }
    public string TestResultsXmlFile { get; set; }
    public string FailureMessage { get; set; }
    public string StackTrace { get; set; }
    public string FailureStackTrace { get; set; }
    //todo: Report an error if more than one assembly exists under assemblies node
    public XmlDocument testResultXmlDocument;
    public string FailureText { get; set; }
    private XmlNodeList MyListOfTestAssembliesInResultsFile { get; set; }
    private XmlTextReader MyXmlTextReader;
    public double TestDurationSeconds;
    // And more stuff... this is only a partial example, extracted from working code.
}

我正在使用的XUnit结果文件来自xUnit 2.4.x,.NET Framework,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<assemblies timestamp="05/06/2019 19:06:38">
  <assembly name="C:\Program Files (x86)\RunXUnitTests\TestAssemblies\HRCafeORT.DLL" environment="64-bit .NET 4.0.30319.42000 [collection-per-class, parallel (4 threads)]" test-framework="xUnit.net 2.4.1.0" run-date="2019-05-06" run-time="19:06:30" config-file="C:\Program Files (x86)\RunXUnitTests\TestAssemblies\xunit.console.exe.Config" total="1" passed="0" failed="1" skipped="0" time="7.376" errors="0">
    <errors />
    <collection total="1" passed="0" failed="1" skipped="0" name="Test collection for HRCafeORT.HRCafeWebsiteORTFeature" time="6.814">
      <test name="Ensure Intranet Application HR Cafe is available and working properly." type="HRCafeORT.HRCafeWebsiteORTFeature" method="EnsureIntranetApplicationHRCafeIsAvailableAndWorkingProperly_" time="6.8143311" result="Fail">
        <traits>
          <trait name="FeatureTitle" value="HR Cafe Website ORT" />
          <trait name="Description" value="Ensure Intranet Application HR Cafe is available and working properly." />
          <trait name="Category" value="HRCafe" />
          <trait name="Category" value="IE" />
        </traits>
        <failure exception-type="OpenQA.Selenium.ElementNotInteractableException">
          <message><![CDATA[OpenQA.Selenium.ElementNotInteractableException : Element cannot be interacted with via the keyboard because it is not focusable]]></message>
          <stack-trace><![CDATA[   at OpenQA.Selenium.Remote.RemoteWebDriver.UnpackAndThrowOnError(Response errorResponse)
   at OpenQA.Selenium.Remote.RemoteWebDriver.Execute(String driverCommandToExecute, Dictionary`2 parameters)
   at OpenQA.Selenium.Remote.RemoteWebElement.Execute(String commandToExecute, Dictionary`2 parameters)
   at HRCafeORT.HRCafeWebsiteORTSteps.GivenIHaveSelectedTheLeaveSelection() in C:\AppTest\ORT\HRCafeORT\HRCafeWebsiteORTSteps.cs:line 49
   at TechTalk.SpecFlow.Bindings.BindingInvoker.InvokeBinding(IBinding binding, IContextManager contextManager, Object[] arguments, ITestTracer testTracer, TimeSpan& duration)
   at TechTalk.SpecFlow.Infrastructure.TestExecutionEngine.ExecuteStepMatch(BindingMatch match, Object[] arguments)
   at TechTalk.SpecFlow.Infrastructure.TestExecutionEngine.ExecuteStep(IContextManager contextManager, StepInstance stepInstance)
   at TechTalk.SpecFlow.Infrastructure.TestExecutionEngine.OnAfterLastStep()
   at TechTalk.SpecFlow.TestRunner.CollectScenarioErrors()
   at HRCafeORT.HRCafeWebsiteORTFeature.ScenarioCleanup()
   at HRCafeORT.HRCafeWebsiteORTFeature.EnsureIntranetApplicationHRCafeIsAvailableAndWorkingProperly_() in C:\AppTest\ORT\HRCafeORT\HRCafe.feature:line 14]]></stack-trace>
        </failure>
      </test>
    </collection>
  </assembly>
</assemblies>

用于控制台测试运行程序的典型xUnitConsole命令行如下所示。 -xml后跟输出文件名,指定运行期间要创建的XML结果文件。

"C:\RunXUnitTests\TestAssemblies\xunit.console.exe" "C:\RunXUnitTests\TestAssemblies\HRCafeORT.DLL"  -xml "C:\Users\Public\Documents\TestResults\HRCafeORT.xml"

答案 1 :(得分:0)

失败的测试将引发异常。您可以捕获它们,并使用ITestOutputHelper输出其他信息。

public class AuditCheck
{        
    public AuditCheck(ITestOutputHelper output)
    {
        this.output = output;
    }

    [Fact]
    public void MyTest()
    {
        var expected = 23;
        var actual = 42;
        try
        {
            Assert.Equal(expected, actual);
        }
        catch (XunitException e)
        {
            output.WriteLine($"My own output, like filename, etc. Today is {DateTime.Today.DayOfWeek} and i expected {expected} but got {actual}");
            throw e;
        }
        Assert.Equal(expected, actual);
    }
}

输出被写入日志,并且您可以通过在Visual Studio Test Explorer(Capturing Output)中单击“输出”来查看它:

Visual Studio Test Explorer