From 849a4efda88fdb908c02529a2211d1d21be81f83 Mon Sep 17 00:00:00 2001 From: Nate Clark Date: Wed, 16 Dec 2009 17:27:06 -0800 Subject: [PATCH] adds support to run Jasmine suites on CI using Sauce Labs --- Rakefile | 33 ++++++++----- contrib/ruby/jasmine_runner.rb | 77 +++++++++++++++++++++++------- examples/ruby/Rakefile | 19 ++++++-- examples/ruby/spec/jasmine_spec.rb | 17 +++++-- examples/ruby/spec/saucelabs.yml | 24 ++++++++++ geminstaller.yml | 3 ++ spec/jasmine_spec.rb | 17 +++++-- spec/saucelabs.yml | 24 ++++++++++ 8 files changed, 171 insertions(+), 43 deletions(-) create mode 100644 examples/ruby/spec/saucelabs.yml create mode 100644 spec/saucelabs.yml diff --git a/Rakefile b/Rakefile index 4ce8838..2bb0f6e 100644 --- a/Rakefile +++ b/Rakefile @@ -59,7 +59,7 @@ namespace :jasmine do task :build => :lint do puts 'Building Jasmine from source' require 'json' - + sources = jasmine_sources version = version_hash @@ -119,17 +119,26 @@ jasmine.version_= { end namespace :test do - desc "Run continuous integration tests" - task :ci => 'jasmine:build' do - require "spec" - require 'spec/rake/spectask' - Spec::Rake::SpecTask.new(:lambda_ci) do |t| - t.spec_opts = ["--color", "--format", "specdoc"] - t.spec_files = ["spec/jasmine_spec.rb"] - end - Rake::Task[:lambda_ci].invoke - end + desc "Run continuous integration tests using a local Selenium runner" + task :ci => :'ci:local' + namespace :ci do + task :local => 'jasmine:build' do + require "spec" + require 'spec/rake/spectask' + Spec::Rake::SpecTask.new(:lambda_ci) do |t| + t.spec_opts = ["--color", "--format", "specdoc"] + t.spec_files = ["spec/jasmine_spec.rb"] + end + Rake::Task[:lambda_ci].invoke + end + + desc "Run continuous integration tests using Sauce Labs 'Selenium in the Cloud'" + task :saucelabs => 'jasmine:build' do + ENV['SAUCELABS'] = 'true' + Rake::Task['jasmine:test:ci:local'].invoke + end + end end -end \ No newline at end of file +end diff --git a/contrib/ruby/jasmine_runner.rb b/contrib/ruby/jasmine_runner.rb index 5a6b1ef..2388396 100644 --- a/contrib/ruby/jasmine_runner.rb +++ b/contrib/ruby/jasmine_runner.rb @@ -228,46 +228,53 @@ module Jasmine @browser = options[:browser] ? options[:browser].delete(:browser) : 'firefox' @selenium_pid = nil @jasmine_server_pid = nil + @selenium_host = 'localhost' + @jasmine_server_port = Jasmine::find_unused_port + @selenium_server_port = Jasmine::find_unused_port end def start - start_servers - @client = Jasmine::SimpleClient.new("localhost", @selenium_server_port, "*#{@browser}", "http://localhost:#{@jasmine_server_port}/") + start_jasmine_server + start_selenium_server + @client = Jasmine::SimpleClient.new(@selenium_host, @selenium_server_port, "*#{@browser}", "http://localhost:#{@jasmine_server_port}/") @client.connect end def stop @client.disconnect - stop_servers + stop_selenium_server + stop_jasmine_server end - def start_servers - @jasmine_server_port = Jasmine::find_unused_port - @selenium_server_port = Jasmine::find_unused_port - - @selenium_pid = fork do - Process.setpgrp - exec "java -jar #{@selenium_jar_path} -port #{@selenium_server_port} > /dev/null 2>&1" - end - puts "selenium started. pid is #{@selenium_pid}" - + def start_jasmine_server @jasmine_server_pid = fork do Process.setpgrp Jasmine::SimpleServer.start(@jasmine_server_port, @spec_files, @dir_mappings, @options) exit! 0 end puts "jasmine server started. pid is #{@jasmine_server_pid}" - - Jasmine::wait_for_listener(@selenium_server_port, "selenium server") Jasmine::wait_for_listener(@jasmine_server_port, "jasmine server") end - def stop_servers - puts "shutting down the servers..." - Jasmine::kill_process_group(@selenium_pid) if @selenium_pid + def start_selenium_server + @selenium_pid = fork do + Process.setpgrp + exec "java -jar #{@selenium_jar_path} -port #{@selenium_server_port} > /dev/null 2>&1" + end + puts "selenium started. pid is #{@selenium_pid}" + Jasmine::wait_for_listener(@selenium_server_port, "selenium server") + end + + def stop_jasmine_server + puts "shutting down Jasmine server..." Jasmine::kill_process_group(@jasmine_server_pid) if @jasmine_server_pid end + def stop_selenium_server + puts "shutting down Selenium server..." + Jasmine::kill_process_group(@selenium_pid) if @selenium_pid + end + def run begin start @@ -284,6 +291,40 @@ module Jasmine end end + class SauceLabsRunner < Runner + def initialize(spec_files, dir_mappings, options={}) + @spec_files = spec_files + @dir_mappings = dir_mappings + @options = options + + @browser = options[:browser] ? options[:browser].delete(:browser) : 'firefox' + @jasmine_server_pid = nil + @jasmine_server_port = Jasmine::find_unused_port + @saucelabs_config = SeleniumConfig.new(options[:saucelabs_config], options[:saucelabs_config_file], @jasmine_server_port) + end + + def start_selenium_server + @sauce_tunnel = SauceTunnel.new(@saucelabs_config) + end + + def start + start_jasmine_server + start_selenium_server + @client = Jasmine::SimpleClient.new(@saucelabs_config['selenium_server_address'], + 4444, + @saucelabs_config['selenium_browser_key'], + "http://#{@saucelabs_config['application_address']}") + @client.connect + end + + def stop + @client.disconnect + @sauce_tunnel.shutdown + stop_jasmine_server + end + + end + def self.files(f) result = f result = result.call if result.respond_to?(:call) diff --git a/examples/ruby/Rakefile b/examples/ruby/Rakefile index 9cf3592..4196c32 100644 --- a/examples/ruby/Rakefile +++ b/examples/ruby/Rakefile @@ -2,12 +2,21 @@ require File.expand_path(File.join(File.dirname(__FILE__), "spec/jasmine_helper. namespace :test do desc "Run continuous integration tests" - require "spec" - require 'spec/rake/spectask' + task :ci => :'ci:local' + namespace :ci do + require "spec" + require 'spec/rake/spectask' - Spec::Rake::SpecTask.new(:ci) do |t| - t.spec_opts = ["--color", "--format", "specdoc"] - t.spec_files = ["spec/jasmine_spec.rb"] + Spec::Rake::SpecTask.new(:local) do |t| + t.spec_opts = ["--color", "--format", "specdoc"] + t.spec_files = ["spec/jasmine_spec.rb"] + end + + desc "Run continuous integration tests using Sauce Labs 'Selenium in the Cloud'" + task :saucelabs do + ENV['SAUCELABS'] = 'true' + Rake::Task['test:ci:local'].invoke + end end end diff --git a/examples/ruby/spec/jasmine_spec.rb b/examples/ruby/spec/jasmine_spec.rb index ce15f00..1b37d8b 100644 --- a/examples/ruby/spec/jasmine_spec.rb +++ b/examples/ruby/spec/jasmine_spec.rb @@ -1,11 +1,20 @@ require 'rubygems' -require "selenium_rc" require File.expand_path(File.join(File.dirname(__FILE__), "jasmine_helper.rb")) require File.expand_path(File.join(JasmineHelper.jasmine_root, "contrib/ruby/jasmine_spec_builder")) -jasmine_runner = Jasmine::Runner.new(SeleniumRC::Server.new.jar_path, - JasmineHelper.specs, - JasmineHelper.dir_mappings) +jasmine_runner = if ENV['SAUCELABS'] == 'true' + require 'sauce_tunnel' + require 'selenium_config' + Jasmine::SauceLabsRunner.new(JasmineHelper.specs, + JasmineHelper.dir_mappings, + :saucelabs_config => 'saucelabs', + :saucelabs_config_file => File.expand_path(File.join(File.dirname(__FILE__), "saucelabs.yml"))) +else + require "selenium_rc" + Jasmine::Runner.new(SeleniumRC::Server.new.jar_path, + JasmineHelper.specs, + JasmineHelper.dir_mappings) +end spec_builder = Jasmine::SpecBuilder.new(JasmineHelper.raw_spec_files, jasmine_runner) diff --git a/examples/ruby/spec/saucelabs.yml b/examples/ruby/spec/saucelabs.yml new file mode 100644 index 0000000..8a46d1c --- /dev/null +++ b/examples/ruby/spec/saucelabs.yml @@ -0,0 +1,24 @@ +local: + application_framework: :selenium +# +# Possible Sauce Labs configurations as of 2009/11/19 +# From: http://saucelabs.com/products/docs/sauce-ondemand/browsers +# os: "Windows 2003" +# browser: "iexplore" +# browser-version: "6.", "7.", "8." +# browser: "firefox" +# browser-version: "2.", "3.0", "3.5" +# browser: "safari" +# browser-version: "3.", "4." +# browser: "opera" +# browser-version: "9." +# browser: "googlechrome" +# browser-version: "" +# os: "Linux" +# browser: "firefox" +# browser-version: "3." +saucelabs: + application_framework: :external + selenium_server_address: "saucelabs.com" + selenium_browser_key: '{"username": "--YOUR-SAUCELABS-USERNAME--", "access-key": "--YOUR-SAUCELABS-ACCESS-KEY--", "os": "Linux", "browser": "firefox", "browser-version": "3."}' + application_port: "80" diff --git a/geminstaller.yml b/geminstaller.yml index 860e086..780400c 100644 --- a/geminstaller.yml +++ b/geminstaller.yml @@ -18,3 +18,6 @@ gems: version: 1.2.9 - name: selenium-client version: 1.2.17 +- name: saucelabs-adapter + version: 0.3.2 + install_options: --source=http://gems.pivotallabs.com diff --git a/spec/jasmine_spec.rb b/spec/jasmine_spec.rb index ce15f00..1b37d8b 100644 --- a/spec/jasmine_spec.rb +++ b/spec/jasmine_spec.rb @@ -1,11 +1,20 @@ require 'rubygems' -require "selenium_rc" require File.expand_path(File.join(File.dirname(__FILE__), "jasmine_helper.rb")) require File.expand_path(File.join(JasmineHelper.jasmine_root, "contrib/ruby/jasmine_spec_builder")) -jasmine_runner = Jasmine::Runner.new(SeleniumRC::Server.new.jar_path, - JasmineHelper.specs, - JasmineHelper.dir_mappings) +jasmine_runner = if ENV['SAUCELABS'] == 'true' + require 'sauce_tunnel' + require 'selenium_config' + Jasmine::SauceLabsRunner.new(JasmineHelper.specs, + JasmineHelper.dir_mappings, + :saucelabs_config => 'saucelabs', + :saucelabs_config_file => File.expand_path(File.join(File.dirname(__FILE__), "saucelabs.yml"))) +else + require "selenium_rc" + Jasmine::Runner.new(SeleniumRC::Server.new.jar_path, + JasmineHelper.specs, + JasmineHelper.dir_mappings) +end spec_builder = Jasmine::SpecBuilder.new(JasmineHelper.raw_spec_files, jasmine_runner) diff --git a/spec/saucelabs.yml b/spec/saucelabs.yml new file mode 100644 index 0000000..8a46d1c --- /dev/null +++ b/spec/saucelabs.yml @@ -0,0 +1,24 @@ +local: + application_framework: :selenium +# +# Possible Sauce Labs configurations as of 2009/11/19 +# From: http://saucelabs.com/products/docs/sauce-ondemand/browsers +# os: "Windows 2003" +# browser: "iexplore" +# browser-version: "6.", "7.", "8." +# browser: "firefox" +# browser-version: "2.", "3.0", "3.5" +# browser: "safari" +# browser-version: "3.", "4." +# browser: "opera" +# browser-version: "9." +# browser: "googlechrome" +# browser-version: "" +# os: "Linux" +# browser: "firefox" +# browser-version: "3." +saucelabs: + application_framework: :external + selenium_server_address: "saucelabs.com" + selenium_browser_key: '{"username": "--YOUR-SAUCELABS-USERNAME--", "access-key": "--YOUR-SAUCELABS-ACCESS-KEY--", "os": "Linux", "browser": "firefox", "browser-version": "3."}' + application_port: "80"