Кто-нибудь выяснил, как запустить один и тот же сценарий огурца в нескольких браузерах/веб-драйверах?
Я использую cucumber + capybara для некоторого тестирования веб-автоматизации. Я хотел бы иметь возможность подключить свой собственный тег (что-то вроде @all_browsers перед сценарием) и запустить его против списка веб-драйверов, которые я установил (скорость, селен в firefox, ie и chrome). Я не хочу писать сценарий 4 раза с 4 разными тегами снаружи. Я изучил попытку сделать это с новым драйвером, который я регистрирую через:
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
но я не совсем уверен, что положить в это перед методом, который может действительно работать.
Я пробовал использовать огуречные крючки, в частности:
Around('@all_browsers') do |scenario, block|
Capybara.current_driver = :selenium_firefox
block.call
Capybara.current_driver = :selenium_chrome
block.call
# etc
end
но это не так, как я надеялся. Он использует один и тот же драйвер и дважды запускает сценарий с ним.
следуя вдоль линий крючка, есть это из документации огурца: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...
Это может быть потенциальный путь для этого, но я не удалось придумать все, что здесь работает.
Я просмотрел пользовательские форматеры, но они действительно выглядят только так, как будто они делают именно это - форматируют вывод, а не столько обозначают, как на самом деле выполняются функции.
Я посмотрел на переопределение функции бегуна огурца, но это не выглядит легким или дружелюбным.
Помогите пожалуйста? Кто?
4 ответов
Итак, я закончил сворачивать свое собственное решение. Не уверен, что это был лучший или самый элегантный подход, но я на самом деле просто завелся:
- абстрагирование всех общих вещей окружающей среды в
env.rb
- использование профилей Cucumber, для которых требуется определенный файл среды (например, firefox.РБ), что требуется
env.rb
а затем установите драйвер по умолчанию для Capybara в соответствующий драйвер. - написал большой ol' Тор класс с задачами, которые связывают кучу команд огурца и призывают запустить плохого мальчика с правильным профилем.
- написал задачу "all_browsers", которая связывает команды, а затем вызывает каждую конкретную задачу драйвера, поэтому теперь у меня может быть одна задача, которая запускает любой набор сценариев, которые я предоставляю на всех поддерживаемых драйверах.
работает как шарм, и я думаю, что, возможно, на самом деле получилось лучше, чем все, что я пытался выше, как в файле Thor Я смог добавить такие вещи, как вариант бенчмаркинга, а также разделить функцию на несколько потоков. Все еще любопытно, если кто-то еще придумал решение для этого.
огурец.и YAML:
Здесь файл all_features просто делает Глоб всего, что заканчивается .особенность, потому что если бы я вытащил весь каталог функций, он бы вытащил все под ним, включая все файлы профиля, и т. д., которые не то, что я хотел поскольку каждый файл профиля устанавливает драйвер capybara по умолчанию для другого значения. Как только вы укажете -r
как вариант огурец, все Автозагрузка любой прекращено.
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 (файл "профиль"):
require File.dirname(__FILE__) + "/../env.rb"
Capybara.configure do |config|
config.default_driver = :selenium_firefox
end
selenium_firefox.rb (где я регистрирую драйвер и устанавливаю некоторые возможности тегов, которые мне сейчас не нужны, как @selenium_firefox
тег был частью моей первоначальной попытки это опубликовано в вопрос):
# 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.Тор:
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
где все завертелось, по отношению к корневому каталогу:
.
|____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
Это будет запускать все функции на всех драйверах capybara в потоке для каждого драйвера, benchmnarking результаты.
илиthor feature_runner:celerity_runner
Это будет запускать все функции только на celerity.
но теперь я могу также предоставить некоторые другие опции команде thor, которые передаются на огурец, такие как:--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
или создать набор тестов дыма, который работает в скорости:thor feature_runner:celerity_runner --tags=@smoke_test
Это возможно через размещенную службу SauceLabs. The Огуречным Соусом gem дает вам параллельные, мульти-браузерные тесты.
кроме того, вы можете заимствовать из источника этого драгоценного камня, если хотите реализовать его самостоятельно.
вот мой Хак: (моя ситуация доказывает, что функция работает с javascript on и javascript off)
- поместите каждый сценарий в свой собственный файл функций.
- переместите каждую строку, кроме последней, в раздел " фон:".
- поместите последнюю строку в сценарий для каждого браузера
-
помечайте каждый сценарий соответствующим образом
Feature: a feature Background: Given a user "Jim" exists Given a user "Mike" exists When I login as "mike" And I follow "Lesson 1" And I follow "Upload a video" Then "#upload_a_video" should be active And I fill in "video_title" with "my film" And I attach the file "video.mov" to "video_upload" And I press "Post" Scenario: normal And I should see "my film" @javascript Scenario: javascript And I should see "my film"
Я делаю это так, как рекомендует проект "watir". Я использую require parallel_cucumber
в моем Rakefile, а затем каждый сценарий огурца получает свой собственный параллельный поток (в этом случае до 20):
task :run_cucumber do
FileUtils.mkpath(ENV['OUT_DIR'])
begin
# cannot format report as HTML because of parallel forking
threads = 20
@result = system "parallel_cucumber features -o \"--format junit --out #{ENV['OUT_DIR']} --format pretty --tag @sauce\" -n #{threads}"
ensure
@success &= @result
end
end
тогда оставшаяся часть вашего проекта Cucumber может быть написана как обычно!! Так просто! Мой полный пример здесь: https://github.com/djangofan/cuke-parallel-starter