【问题标题】:How to not continually repeat a background scenario for Cucumber features that depend on that background scenario如何不为依赖于该背景场景的 Cucumber 功能不断重复背景场景
【发布时间】:2019-10-13 16:01:41
【问题描述】:

我正在使用 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 实例是正确的方法?

【问题讨论】:

    标签: selenium testing selenium-webdriver automated-tests cucumber


    【解决方案1】:

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

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

    要优雅地使用权力做到这一点,即处理具有角色和额外属性的不同用户,您需要做更多的事情。您可以在此处查看详细示例 (https://github.com/diabolo/cuke_up)。

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

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

    最终的结果是你可以写一个像这样的步骤定义

    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 用于将用户从一个步骤传递到下一步

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

    【讨论】:

      【解决方案2】:

      这个例子是用 Ruby 编写的。您可以将用于登录的步骤分组到login_steps.rb 文件中。

      .feature 文件中,您需要编写类似“鉴于用户已登录”的步骤。如果需要,您也可以在此步骤中传入登录数据。然后在login_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
      

      它将在特定.feature文件的每个场景之前使用

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

      希望对你有帮助!

      【讨论】:

      • 不要嵌套步骤,而是将内容提取到辅助方法并调用它。
      • @diabolist,介意扩展一下吗?有多种方法可以做到这一点,包括编写一个不嵌套并包含登录逻辑的步骤以及编写一个辅助方法。通过解释原因来告诉人们不该做什么时,尽量做到更清楚。
      • 当然:步骤定义只是签名非常丑陋的方法。什么step('foo') does is just use a method step` 调用另一个方法(这恰好是一个步骤定义)。用直接方法调用替换它是等效且更简单的。如果您将步骤 foo 的内容提取到辅助方法中,则可以在两个步骤定义中使用相同的调用,从而消除大量复杂性并使方法链更易于遵循。
      • 当你最终嵌套时,step 的问题真正开始发生,即你有一个使用 step 的 step def 调用另一个使用 step 的 step def。现在很难跟踪正在发生的事情,最终会产生破坏场景的副作用。提取方法并直接调用它们要简单得多,您可以使用我们必须使这些方法简单而强大的所有标准代码重构和组织工具,同时将所有代码从您的步骤定义中取出,这些代码现在只是充当场景和之间的简单中介实施。
      • 不确定“真的很难理解”,但感谢您的意见。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-07
      • 1970-01-01
      • 2013-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多