Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>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:</p> <ol> <li>Abstracting all common environment stuff into <code>env.rb</code></li> <li>Using Cucumber profiles which would require a specific environment file (such as firefox.rb) that required <code>env.rb</code> and then set the default driver for Capybara to the appropriate driver.</li> <li>Wrote a big ol' <a href="https://github.com/wycats/thor#readme" rel="noreferrer">thor</a> class with tasks that bundle up a bunch of cucumber commands and call out to run the bad boy with the proper profile.</li> <li>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.</li> </ol> <p>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.</p> <p>cucumber.yaml:<br> 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 <em>everything</em> 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 <code>-r</code> as an option to cucumber, <em>all</em> autoloading of <em>any</em> file is halted. </p> <pre><code>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 </code></pre> <p>firefox.rb (the 'profile' file): </p> <pre><code>require File.dirname(__FILE__) + "/../env.rb" Capybara.configure do |config| config.default_driver = :selenium_firefox end </code></pre> <p>selenium_firefox.rb (where I register the driver, and set some tag capability which I've wound up not needing now, as the <code>@selenium_firefox</code> tag was part of my original attempt at this posted in the question):</p> <pre><code># Register a specific selenium driver for firefox Capybara.register_driver :selenium_firefox do |app| Capybara::Driver::Selenium.new(app, :browser =&gt; :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 </code></pre> <p>feature_runner.thor:</p> <pre><code>require 'benchmark' class FeatureRunner &lt; 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 =&gt; :boolean, :default =&gt; true, :aliases =&gt; "-v" method_option :tags, :type =&gt; :string method_option :formatter, :type =&gt; :string method_option :other_cucumber_args, :type =&gt; :string } desc "all_drivers_runner", "Run features in all available browsers" method_option :benchmark, :type =&gt; :boolean, :default =&gt; false method_option :threaded, :type =&gt; :boolean, :default =&gt; 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 &lt;&lt; t t = Thread.new do |n| invoke :chrome_runner end thread_pool &lt;&lt; t t = Thread.new do |n| invoke :celerity_runner end thread_pool &lt;&lt; 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} &amp;&amp; ./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 </code></pre> <p>Where everything wound up, in relation to the root directory: </p> <pre><code>. |____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 </code></pre> <p>Output of <code>thor -T</code> </p> <pre><code>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 </code></pre> <p>Now I can run something like:<br> <code>thor feature_runner:all_drivers_runner --benchmark</code><br> This would run all features on all capybara drivers in a thread for each driver, benchmnarking the results. </p> <p>Or<br> <code>thor feature_runner:celerity_runner</code><br> This would run all features only on celerity. </p> <p>But I can now also supply some other options to the thor command which get passed onto cucumber such as:<br> <code>--tags=@all_browsers</code><br> <code>--formatter=hotpants</code><br> <code>--other_cucumber_args="--dry-run --guess --etc"</code> </p> <p>What a feature file can now look like: </p> <pre><code>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" </code></pre> <p>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:<br> <code>thor feature_runner:all_drivers_runner --threaded --tags=@all_browsers</code></p> <p>Or build out a smoke test suite that runs in celerity:<br> <code>thor feature_runner:celerity_runner --tags=@smoke_test</code> </p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload