Кто-нибудь выяснил, как запустить один и тот же сценарий огурца в нескольких браузерах/веб-драйверах?

Я использую 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 ответов


Итак, я закончил сворачивать свое собственное решение. Не уверен, что это был лучший или самый элегантный подход, но я на самом деле просто завелся:

  1. абстрагирование всех общих вещей окружающей среды в env.rb
  2. использование профилей Cucumber, для которых требуется определенный файл среды (например, firefox.РБ), что требуется env.rb а затем установите драйвер по умолчанию для Capybara в соответствующий драйвер.
  3. написал большой ol' Тор класс с задачами, которые связывают кучу команд огурца и призывают запустить плохого мальчика с правильным профилем.
  4. написал задачу "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)

  1. поместите каждый сценарий в свой собственный файл функций.
  2. переместите каждую строку, кроме последней, в раздел " фон:".
  3. поместите последнюю строку в сценарий для каждого браузера
  4. помечайте каждый сценарий соответствующим образом

    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