有没有人想出一种在多个浏览器/网络驱动程序上运行相同黄瓜场景的方法? [英] Has anyone figured out a way to run the same cucumber scenario on multiple browsers/web drivers?

查看:18
本文介绍了有没有人想出一种在多个浏览器/网络驱动程序上运行相同黄瓜场景的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 cucumber + capybara 进行一些网络自动化测试.我希望能够连接我自己的标签(类似于场景之前的@all_browsers),并让它针对我设置的网络驱动程序列表(celerity、firefox 上的 selenium、ie 和 chrome)运行.我不想用 4 个不同的标签在 4 个不同的时间编写场景.我已经考虑尝试使用我通过以下方式注册的新驱动程序来执行此操作:

I'm using cucumber + capybara for some web automation testing. I'd love to be able to wire up my own tag (something like @all_browsers before the scenario) and have it run against a list of web drivers I set (celerity, selenium on firefox, ie and chrome). I don't want to have to write the scenario 4 different times with 4 different tags out front. I've looked into trying to do this with a new driver I register via:

Capybara.register_driver :all_browsers do |app|
 # What would even work in here? I don't think anything will.
end  

然后跟进:

Before('@all_browsers') do
 # Same problem here.
end

但我不太确定在可能实际工作的 Before 方法中放入什么.

But I'm not quite sure what to put in that Before method that might actually work.

我试过用黄瓜钩,具体来说:

I've tried using cucumber hooks, specifically:

Around('@all_browsers') do |scenario, block|
  Capybara.current_driver = :selenium_firefox
  block.call

  Capybara.current_driver = :selenium_chrome
  block.call
  # etc
end

但这并不像我希望的那样.它使用相同的驱动程序并使用它运行场景两次.

But this doesn't behave as I had hoped. It uses the same driver and runs the scenario twice with it.

沿着钩线,黄瓜文档中有这样的内容:
您还可以提供一个 AfterConfiguration 挂钩,它将在 Cucumber 配置后运行.这个钩子只会运行一次;在加载支持之后但在加载功能之前.您可以使用此挂钩来扩展 Cucumber,例如您可以影响功能的加载方式...
这可能是一个潜在的途径,但我也没有设法想出任何可以在这里工作的东西.

Following along the hook lines, there's this from the cucumber documentation:
You may also provide an AfterConfiguration hook that will be run after Cucumber has been configured. This hook will run only once; after support has been loaded but before features are loaded. You can use this hook to extend Cucumber, for example you could affect how features are loaded...
This may be a potential path to go down for this, but I've not managed to come up with anything that works here either.

我已经研究过自定义格式化程序,但它们实际上只是看起来确实是这样做的 - 格式化输出,而不是指定功能的实际运行方式.

I've looked into custom formatters, but they really only look like they do exactly that - format the output, not so much designate how the features are actually run.

我已经研究过覆盖 cucumber 的功能运行器,但这看起来并不容易或不友好.
请帮忙?有人吗?

I've looked into overriding cucumber's feature runner, but that doesn't look easy or friendly to do.
Help please? Anyone?

推荐答案

所以,我最终推出了自己的解决方案.不确定这是否是最好或最优雅的方法,但实际上我只是结束了:

So, I wound up rolling my own solution to this. Not sure if it was the best or most elegant approach, but I actually just wound up:

  1. 将所有常见的环境内容抽象到 env.rb
  2. 使用需要 env.rb 的特定环境文件(例如 firefox.rb)的 Cucumber 配置文件,然后将 Capybara 的默认驱动程序设置为适当的驱动程序.
  3. 编写了一个大型的 thor 类,其中包含捆绑一堆黄瓜命令和呼吁以正确的个人资料运行坏男孩.
  4. 编写了一个all_browsers"任务,该任务捆绑了命令,然后调用每个特定的驱动程序任务,因此我现在可以拥有一个任务来运行我在所有支持的驱动程序上提供的任何一组场景.
  1. Abstracting all common environment stuff into env.rb
  2. Using Cucumber profiles which would require a specific environment file (such as firefox.rb) that required env.rb and then set the default driver for Capybara to the appropriate driver.
  3. Wrote a big ol' thor class with tasks that bundle up a bunch of cucumber commands and call out to run the bad boy with the proper profile.
  4. Wrote an 'all_browsers' task which bundles up the commands, then calls out to each specific driver task, so I can now have one task that runs any set of scenarios I supply on all the supported drivers.

像魅力一样工作,我认为最终结果可能比我上面尝试的任何东西都好,因为在 Thor 文件中,我能够添加诸如基准测试选项之类的东西,以及是否拆分该功能运行到多个线程中.仍然很好奇是否有其他人为此提出了解决方案.

Working like a charm and I think might have actually wound up better in the end than anything I was trying above, as within the Thor file I was able to add things like a benchmarking option, as well as whether or not to split the feature run up into multiple threads. Still curious if anyone else came up with a solution for this though.

黄瓜.yaml:
在这里,all_features 文件只包含以 .feature 结尾的所有内容,因为如果我拉入整个 features 目录,它将拉入其下方的 所有内容,包括所有配置文件等,这是这不是我想要的,因为每个配置文件都将默认的水豚驱动程序设置为不同的值.一旦您将 -r 指定为 cucumber 的选项,all any 文件的自动加载将停止.

cucumber.yaml:
Here, the all_features file just does a glob of everything ending in .feature, because if I pulled in the entire features directory it would pull in everything beneath it, including all the profile files, etc, which isn't what I wanted since each profile file sets the default capybara driver to a different value. Once you specify -r as an option to cucumber, all autoloading of any file is halted.

default: --format pretty

chrome: --format pretty -r features/support/profiles/chrome.rb -r features/all_features -r features/step_definitions

firefox: --format pretty -r features/support/profiles/firefox.rb -r features/all_features -r features/step_definitions

celerity: --format pretty -r features/support/profiles/celerity.rb -r features/all_features -r features/step_definitions

firefox.rb(配置文件"文件):

firefox.rb (the 'profile' file):

require File.dirname(__FILE__) + "/../env.rb"

Capybara.configure do |config|
  config.default_driver = :selenium_firefox
end

selenium_firefox.rb(我在其中注册了驱动程序,并设置了一些我现在不需要的标签功能,因为 @selenium_firefox 标签是我最初尝试的一部分,发布在问题):

selenium_firefox.rb (where I register the driver, and set some tag capability which I've wound up not needing now, as the @selenium_firefox tag was part of my original attempt at this posted in the question):

# Register a specific selenium driver for firefox
Capybara.register_driver :selenium_firefox do |app|
  Capybara::Driver::Selenium.new(app, :browser => :firefox)
end

# Allows the use of a tag @selenium_firefox before a scenario to run it in selenium with firefox
Before('@selenium_firefox') do
  Capybara.current_driver = :selenium_firefox
end

feature_runner.thor:

feature_runner.thor:

require 'benchmark'

class FeatureRunner < Thor
  APP_ROOT = File.expand_path(File.dirname(__FILE__) + "/../")

  # One place to keep all the common feature runner options, since every runner in here uses them.
  # Modify here, and all runners below will reflect the changes, as they all call this proc.
  feature_runner_options = lambda { 
    method_option :verbose, :type => :boolean, :default => true, :aliases => "-v"
    method_option :tags, :type => :string
    method_option :formatter, :type => :string
    method_option :other_cucumber_args, :type => :string
  }


  desc "all_drivers_runner", "Run features in all available browsers"
  method_option :benchmark, :type => :boolean, :default => false
  method_option :threaded, :type => :boolean, :default => true
  feature_runner_options.call # Set up common feature runner options defined above
  def all_drivers_runner
    if options[:threaded]
      feature_run = lambda { 
        thread_pool = []

        t = Thread.new do |n|
          invoke :firefox_runner
        end
        thread_pool << t

        t = Thread.new do |n|
          invoke :chrome_runner
        end
        thread_pool << t

        t = Thread.new do |n|
          invoke :celerity_runner
        end
        thread_pool << t

        thread_pool.each {|th| th.join}
      }
    else
      feature_run = lambda { 
        invoke "feature_runner:firefox_runner", options
        invoke "feature_runner:chrome_runner", options
        invoke "feature_runner:celerity_runner", options
      }
    end

    if options[:benchmark]
      puts "Benchmarking feature run"
      measure = Benchmark.measure { feature_run.call }
      puts "Benchmark Results (in seconds):"
      puts "CPU Time: #{measure.utime}"
      puts "System CPU TIME: #{measure.stime}"
      puts "Elasped Real Time: #{measure.real}"
    else
      feature_run.call
    end
  end

  desc "firefox_runner", "Run features on firefox"
  feature_runner_options.call # Set up common feature runner options defined above
  def firefox_runner
    command = build_cucumber_command("firefox", options)
    run_command(command, options[:verbose])
  end

  desc "chrome_runner", "Run features on chrome"
  feature_runner_options.call # Set up common feature runner options defined above
  def chrome_runner
    command = build_cucumber_command("chrome", options)
    run_command(command, options[:verbose])
  end

  desc "celerity_runner", "Run features on celerity"
  feature_runner_options.call # Set up common feature runner options defined above
  def celerity_runner
    command = build_cucumber_command("celerity", options)
    run_command(command, options[:verbose])
  end

  private
  def build_cucumber_command(profile, options)
    command = "cd #{APP_ROOT} && ./bin/cucumber -p #{profile}"
    command += " --tags=#{options[:tags]}" if options[:tags]
    command += " --formatter=#{options[:formatter]}" if options[:formatter]
    command += " #{options[:other_cucumber_args]}" if options[:other_cucumber_args]
    command
  end

  def run_command(command, verbose)
    puts "Running: #{command}" if verbose
    output = `#{command}`
    puts output if verbose
  end

end

一切都结束了,相对于根目录:

Where everything wound up, in relation to the root directory:

.
|____cucumber.yml
|____features
| |____all_features.rb
| |____google_search.feature
| |____step_definitions
| | |____google_steps.rb
| | |____web_steps.rb
| |____support
| | |____custom_formatters
| | | |____blah.rb
| | |____env.rb
| | |____paths.rb
| | |____profiles
| | | |____celerity.rb
| | | |____chrome.rb
| | | |____firefox.rb
| | |____selenium_drivers
| | | |____selenium_chrome.rb
| | | |____selenium_firefox.rb
| | | |____selenium_ie.rb
| | | |____selenium_remote.rb
| | |____selenium_drivers.rb
|____tasks
| |____feature_runner.thor
| |____server_task.rb  

thor -T的输出

feature_runner
--------------
thor feature_runner:all_drivers_runner  # Run features in all available browsers
thor feature_runner:celerity_runner     # Run features on celerity
thor feature_runner:chrome_runner       # Run features on chrome
thor feature_runner:firefox_runner      # Run features on firefox  

现在我可以运行类似的东西:
thor feature_runner:all_drivers_runner --benchmark
这将为每个驱动程序在一个线程中运行所有水豚驱动程序上的所有功能,并对结果进行基准测试.

Now I can run something like:
thor feature_runner:all_drivers_runner --benchmark
This would run all features on all capybara drivers in a thread for each driver, benchmnarking the results.

或者
雷神 feature_runner:celerity_runner
这将仅在 celerity 上运行所有功能.

Or
thor feature_runner:celerity_runner
This would run all features only on celerity.

但我现在还可以为 thor 命令提供一些其他选项,这些选项会传递给 cucumber,例如:
--tags=@all_browsers
--formatter=hotpants
--other_cucumber_args="--dry-run --guess --etc"

But I can now also supply some other options to the thor command which get passed onto cucumber such as:
--tags=@all_browsers
--formatter=hotpants
--other_cucumber_args="--dry-run --guess --etc"

功能文件现在的样子:

Feature: Start up browser
  @all_browsers
  Scenario: Search Google
   Given I am on the home page
   When I fill in the search bar with "Capybara"
   And I press "Search"
   Then I should see "Capybara"

似乎需要进行很多设置,但现在如果我使用 @all_browsers 标记一个功能,我可以构建一个套件来测试所有 capybara 驱动程序,在多线程环境中,使用一个 thor 命令:
thor feature_runner:all_drivers_runner --threaded --tags=@all_browsers

Seems like a lot of setup, but now if I tag a feature with @all_browsers, I can build out a suite to test against all capybara drivers, in a multi-threaded environment, with one thor command:
thor feature_runner:all_drivers_runner --threaded --tags=@all_browsers

或者构建一个快速运行的冒烟测试套件:
thor feature_runner:celerity_runner --tags=@smoke_test

Or build out a smoke test suite that runs in celerity:
thor feature_runner:celerity_runner --tags=@smoke_test

这篇关于有没有人想出一种在多个浏览器/网络驱动程序上运行相同黄瓜场景的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆