如何使用具有大量输出的Cucumber测试Ruby命令行程序?

时间:2012-12-04 22:40:12

标签: ruby cucumber aruba

我正在构建一个Ruby命令行程序,并使用Cucumber和Aruba来测试它。 Aruba包含一些非常方便的匹配器,所以我可以在.feature文件中用几行测试输出:

When I run `myprogram`
Then it should pass with:
  """
  my program output
  """

问题是我的程序可能包含数十行甚至数百行输出;将所有内容放在.feature文件中将使得阅读和导航变得更加困难(并且有点令人讨厌)。在这种情况下测试输出的推荐方法是什么?

4 个答案:

答案 0 :(得分:7)

简短的回答是:你不应该这样做。

黄瓜测试应该是面向用户和可读的。他们描述了特征。如果错误输出与字节的某个已知值字节匹配,则用户不会关心。

你需要问问自己:我在测试什么?答案是错误信息吗?可能不是。您正在测试应用程序中的某些功能。如果您真的想确保它失败,那么您在Cucumber场景中想要的是以下几行:

Then the exit status should not be 0

这假设脚本遵循标准惯例,即非零退出状态表示错误。

如果您的方案要求输出中有某条消息,您可以添加它:

Then it should fail with
"""
Some error message
"""

但这不一定是整个输出,只是部分匹配。 (请注意,在aruba中定义了“它应该完全失败:”,但我不建议使用它。)

编辑:您已将示例更改为测试通过而非失败,但我的基本建议是相同的:

  1. 将输出的细节与场景的逻辑分开。使用注释中的示例,如果您有一个测试确认您可以输出单个用户生成的注释,另一个测试确认您输出了正确的100个注释,那么就足够了,在黄瓜方案中不需要有100条评论的输出值。
  2. 保持从用户角度编写的Cucumber场景。每个场景都应该测试对用户来说很重要的东西。尝试通过在用户不关心的情况下删除从实现中泄漏的任何内容来保持最小化。
  3. 使用测试部分匹配的内置Aruba结构来实现此目的。在输出中查找关键词或短语。黄瓜测试不仅更容易阅读,而且更加强大,不受不相关的输出变化的影响。

答案 1 :(得分:2)

要测试您的程序,您有两个选择:

  1. 仅检查邮件的相关部分(您实际要通过此测试检查的内容)。 Aruba有built-in stepdef因为它很容易

  2. 检查完整消息。如果消息很短,您可以使用Aruba的built-in stepdef。但是,如果消息很长,您可能希望将其放在单独的文件中。由于Aruba不包含此类方法,您应该自己编写此步骤。

  3. 看起来像:

    # Require aruba/api before that
    Then /^it should (pass|fail) with message from file "(.*)"$/ do |pass_fail, filename|
      exact_output = File.read(filename)
      Aruba::API::assert_exit_status_and_output(pass_fail == "pass", exact_output, true)
    end
    

    如果您想编写大量测试并且许多消息类似,那么最终可能会出现大量WET消息。断言完整的消息将使支持测试变得更加困难。

    因此,您可能希望使用某种模板引擎来断言这些消息以进行DRYer测试。

    你可以用不同的方式设计你的测试 如果您只使用第一种方法,那么您的测试可能找不到一些回归错误,因为它们不会测试所有内容。如果您使用第二种方法,如果消息之间存在大量重复,则支持它们可能要困难得多。

    因此,在这两个选项之间存在权衡。通常你用方法1构建一些测试,用方法2构建另一个测试。你应该考虑在你的情况下哪个更好。我不知道任何黄金法则。

答案 2 :(得分:0)

数百个输出在应用程序中并不令人惊讶。是的,你需要让它们易于阅读。如果您不能在Cucumber功能文件中执行此操作,我担心没有更好的替换位置。毕竟Cucumber都是简单的英语,并作为现场文档。

您只需要整理它们。以下是一些基本提示,以防您忽略它们。

  1. 仅针对.feature个文件编写涵盖一个主题的特定功能。虽然我知道您提到的When I run my program仅用于演示目的,但这样的广泛主题是不可接受的。

  2. .feature个文件放入features/文件夹。并且,如有必要,进一步将它们拆分为子文件夹,如features/user/user_login.feature

  3. 使用Scenario OutlineExamples在一个场景中组织类似的输出。这些示例将有行清楚地表示它们中的每一个。

  4. 希望这些帮助。

答案 3 :(得分:0)

我会推荐以下内容:

When I run `my_app`
Then the exit status should not be 0
And the output should contain:
"""
some output
"""

这样,只要从程序中输出“some output”,测试就会通过,但附加输出会被忽略,你的测试不需要输出所有输出。

如果你想一步断言所有这一切,那就自己动手吧,虽然我觉得这更清楚。