如何使用黄瓜在场景之间共享状态

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

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数组保留在其他方案中,以便我可以继续使用实际结果集吗?

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

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

我发现技术上可以使用

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

然而,就像其他人一样,这可能不是一个好主意。

我试图在类似的场景中避免重复登录步骤。 同样,这可能不是一个好习惯。 在必要时使用技巧

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

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

相反,你应该模拟外部系统,并让你的场景控制模拟系统将提供什么:

 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" 

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

该forms的场景也可以传达给利益相关者,他们可以在不事先了解这些外部系统中存在的任何测试数据的情况下validation场景。

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

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

我生成用户:

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

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

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

后来,当我需要其他function中的数据时,我使用:

 @randomName = data = File.read("randomName.txt") 

使场景依赖或在场景之间共享数据不是一个好习惯。

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

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