C# NUnit:Assert.Multiple用于包含Aspect的方法

C# NUnit:Assert.Multiple用于包含Aspect的方法,c#,unit-testing,nunit,assert,C#,Unit Testing,Nunit,Assert,我正在测试一个包含三个不同模块的网页。在我的测试框架中,每个页面模块都由自己的测试类表示:Module1Tests,Module2Tests,Module3Tests。此外,为了满足每个模块的特定条件,我在每个测试类中使用假设。 使用此设置,如果我只是测试单独的模块,那么一切都可以正常工作。 但是,当我为整个页面创建一个测试类并使用Assert.Multiple时,如下所示: public class HomePageTests { public Module1Tests

我正在测试一个包含三个不同模块的网页。在我的测试框架中,每个页面模块都由自己的测试类表示:
Module1Tests
Module2Tests
Module3Tests
。此外,为了满足每个模块的特定条件,我在每个测试类中使用
假设。
使用此设置,如果我只是测试单独的模块,那么一切都可以正常工作。
但是,当我为整个页面创建一个测试类并使用
Assert.Multiple
时,如下所示:

public class HomePageTests
    {
        public Module1Tests Module1Tests { get; } = new Module1Tests();

        public Module2Tests Module2Tests { get; } = new Module2Tests();

        public Module3Tests Module3Tests { get; } = new Module3Tests();

[Test]
public void HomePage()
{
    Assert.Multiple(() =>
    {
        Module1Tests.Module1TestMethod();
        Module2Tests.Module2TestMethod();
        Module3Tests.Module3TestMethod();
    });
}
我收到一条错误消息,表示我无法将方法与
假定一起使用。这是
断言中的
。多个

我还尝试在没有Assert.Multiple
块的情况下调用模块测试方法,但是在第一次失败时整个页面测试停止执行


有办法解决这个问题吗?基本上,我只想对页面进行一个测试,如果所有底层模块测试都通过,该测试就会通过。

正如已经指出的,并且正如消息所示,您不能在多断言块中使用假设。如果您查看文档“假设”页面上注释6中的排除项目列表,您将看到它们都是用于立即终止测试执行的项目

当然,Fail和failed断言也用于立即终止测试。多个断言都是例外。。。记录失败,但直到所有嵌套的Assert.Multiple块结束,测试才终止

我考虑对列表中的每个项目都做一些例外,这需要为每个项目定义新的行为。目前还不清楚最佳替代行为是什么,所以我决定等待用户反馈。这个问题实际上是我在任何地方看到的第一个反馈,所以谢谢

通常,假设放在所有断言之前,有时甚至在SetUp方法中也是如此。在这种情况下,它们的意思基本上是:“如果这个假设失败了,那么运行测试就没有意义了。”偶尔,它们被放在一些断言之后,意思是“如果这个假设失败了,那么运行更多的测试就没有意义了。”

如果我理解正确,您可能希望失败的假设意味着我们应该跳过您的一个模块测试中的以下所有断言,但继续进行任何其他模块测试。但在测试用例中进行模块测试的概念在NUnit中并不存在,至少在今天是这样。NUnit中可用的结构由层次结构表示: *命名空间(可能是嵌套的) *固定装置 *测试用例 *多个断言块(可能嵌套) *断言

如果您的模块测试使用多个断言块本身,那么我们可以考虑在多个断言块内映射假定的行为,意思是“在这个块中运行更多的测试代码是没有意义的。”如果您想要,则需要在GITHUB上提交一个特征请求。我可以提前告诉你,这不是一个微不足道的改变,所以不能保证我们会这样做,但也许值得做一些分析,看看它是如何运作的。基本上,我们希望在不混淆其他用户的情况下为您提供所需信息。:-)

根据当前的功能,我看到了两种解决方案:

  • 使每个模块在夹具内采用单独的测试方法进行测试,该夹具基本上取代了当前的测试方法。如果执行顺序对您很重要,请在每个测试上放置Order属性。换句话说,具有n个测试的现有装置将成为n个单独的装置。我不知道这对您是否可行,因为我还没有看到您的代码,但这是一种利用NUnit现有设施构建测试的方法

  • 将模块测试封装为一组类,而不是一组方法。用一种方法运行所有假设,用另一种方法运行所有断言。在Assert.Multiple块之前,预先调用所有假设。如果您不希望失败的假设停止整个测试,那么您必须从假设条目返回bool,并记住是否运行每个模块

  • 可能是最简单的:将您的假设转化为每个模块测试方法中的条件。如果假设失败,那么不要运行测试

  • 我真希望我能提供嵌套装置作为结构化的替代方案。在许多方面,这比其他选项更适合您正在尝试做的事情。不幸的是,尽管NUnit允许在语法上嵌套fixture,但在测试运行时嵌套被完全忽略。我们有一个突出的功能要求来改变这一点,但它是相当未来的

  • 雷帕克

  • 是的,那是故意的。我希望一定有别的方法来实现我的目标。谢谢你这么详细的回答,@Charlie!建议1是我在这里发帖之前第一次尝试的。我有一个页面测试类,它有三个
    [test]
    块,每个块表示从模块测试类调用模块测试方法的方法。实际上它是有效的,但问题是我对模块使用了参数化测试方法(带有
    [Values]
    [ValueSource]
    属性),并且对每个模块重复相同的参数块对我来说似乎并不优雅。我尝试在夹具级别进行参数化,但无法在那里使用
    [ValueSource]
    属性。建议3看起来不错,但如果条件不满足,我如何不运行测试?例如,我使用
    if
    检查布尔条件,如果它不是真的,我应该做什么来跳过测试?出于同样的原因,不允许调用
    Assert.Inconclusive
    。我假设您将从模块测试返回,将控制权传递回测试方法本身,然后该方法将调用下一个模块测试。