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

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

问题描述

我使用黄瓜+ capybara进行一些网络自动化测试。我想能够连接我自己的标签(像场景之前的@all_browsers),并使其运行在我设置的web驱动程序列表(celerity,在firefox上的硒,ie和chrome)。我不想要写4个不同的时间与4个不同的标签前面的场景。我试图尝试这样做与一个新的驱动程序我注册通过:

  Capybara.register_driver:all_browsers do | app | 
#什么甚至可以在这里工作?我不认为会有什么事情。
end

然后跟着:

  Before('@ all_browsers')do 
#同样的问题。
end

但我不太确定在Before方法实际工作。



我尝试过使用黄瓜钩,特别是:

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

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

但这不符合我的预期。它使用相同的驱动程序并运行场景两次。



沿着钩子线,黄瓜文档中有以下内容:

您还可以提供一个AfterConfiguration钩子,将在配置Cucumber后运行。这个钩子只会运行一次;在加载支持之后但在加载功能之前。你可以使用这个钩子扩展Cucumber,例如你可以影响如何加载功能...

这可能是一个潜在的路径,为此, ve没有设法想出任何在这里工作的东西。



我已经查看过自定义格式化程序,但是他们只是看起来像他们做的那样 - 格式化输出,而不是指定如何实际运行功能。 / p>

我已经研究了黄瓜的特色运动员,但这看起来不容易或不友好。

请帮助?

解决方案

所以,我绕过了自己的解决方案。不确定这是最好还是最优雅的方法,但我实际上刚刚结束:


  1. 将所有常见环境的东西抽象为 env.rb

  2. 使用Cucumber配置文件需要一个特定的环境文件(如firefox.rb),需要 env .rb ,然后将Capybara的默认驱动程序设置为相应的驱动程序。

  3. 写了一个大的' thor 类,其任务捆绑了一堆黄瓜命令,并调用以正确的配置文件运行坏男孩。

  4. 写了一个'all_browsers'任务,它捆绑了命令,然后调用每个特定的驱动程序任务,所以我现在可以有一个任务运行我提供的所有支持的驱动程序的任何集合。

工作像一个魅力,我认为可能实际上最好比任何我上面尝试,在Thor文件内,我能够添加诸如基准选项之类的功能,以及是否将功能分成多个线程。
仍然很好奇,如果任何人想出了一个解决方案,虽然。



cucumber.yaml:

这里,all_features文件做一个glob的所有结束于.feature,因为如果我拉入整个功能目录,它会拉在它下面的所有,包括所有的配置文件等,这不是我想要的,因为每个配置文件将默认大小写驱动程序设置为不同的值。一旦您指定 -r 作为cucumber的选项,就会暂停任何文件的所有自动加载。

 默认值:--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('profile'文件):

  require File.dirname(__ FILE__)+/../env.rb

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

selenium_firefox.rb注册驱动程序,并设置一些标签功能,我已经清理不需要现在,因为 @selenium_firefox 标签是我原来尝试在此问题的一部分) :

 #为firefox注册一个特定的selenium驱动程序
Capybara.register_driver:selenium_firefox do | app |
Capybara :: Driver :: Selenium.new(app,:browser =>:firefox)
end

#允许在场景之前使用标签@selenium_firefox使用firefox在selenium中运行它
Before('@ selenium_firefox')do
Capybara.current_driver =:selenium_firefox
end

feature_runner.thor:

  require'benchmark'

class FeatureRunner< Thor
APP_ROOT = File.expand_path(File.dirname(__ FILE__)+/../)

#一个地方保存所有常见的特色跑步选项,因为每个跑步者在这里使用它们。
#修改这里,下面所有的运行者都会反映这些改变,因为他们都称为这个过程。
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
}


descall_drivers_runner,在所有可用浏览器中运行功能
method_option:benchmark,:type => :boolean,:default => false
method_option:threaded,:type => :boolean,:default => true
feature_runner_options.call#设置上面定义的通用特性选择器选项
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 {
调用feature_runner:firefox_runner,选项
调用feature_runner:chrome_runner,选项
invokefeature_runner:celerity_runner,options
}
end

如果options [:benchmark]
输入Benchmarking feature run
measure = Benchmark。测量{feature_run.call}
输入基准测试结果(以秒为单位):
putsCPU时间:#{measure.utime}
puts系统CPU时间: stime}
putsElasped Real Time:#{measure.real}
else
feature_run.call
end
end

descfirefox_runner,在Firefox上运行功能
feature_runner_options.call#设置上面定义的常用功能选项
def firefox_runner
command = build_cucumber_command(firefox,options)
run_command(command,options [:verbose])
end

descchrome_runner,在Chrome上运行功能
feature_runner_options.call#上面
def chrome_runner
command = build_cucumber_command(chrome,options)
run_command(command,options [:verbose])
end

desc celerity_runner,在celerity上运行功能
feature_runner_options.call#设置上面定义的常用功能部件选项
def celerity_runner
command = build_cucumber_command(celerity,options)
run_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}`
则输出Running:#{command} b $ b end

end

根目录:

 
| ____ cucumber.yml
| ____ features
| | ____ all_features .rb
| | ____ google_search.feature
| | ____ step_definitions
| | | ____ google_steps.rb
| | | ____ web_steps.rb
| | ____支持
| | | ____ custom_formatters
| | | | ____ blah.rb
| | | ____ env.rb
| | | ____ paths.rb
| | | ____个人资料
| | | ____ 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#在所有可用浏览器中运行功能
thor feature_runner:celerity_runner#在celerity上运行功能
thor feature_runner:chrome_runner#在chrome上运行功能
thor feature_runner:firefox_runner#在Firefox上运行功能

现在我可以运行像:

thor feature_runner: all_drivers_runner --benchmark

这将在每个驱动程序的一个线程中运行所有的capybara驱动程序的所有功能,benchmnarking的结果。





thor feature_runner:celerity_runner

所有功能只在波速。



但我现在还可以提供一些其他选项给thor命令,它传递到黄瓜,如:

-tags = @ all_browsers

- formatter = hotpants

--other_cucumber_args = - dry-run --guess --etc



功能文件现在可以是什么样子: p>

 功能:启动浏览器
@all_browsers
场景:搜索Google
首页
当我在搜索栏中填入Capybara
然后按搜索
然后我会看到Capybara

看起来像很多设置,但现在如果我用@all_browsers标记一个功能,我可以建立一个套件来测试所有的水豚驱动程序,在多线程环境,使用一个thor命令:

thor feature_runner:all_drivers_runner --threaded --tags = @ all_browsers



或建立一个以速度运行的烟雾测试套件:

thor feature_runner:celerity_runner --tags = @ smoke_test


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  

And then following it up with:

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

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.

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.

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. 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.

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.

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 (the 'profile' file):

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

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

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:

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  

Output of 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  

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.

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

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"

What a feature file can now look like:

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"

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

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

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

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