Xunit:在一种测试方法中执行所有“断言”?

发布于 2024-08-13 22:12:18 字数 1255 浏览 14 评论 0原文

是否可以告诉 xUnit.net 在一个测试方法中执行所有操作,例如 Assert.True() ?基本上,在我们的一些使用/测试用例中,所有断言在逻辑上都属于同一个测试“范围”,我有这样的东西:

    [Fact(DisplayName = "Tr-MissImpl")]
    public void MissingImplementationTest()
    {
        // parse export.xml file
        var exportXml = Libraries.Utilities.XML.GenericClassDeserializer.DeserializeXmlFile<Libraries.MedTrace.ExportXml>(
                ExportXmlFile);

        // compare parsed results with expected ones
        Assert.True(exportXml.ContainsRequirementKeyWithError("PERS_154163", "E0032A"));
        Assert.True(exportXml.ContainsRequirementKeyWithError("PERS_155763", "E0032A"));
        Assert.True(exportXml.ContainsRequirementKeyWithError("PERS_155931", "E0032A"));
        Assert.True(exportXml.ContainsRequirementKeyWithError("PERS_157145", "E0032A"));

        Assert.True(exportXml.ContainsRequirementKeyWithError("s_sw_ers_req_A", "E0032A"));
        Assert.True(exportXml.ContainsRequirementKeyWithError("s_sw_ers_req_C", "E0032A"));
        Assert.True(exportXml.ContainsRequirementKeyWithError("s_sw_ers_req_D", "E0032A"));       
    }

现在,如果例如第一个 Assert.True(...)失败,其他的不会被执行/检查。我不想将这七个断言分解为单独的方法,因为它们在逻辑上确实属于在一起(只有当所有七个断言都一起通过时,TC 才会完全“通过”)。

Is it possible to tell xUnit.net to perform all e.g. Assert.True() in one test method? Basically in some of our use/testcases all assertions belong logically to one and the same 'scope' of tests and I have e.g. something like this:

    [Fact(DisplayName = "Tr-MissImpl")]
    public void MissingImplementationTest()
    {
        // parse export.xml file
        var exportXml = Libraries.Utilities.XML.GenericClassDeserializer.DeserializeXmlFile<Libraries.MedTrace.ExportXml>(
                ExportXmlFile);

        // compare parsed results with expected ones
        Assert.True(exportXml.ContainsRequirementKeyWithError("PERS_154163", "E0032A"));
        Assert.True(exportXml.ContainsRequirementKeyWithError("PERS_155763", "E0032A"));
        Assert.True(exportXml.ContainsRequirementKeyWithError("PERS_155931", "E0032A"));
        Assert.True(exportXml.ContainsRequirementKeyWithError("PERS_157145", "E0032A"));

        Assert.True(exportXml.ContainsRequirementKeyWithError("s_sw_ers_req_A", "E0032A"));
        Assert.True(exportXml.ContainsRequirementKeyWithError("s_sw_ers_req_C", "E0032A"));
        Assert.True(exportXml.ContainsRequirementKeyWithError("s_sw_ers_req_D", "E0032A"));       
    }

Now if e.g. the first Assert.True(...) fails, the other ones are not executed/checked. I'd rather not break these seven Assertions up into separate methods, since these really do belong together logically (the TC only is 'passed' entirely if all seven are passing all together).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

箹锭⒈辈孓 2024-08-20 22:12:18

AAA 的重点是尽可能简化每个部分并保持重点,以便读者可以快速理解测试并轻松隔离故障原因。

这里有 7 个不同的事实,它们共同构成一个理论。因此,您应该创建一个 [Theory],其中包含 7 组代表期望的 [InlineData]。请参阅http://blog.benhall.me.uk /2008/01/introduction-to-xunitnet-extensions.html 为例。

如果重新执行安排/操作是一个问题,那么您应该通过在测试类的构造函数中执行此操作来制作“固定装置”(用 xUnit 测试模式的说法)。

public class WithGenericClassDeserializer
{
    var exportXml;

    public WithGenericClassDeserializer()
    {
        // Or move this into the GivenExportXmlFile_ExpectedValueAtKeyShouldMatch
        exportXml = Libraries.Utilities.XML.GenericClassDeserializer.DeserializeXmlFile<Libraries.MedTrace.ExportXml>( ExportXmlFile );
    }

    [Theory( DisplayName = "Tr-MissImpl" )]
    [InlineData( "PERS_154163", "E0032A" )]
    [InlineData( "PERS_155763", "E0032A" )]
    [InlineData( "PERS_155931", "E0032A" )]
    [InlineData( "PERS_157145", "E0032A" )]
    [InlineData( "s_sw_ers_req_A", "E0032A" )]
    [InlineData( "s_sw_ers_req_C", "E0032A" )]
    [InlineData( "s_sw_ers_req_D", "E0032A" )]
    public void GivenExportXmlFile_ExpectedValueAtKeyShouldMatch( string key, string value )
    {
        Assert.True( exportXml.ContainsRequirementKeyWithError( key, value ) );
    }
}

The whole point of AAA is to aim to simplify each piece as much as possible and keep it focused, so readers can understand the tests quickly and isolate the cause of failures easily.

You have 7 different Facts here, which together comprise a Theory. So you should create a [Theory] with 7 sets of [InlineData] representing the expectations. See http://blog.benhall.me.uk/2008/01/introduction-to-xunitnet-extensions.html for an example.

If the re-executing of the Arrange/Act is an issue, then you should be making that the 'fixture' (in xUnit Test Patterns parlance) by doing that in the constructor of your test class.

public class WithGenericClassDeserializer
{
    var exportXml;

    public WithGenericClassDeserializer()
    {
        // Or move this into the GivenExportXmlFile_ExpectedValueAtKeyShouldMatch
        exportXml = Libraries.Utilities.XML.GenericClassDeserializer.DeserializeXmlFile<Libraries.MedTrace.ExportXml>( ExportXmlFile );
    }

    [Theory( DisplayName = "Tr-MissImpl" )]
    [InlineData( "PERS_154163", "E0032A" )]
    [InlineData( "PERS_155763", "E0032A" )]
    [InlineData( "PERS_155931", "E0032A" )]
    [InlineData( "PERS_157145", "E0032A" )]
    [InlineData( "s_sw_ers_req_A", "E0032A" )]
    [InlineData( "s_sw_ers_req_C", "E0032A" )]
    [InlineData( "s_sw_ers_req_D", "E0032A" )]
    public void GivenExportXmlFile_ExpectedValueAtKeyShouldMatch( string key, string value )
    {
        Assert.True( exportXml.ContainsRequirementKeyWithError( key, value ) );
    }
}
意犹 2024-08-20 22:12:18

是的,您可以,但您必须在测试中添加额外的代码。如果断言失败,xUnit 中的每个 Assert 语句都会抛出异常。因此,在 Assert.True 的情况下,它会抛出 TrueException。因此,您可以做的是:

    [Fact]
    public void MultipleAssertTest()
    {
        bool passesValidation = true;

        passesValidation = PassesAssert(true == true);
        passesValidation = PassesAssert(false == true);
        passesValidation = PassesAssert(5 == 1);

        Assert.True(passesValidation);

    }

    private bool PassesAssert(bool expression)
    {
        try
        {
            Assert.True(expression);
            return true;
        }
        catch
        {
            return false;
        }
    }

这将允许您运行所有断言并完整地进行测试。然而,它并不是很有帮助,因为您不知道断言失败的原因。下面的内容会更好,这样您就可以实际从测试中获得结果,从而知道哪些项目失败了。

       private StringBuilder resultMsg;
    [Fact]
    public void MultipleAssertTest()
    {
        bool passesValidation = true;
        resultMsg = new StringBuilder();

        passesValidation = PassesAssert(true == true, "True True test");
        passesValidation = PassesAssert(false == true, "False True test");
        passesValidation = PassesAssert(5 == 1, "5==1 Test");

        Assert.True(passesValidation, resultMsg.ToString());

    }

    private bool PassesAssert(bool expression, string message)
    {
        try
        {
            Assert.True(expression, message);
            return true;
        }
        catch (AssertException ex)
        {
            resultMsg.Append(ex.UserMessage);
            resultMsg.Append(Environment.NewLine);
            return false;
        }
    }

当然,这需要更多的工作,但它允许您一起阻止所有断言。您可以通过这种方式包装任何测试 Assert 方法。所以你可以说你正在扩展 xUnit 以拥有一个不会失败的 Assert 过程。

希望这有帮助。

编辑:根据评论,为了使其工作,您需要使用 &运算符,因为后续调用将覆盖该值。

Yes you can but you have to add extra code to your test. Each Assert statement in xUnit will throw an exception if the assert fails. So in the case of Assert.True it throws a TrueException. So what you could do is something along the lines of:

    [Fact]
    public void MultipleAssertTest()
    {
        bool passesValidation = true;

        passesValidation = PassesAssert(true == true);
        passesValidation = PassesAssert(false == true);
        passesValidation = PassesAssert(5 == 1);

        Assert.True(passesValidation);

    }

    private bool PassesAssert(bool expression)
    {
        try
        {
            Assert.True(expression);
            return true;
        }
        catch
        {
            return false;
        }
    }

This will allow you to run all your asserts and do your test completely. However it is not very helpfull as you don't know what assert fails. What would be better is below so you can actually get results out of your test so you know which items fail.

       private StringBuilder resultMsg;
    [Fact]
    public void MultipleAssertTest()
    {
        bool passesValidation = true;
        resultMsg = new StringBuilder();

        passesValidation = PassesAssert(true == true, "True True test");
        passesValidation = PassesAssert(false == true, "False True test");
        passesValidation = PassesAssert(5 == 1, "5==1 Test");

        Assert.True(passesValidation, resultMsg.ToString());

    }

    private bool PassesAssert(bool expression, string message)
    {
        try
        {
            Assert.True(expression, message);
            return true;
        }
        catch (AssertException ex)
        {
            resultMsg.Append(ex.UserMessage);
            resultMsg.Append(Environment.NewLine);
            return false;
        }
    }

Of course this requires a little more work but it allows you to block all your Asserts together. You can wrap any of your test Assert methods this way. So you could say you are extending xUnit to have a non-failing Assert process.

Hope this helps.

EDIT: As per the comments in order for this to work you would need to use the & operator as the subsequent calls would overwrite the value.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文