Selenium 如何不为依赖于背景场景的Cucumber特性不断重复背景场景

Selenium 如何不为依赖于背景场景的Cucumber特性不断重复背景场景,selenium,testing,selenium-webdriver,automated-tests,cucumber,Selenium,Testing,Selenium Webdriver,Automated Tests,Cucumber,我正在使用Cucumber和Selenium为我的应用程序编写一些端到端测试。正如Cucumber网站上所建议的那样,我保持每个场景完全独立。但是,我的应用程序具有基于会话的身份验证,因此每次运行新场景时,都需要登录过程才能首先访问该站点。现在,我的方法是将登录场景作为所有其他场景的背景场景,如下所示: Background: User is Logged In Given I am on the login screen When I enter my login deta

我正在使用Cucumber和Selenium为我的应用程序编写一些端到端测试。正如Cucumber网站上所建议的那样,我保持每个场景完全独立。但是,我的应用程序具有基于会话的身份验证,因此每次运行新场景时,都需要登录过程才能首先访问该站点。现在,我的方法是将登录场景作为所有其他场景的背景场景,如下所示:

  Background: User is Logged In
    Given I am on the login screen
    When I enter my login details
    And I click submit
    Then I should be logged in
然而,这感觉像是许多重复的“代码”。此外,独立运行每个场景需要创建一个新的WebDriver实例,并为每个场景运行一个浏览器,这感觉有点低效


有没有人能建议我如何避免在其他场景中重复背景场景(如果可能的话),第二,为每个场景提供一个单独的WebDriver实例是否是正确的方法?

这个例子是用Ruby编写的。您可以在
Login\u steps.rb
文件中将用于登录的步骤分组

.feature
文件中,您需要编写一个类似“给定用户已登录”的步骤。如果需要,也可以在此步骤中传入登录数据。然后在
login\u steps.rb
文件中创建:

Given(/^the user is logged in$/) do
  step('I am on the login screen')
  step('I enter my login details')
  step('I click submit')
  step('I should be logged in')
end
我相信你可以在任何其他语言中找到等价物。现在,您可以在后台编写一个脚本,如下所示:

Background: Given the user is logged in
它将在特定
功能文件的每个场景之前使用

至于Webdriver,据我所知,测试开始时创建一个会话,测试结束时退出


希望有帮助

首先,您的每个场景都必须登录并创建一个新会话。这是您进行端到端测试所付出的代价。由于大多数登录屏幕都很简单,渲染时间短,数据库访问量很少,因此在运行时使用标准登录过程的成本应该相对较小。尝试在场景之间共享会话,从而在此处放置和保存运行时,这确实是一个非常糟糕的主意

要开始整理你的cukes,你可以按照Daniel的答案,但是我建议不要嵌套这些步骤,而是将代码提取到一个helper方法并调用它

要优雅地使用power,即使用角色和额外属性处理不同的用户,您需要做更多的工作。您可以在这里看到这方面的详细示例()

要有效地使用它,请遵循提交历史记录并主要关注features文件夹

这有一些框架代码,允许您注册/创建用户,然后在许多不同的配置中使用它们。有一些底层代码有点复杂,它使您能够创建知道自己密码的用户,以及添加其他属性(如角色)

最终的结果是,您可以编写一个步骤定义,如

Given I am registered
Given I am an admin
Given I am logged in
Given I am logged in as an admin
它们被实现为

Given 'I am registered' do
  @i = create_user
end

Given 'I am an admin' do
  @i = create_user role: 'admin'
end

Given 'I am logged in' do
  @i = create_user
  login as: @i
end

Given 'I am logged in as an admin' do
  @i = create_user role: 'admin'
  login as: @i
end
注意:变量@i用于将用户从一个步骤传递到下一个步骤


这里不必担心重复,因为所有步骤都会调用相同的helper方法。您可以在更广泛的上下文中使用此处显示的模式来简化您的功能/

不要嵌套步骤,而是将内容提取到帮助器方法并调用该方法。@Debaolist,介意扩展一下吗?有多种方法可以做到这一点,包括编写一个不嵌套且包含登录逻辑的步骤,以及编写一个helper方法。在告诉人们什么不该做时,解释一下原因,让他们更加清楚。当然:步骤定义只是带有非常难看签名的方法。
step('foo')所做的只是使用一个方法
step`调用另一个方法(恰好是step def)。用直接方法调用替换它是等效的和更简单的。如果将步骤
foo
的内容提取到帮助器方法中,则可以在两个步骤定义中使用相同的调用,这将消除大量复杂性并使方法链更易于遵循。步骤的问题实际上是在嵌套结束时开始出现的,即,您有一个使用步骤调用另一个使用步骤的步骤定义的步骤定义。现在真的很难跟踪到底发生了什么,你最终会产生一些副作用,打破各种情景。提取方法并直接调用它们要简单得多,您可以使用所有标准的代码重构和组织工具,我们必须使这些方法简单而强大,同时将所有代码从步骤定义中去掉,这些定义现在只是作为场景和实现之间的简单中介。不确定“真的很难理解”,但谢谢你的意见。