5

我有一个功能“从外部网站导入文章”。在我的第一个场景中,我测试从外部网站导入链接列表。

Feature: Importing articles from external website
  Scenario: Searching articles on example.com and return the links
    Given there is an Importer
    And its URL is "http://example.com"
    When we search for "demo"
    Then the Importer should return 25 links
    And one of the links should be "http://example.com/demo.html"

在我的步骤中,我在一个@result数组中有 25 个链接。

在我的第二种情况下,我想获取其中一个链接并测试我正确解析文章的事实。

现在显然我不想每次都去外部网站,尤其是现在第一个场景已经过去了。

如何在此处继续进行,以便在不为第一个场景发出 HTTP 请求的情况下继续测试?或者我应该运行一次并@result在其余场景中保留数组,以便我可以继续使用实际结果集?

4

6 回答 6

9

这是故意很难做到的!在测试之间共享状态通常是一件非常糟糕的事情,尤其是因为它迫使你的测试按顺序运行(你的第一个场景必须在后续的场景之前运行,而不是 Cucumber 明确支持的东西)。

我的建议是重新考虑您的测试策略。在测试中使用外部服务是使它们运行缓慢且不可靠的好方法(当外部服务出现故障时会发生什么?)。在这种情况下,我建议使用webmockvcr之类的东西来创建外部站点的假版本,它返回的响应与您对真实站点的期望相同,但是您可以在没有担心性能或不可用。

于 2012-06-23T08:16:01.827 回答
3

我发现在技术上可以使用

@@global_variable 在步骤定义中共享全局状态。

但是,就像其他人指出的那样,这可能不是一个好主意。

我试图避免在类似情况下重复登录步骤。同样,这可能不是一个好习惯。在真正需要的时候使用这个技巧

于 2013-11-01T23:42:17.013 回答
2

您不应该在场景之间共享状态。场景描述了整个系统的预期行为,应该可以只运行一个场景。例如,如果您已经运行了整个测试套件,并且发现一个场景失败了,那么您应该能够只运行那个场景来调查出了什么问题。

您的问题出现是因为您尝试联系外部系统。这是不可取的。它不仅使您的测试套件运行得更慢,而且还使测试依赖于您无法控制的外部系统。如果外部系统未运行,则您的测试未运行。如果外部测试不包含您期望的数据,即使您自己的系统中没有错误,您的测试也会失败。你最终让你的测试由你期望在外部系统中的内容来控制,而不是根据你需要测试的内容来控制外部系统中的内容。

相反,您应该模拟外部系统,并让您的场景控制模拟系统将提供的内容:

Scenario: Query external system
    # These two lines setup expected data in a mocked version of the external system
    Given there the system x contains an article named "y"
    And the article contains the text "Lorep ipsum"
    When I query for article "y"
    Then I should see the text "Lorem ipsum"

此场景独立于外部系统中的任何实际数据,因为它明确指定了需要存在的内容。更重要的是,它清楚地描述了您自己的系统应该如何运行。

这种形式的场景也可以传达给利益相关者,他们可以验证场景,而无需对这些外部系统中存在的任何测试数据有任何先验知识。

运行适当的框架可能需要一些时间,但最终,这是值得的。

于 2012-06-23T08:50:44.380 回答
0

我用一个文件。我有一个创建新用户的案例,然后我想注销并在其他功能中使用同一用户重新登录。

我生成用户:

@randomName = [*('a'..'z')].sample(8).join

然后我将用户保存到一个文件中:

File.open("randomName.txt", 'w') {|f| f.write("#{@randomName}") }

后来,当我在其他功能中需要该数据时,我使用:

@randomName = data = File.read("randomName.txt")
于 2014-08-08T16:45:17.917 回答
0

我还没有看到任何让我想使用这些 DI 小框架的东西。我只是在存储会话数据的类中创建了一个静态初始化程序,并让所有步骤定义类扩展该类。它可以工作,我不必在我的项目中添加更多库。

public class MyAbstractClass {
    public static final Object param1;
    public static final Object param2;
    public static final Object param3;

    static {
        // initialize params here
    }

public class MyStepDefinition extends MyAbstractClass {}

如果您需要可以随时间变化的数据,只需将它们声明为非静态。

于 2020-03-06T14:58:56.950 回答
0

使场景依赖或在场景之间共享数据不是一个好的做法。

一些解决方案 1) Cucumber 提供Background标签来运行每个场景的前提条件。

2) Cucumber 提供了钩子@Before 和@after,可以为每个场景定制。

于 2016-12-12T10:36:50.437 回答