Кто-нибудь нашел способ запустить один и тот же сценарий огурца на нескольких браузерах / веб-драйверах? - PullRequest
10 голосов
/ 08 декабря 2010

Я использую огурец + капибару для тестирования веб-автоматизации.Я хотел бы иметь возможность подключить свой собственный тег (что-то вроде @all_browsers перед сценарием) и запускать его в соответствии со списком установленных мной веб-драйверов (быстродействие, селен в Firefox, т.е. и 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 ]

9 голосов
/ 10 декабря 2010

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

  1. Абстрагирование всех общих элементов среды в env.rb
  2. Использование профилей Cucumber, которые потребовали быопределенный файл среды (например, firefox.rb), для которого требуется env.rb, а затем установите драйвер по умолчанию для Capybara на соответствующий драйвер.
  3. Написал большой старый класс thor с задачами, которыесвязать кучу команд огурца и вызвать плохого парня с нужным профилем.
  4. Написал задачу 'all_browsers', которая объединяет команды, а затем вызывает каждую конкретную задачу драйвера, так что я могутеперь есть одно задание, которое запускает любой набор сценариев, которые я предоставляю для всех поддерживаемых драйверов.

Работая как шарм, и я думаю, что в конечном итоге, возможно, получилось лучше, чем все, что я пробовал выше,как и в файле Thor, я смог добавить такие вещи, как опцию бенчмаркинга, а также разделить или нет функцию разбить нанесколько потоков.Тем не менее, все еще любопытно, если кто-то еще придумал решение для этого.

cucumber.yaml:
Здесь файл all_features просто делает все, что заканчивается на .feature, потому что если я вытяну весьКаталог функций, в который он поместил бы все под ним, включая все файлы профиля и т. д., это не то, что я хотел, так как каждый файл профиля устанавливает драйвер капибары по умолчанию на свое значение.Как только вы укажете -r в качестве опции для огурца, all автозагрузка любого файла будет остановлена.

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

Где все завелосьОтносительно корневого каталога:

.
|____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
Это будет работатьвсе функции на всех драйверах капибары в потоке для каждого драйвера, сравнивая результаты.

Или
thor feature_runner:celerity_runner
Все функции будут работать только на скорости.

Но теперь я могу также предоставить некоторые другие опции для команды тор, которые передаются на огурец, такие как:
--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, я могу создать пакет для тестирования всех драйверов капибары,в многопоточной среде с помощью одной команды tor:
thor feature_runner:all_drivers_runner --threaded --tags=@all_browsers

Или создать набор тестов дыма, работающий с высокой скоростью:
thor feature_runner:celerity_runner --tags=@smoke_test

0 голосов
/ 23 февраля 2017

Я делаю это так, как рекомендует проект 'watir'. Я использую require parallel_cucumber в своем Rakefile, и тогда каждый сценарий Cucumber получает свой собственный параллельный поток (в нашем случае до 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

0 голосов
/ 10 декабря 2010

Вот мой хак: (моя ситуация доказывает, что функция работает с включенным JavaScript и выключенным JavaScript)

  1. Поместите каждый сценарий в свой собственный файл функций.
  2. Переместить каждую строку, кроме последней, в раздел «Background:».
  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"
    
0 голосов
/ 08 декабря 2010

Это возможно через сервис SauceLabs. Драгоценный камень Cucumber Sauce позволяет проводить параллельные тесты в нескольких браузерах.

В качестве альтернативы, вы можете позаимствовать у источника этого драгоценного камня, если вы хотите реализовать его самостоятельно.

...