【问题标题】:Tests dependent on commonly used functionality with NUnit测试依赖于 NUnit 的常用功能
【发布时间】:2010-08-03 11:34:24
【问题描述】:

我有一些初始化代码来使用我的 API。初始化可能会失败,我想在 NUnit 测试中对其进行测试。

在初始化之后,API 就可以使用了。我也在测试 API,但我所有的测试方法都将使用相同的通用初始化代码。

如果这种行为发生,我最理想的情况是:

  1. 初始化测试运行。
  2. 如果 [1] 成功,则运行其他测试。

在 [1] 将失败的所有情况下,所有其他测试也会失败。但有价值的信息是 [1] 失败了。那是我最有可能发现问题的地方。如果其他测试可以用 ?或其他什么,表明它们没有执行,因为它们所依赖的功能没有通过测试。

我知道测试不应该是脆弱的。但我无法绕过这样一个事实,即初始化代码对于正确执行其他功能是必需的。

这是一个更普遍的问题,其中某些功能依赖于其他功能。 “其他功能”过于普遍,无法通过依赖它的所有测试失败来提供任何实际价值。最好单独测试“其他功能”。

【问题讨论】:

  • +1。我的第一个想法是涵盖您的初始化的现有测试用例已经工作。只有当你重构你的初始化代码时,你才需要重新运行这些测试用例,直到你再次变绿。我的第二个想法是闭嘴,看看其他人的想法。很可能,这将是我今天的最佳想法。
  • 所有测试用例都在我们的构建服务器上运行。该套件必须能够作为一个整体运行,因为如果您只执行您认为会影响您的测试,那么很容易错过一些东西。这些是集成测试,因此一次测试不止一个类。
  • 正是我的意思,但无法正确解释。
  • 好的。很高兴我们有相同的想法!

标签: nunit integration-testing


【解决方案1】:

好的,这就是我的处理方式......

将通用初始化放入 Setup 方法中,因为所有测试都需要它。如果初始化引发错误,您会看到

  • 套件中的所有测试都失败(随着时间的推移,我已经接受过培训,可以将其识别为安装/拆卸可能引发异常的提示)。
  • 包含 Setup 方法的失败测试的堆栈跟踪。

如果这对您来说过于隐晦,您可以(尽管我不建议这样做)在同一个套件中添加一个具有好名称的空测试。如果该测试显示为绿色,则可以确定 Setup / common init code 已成功。

[Test]
public void VerifySetup() {}

更新:您似乎有一个非常利基的需求。我不知道 NUnit 中的任何机制来指定测试的这种条件执行 - 例如只有在 Test1 通过时才运行 Test2 到 10。

【讨论】:

  • 感谢您的回答!尽管我不能说我认为它是我问题的答案。所以-1。这正是我想要避免的。我希望依赖于通用功能的测试不运行,因为它们不提供其他信息。如果我对通用功能的测试是唯一一个失败的测试(而其他测试则处于排除状态或其他状态),它会立即引导我使用通用代码。可能会有很多通用代码的场景,例如使用 API 的不同部分。使用 Setup 和一个空的方法可能看起来很恶心。
  • 我非常不同意。测试套件中所有失败的测试都提示我设置/拆卸存在问题。然后堆栈跟踪帮助我确认它。至于在安装程序失败时忽略测试,这有什么关系-套件中的所有测试都失败与一个特别命名的测试失败-事实仍然是套件中的所有测试都已损坏/无法正常工作,并且有人需要采取看看它。我不认为你可以在 NUnit 中在运行时包含/排除测试,至少在不使测试代码复杂化的情况下不能......
  • +1。我不能代表 NUnit,但使用 DUnit 肯定可以运行或不运行测试,具体取决于其他测试的结果。我看到了 2 个问题,它像你提到的那样使测试代码复杂化,在纯单元测试中,测试用例不应该相互依赖(严格来说,这不是依赖)。
  • @Gishu:很高兴您的回答,非常感谢您的 cmets!但我认为我们不会达成共识。对于更复杂的依赖关系,我可以看到拥有这种能力的优势。简单地使用 SetUp 并分成不同的测试套件也很好。但我并不认为在所有情况下都足够。使用 JUnit,我认为这是可能的。如果 NUnit 不可能,这也是有价值的信息,如果您确定请将其发布为答案,我会接受。因为这是我正在寻找的可能答案之一。
  • @Binary255 - 根据我昨天发布的 2005 年博客文章,这可能对您有用。使用类别将您的测试划分为“SetupTests”和“RealTests”。现在使用批处理文件/脚本之类的东西来运行 2 个任务 - 只有在第一个任务成功时才运行第二个任务。首先运行 Task1 - 运行类别 SetupTests 的所有测试。如果 Task1 成功,则仅运行类别为 RealTests 的所有测试。
【解决方案2】:

我一直在与 NUnit 开发人员联系。如果不编写一个非常复杂的插件,目前是不可能的。该功能将出现在 3.x 代码库的某个地方,但不会出现在 2.5 中。我会考虑写,但暂时不会。

【讨论】:

    【解决方案3】:

    试试这个:

    1. 将“初始化测试”定义为 TestCase

    2. 将所有其他测试设为此 TestCase 的子类

    3. 创建一个套件,该套件以特定顺序运行您的测试,以便您的“初始化测试”排在第一位。

    【讨论】:

    • -1。如果我的初始化测试失败,这不会阻止其他测试用例的执行。
    • @Binary255。 “如果我对通用功能的测试...... [失败] 它会立即引导我使用通用代码”。这解决了你的问题。它不需要是 only 测试,除非您声称您无法读取日志或其他内容。很明显,你有头脑。您可以阅读日志。常见的东西将被明确标识为失败。
    • 当然。我不认为这是一个大问题。但这不是我要找的。如果另一个测试失败,我希望忽略一些测试。如果只是顺序,我不能先放置初始化测试并将实际的初始化代码分成一个私有(不是测试)辅助方法吗?我们正在监控每个测试用例并生成统计数据。如果初始化代码失败,我们希望它显示用于测试初始化​​代码的测试。在初始化测试之后,我们正在测试 API 的一部分。我们希望在有机会成功时运行测试。
    • 如果一项测试经常失败,这可能表明测试正在测试的代码应该被重写。我们希望具体一点,而不是每次我们总是需要执行的步骤失败时都得到这样的指示。在我们看来,这只会使事情变得混乱。
    • @Binary255:你没抓住重点。测试不是“发现”。您的计划是让所有测试始终通过。时期。如果所有测试都没有通过,你就不再测试,你在调试。测试日志中的“杂乱”程度不再重要,因为——一旦测试失败——你就拥有了你需要的所有信息。一旦测试失败,您将进入调试阶段,这是一个使用单独工具的单独活动。
    【解决方案4】:

    我认为这很明确。问题是你很难分离你的 API 职责。你有两个。 API 和 API 执行的初始化。编写具有这种依赖关系的测试可能会杀死你。

    所以我建议 API 创建一个初始化对象,然后创建各种命令对象来执行 API。命令对象将在某种存储中,或者您可以即时创建。

    API 将使用模拟的初始化对象,并将使用模拟的命令对象。

    初始化对象实际上没有任何依赖关系,除了你需要初始化的任何东西。

    Command 对象需要一个模拟的初始化对象。

    [编辑]

    如果初始化测试失败,有两种方法可以让其他测试失败

    1. 向测试用例添加私有变量。 private isInitialized = false;。然后你的所有其他测试检查这个变量的状态,如果不是真的然后失败。

    2. 使用 API 类扩展您的测试用例。添加询问初始化状态的私有函数。

    两者中的cleaner是2。最快的实现是1。

    恕我直言当您必须以这种方式耦合测试时,这可能是一种代码味道。如果如您所说,这是一个集成测试。为什么你有一个单独的初始化测试。集成更多的是针对您的 API 运行一些操作。因此,每个集成测试必须初始化 API。

    您可能需要重新考虑级联故障场景。完成测试时可能噪音太大。

    [EDIT1a]

    我认为满足您要求的唯一方法是extend NUnit。具体研究 Test Case BuildersTest Decorators

    该链接的日期为 2008 年 3 月,因此希望它不会过时。

    【讨论】:

    • -1。当我正在编写集成测试时,我不想模拟任何东西。如果我写一个单元测试会有所不同。有时事情必须按顺序执行,这并不总是设计不佳的标志。
    • @Binary255 - 抱歉,我没有看到任何有关集成测试的相关信息。您的标签是单元测试的。查看我的编辑了解更多...
    • 啊,对不起。我现在注意到我没有提到我在任何地方进行集成测试。 :-( 我已经更改了标签。
    • 对于我知道如果初始化失败将失败的测试,我希望它们不执行。就像他们有 Ignore 属性一样。我的理由是,他们的失败只会使结果变得混乱,而真正能告诉我问题出在哪里的测试是初始化测试。所以我认为如果另一个测试失败,我会通过让一些测试不执行来减少噪音。我意识到如果一个人不小心,这可能会变得复杂和失控。它肯定可能是一种代码味道,事物相互依赖,这是不应该的。但对于我的情况,我认为这不是真的。
    • 从您的编辑中“如果初始化测试失败,有两种方法可以让其他测试失败”。我不希望其他测试失败,我希望它们被忽略。有一个很大的不同。忽略状态会提醒我它们尚未执行,我不会得到测试成功或失败的误导性信息。我非常感谢您的时间和很好的答复!我将不得不支持我的-1,因为它不能解决问题。我一开始就给了一个误导性的标签是我的错,对此我很抱歉。
    猜你喜欢
    • 2010-11-19
    • 2015-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多