sauce-test 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,57 @@
1
+ = RSpec
2
+
3
+ * http://rspec.info
4
+ * http://rubyforge.org/projects/rspec
5
+ * http://github.com/dchelimsky/rspec/wikis
6
+ * mailto:rspec-users@rubyforge.org
7
+ * mailto:rspec-devel@rubyforge.org
8
+
9
+ == DESCRIPTION:
10
+
11
+ SauceTest lets you run your Selenium tests on Sauce Labs cloud unchanged.
12
+
13
+ sauce_test is command line utility you can use
14
+ or create rake task and run your tests in parallel
15
+
16
+ == SYNOPSIS:
17
+
18
+ 1. create new rake task, should look like that:
19
+
20
+ only 'files' field is mandatory
21
+
22
+ require 'rubygems'
23
+ require 'rake'
24
+ require 'sauce-test/rake/tasks'
25
+
26
+ SauceTest::Rake::RSpecTask.new do |t|
27
+ t.files = 'spec/**/*_spec.rb' # Dir.glob pattern
28
+
29
+ t.browsers = [{'os' => "Linux", 'name' => "firefox", 'version' => 3},
30
+ {'os' => "Windows 2003", 'name' => "iexplore", 'version' => 7}]
31
+
32
+ t.workers = 4 #workers per browser
33
+
34
+ t.report = 'path_to/report'
35
+ t.config = 'config/sauce.yml'
36
+ end
37
+
38
+
39
+
40
+
41
+
42
+ 2. create sauce.yml file in config dir.
43
+ if you like to use different dir/file make sure that SAUCE_CONFIG env variable contains path to config file. .
44
+ example sauce.yml
45
+
46
+ login: user
47
+ key: ff487724-2sfe-4a50-8365-sc750f2d875f
48
+ timeout: 180 #optional but advised to be at least 90 sec
49
+
50
+
51
+ 3. rake sauce:spec
52
+
53
+ == INSTALL:
54
+
55
+ [sudo] gem install rspec
56
+
57
+
@@ -0,0 +1,3 @@
1
+ TestUnit support
2
+ nicer reports
3
+ incomplete browser string in rake tasks
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
3
+ require 'sauce-test/runner'
4
+ SauceTest::Runner.run
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'sauce-test/rake/tasks'
4
+
5
+
6
+ SauceTest::Rake::RSpecTask.new do |t|
7
+ t.files = 'spec/**/*_spec.rb'
8
+ t.workers = 4
9
+ end
@@ -0,0 +1,3 @@
1
+ login:
2
+ key:
3
+ timeout: 180
@@ -0,0 +1,21 @@
1
+ class GooglePage < Selenium::Client::Driver
2
+
3
+ def initialize()
4
+ super( :host => "localhost",
5
+ :port => 4444,
6
+ :browser => '*chrome',
7
+ :url => "http://www.google.com",
8
+ :timeout_in_second => 60 )
9
+ end
10
+
11
+
12
+ def search_for(search_str)
13
+ self.type "q", search_str
14
+ self.click "btnG", :wait_for => :page
15
+ end
16
+
17
+ def query_str
18
+ self.value("q")
19
+ end
20
+
21
+ end
@@ -0,0 +1,37 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe "Google Search" do
4
+
5
+ before(:all) do
6
+ @page = GooglePage.new
7
+ end
8
+
9
+ before(:each) do
10
+ @page.start
11
+ end
12
+
13
+ append_after(:each) do
14
+ @page.stop
15
+ end
16
+
17
+ it "can find Selenium" do
18
+ @page.open "/"
19
+ @page.title.should eql("Google")
20
+ @page.search_for "Selenium"
21
+ @page.query_str.should eql("Selenium")
22
+ @page.title.should eql("Selenium - Google Search")
23
+ @page.text?("seniumhq.org").should be_true
24
+ end
25
+
26
+ it "should return Sauce Labs website as top result" do
27
+ @page.open "/"
28
+ @page.title.should eql("Google")
29
+ @page.search_for "Sauce Labs"
30
+ @page.query_str.should eql("Sauce Labs")
31
+ @page.title.should eql("Sauce Labs - Google Search")
32
+ @page.text?("saucelabs.com").should be_true
33
+ end
34
+
35
+
36
+
37
+ end
@@ -0,0 +1,97 @@
1
+ <!DOCTYPE html
2
+ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5
+ <head>
6
+ <title>SauceTest Report</title>
7
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
8
+ <meta http-equiv="Expires" content="-1" />
9
+ <meta http-equiv="Pragma" content="no-cache" />
10
+ </head>
11
+ <body>
12
+
13
+
14
+
15
+ <div class="sauce-report">
16
+
17
+ <div id="sauce-header">
18
+ <div id="summary">
19
+ <p id="file">/home/bart/Projects/sauce-test/examples/google_search/spec/selenium/google_spec.rb</p>
20
+ <p id="browser">
21
+ googlechrome 1 on Windows 2003
22
+ </p>
23
+ <p id="totals">
24
+ 3 examples
25
+ , 1 FAILED
26
+ , 1 pending
27
+ </p>
28
+ <p id="duration">Duration: 42.071908 sec</p>
29
+ </div>
30
+ </div>
31
+
32
+ <div class="results">
33
+ <div class=example_group">
34
+
35
+
36
+
37
+ <dl>
38
+ <dt>Google Search</dt>
39
+
40
+
41
+
42
+
43
+ <dd class="failed">
44
+ <span class="failed_name">can find Selenium
45
+ <a class="job_link" href="http://saucelabs.com/jobs/dcd89827c758495ca782bcf1c66a1e05">(Sauce Labs Job)</a></span>
46
+ <div class="failure">
47
+ <div class="message"><pre>
48
+ expected true, got false
49
+ </pre></div>
50
+ <div class="backtrace"><pre>
51
+ /home/bart/Projects/sauce-test/examples/google_search/spec/selenium/google_spec.rb:23
52
+ </pre></div>
53
+ </div>
54
+ </dd>
55
+
56
+
57
+
58
+
59
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+ <dd class="passed">
67
+ <span class="passed_name">should return Sauce Labs website as top result
68
+ <a class="job_link" href="http://saucelabs.com/jobs/d7e4b4e1f0ce6fe4985a4896ac70d025">(Sauce Labs Job)</a></span>
69
+ </dd>
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+ <dd class="pending">
82
+ <span class="pending_name">is pend PENDING: blabla</span>
83
+ </dd>
84
+
85
+
86
+
87
+
88
+ </dl>
89
+
90
+
91
+
92
+ </div>
93
+ </div>
94
+
95
+
96
+ </body>
97
+ </html>
@@ -0,0 +1,4 @@
1
+ require "rubygems"
2
+ require "selenium/client"
3
+
4
+ require File.dirname(__FILE__) + '/../helpers/google_test_helper'
@@ -0,0 +1,104 @@
1
+ require 'yaml'
2
+ require 'stringio'
3
+ require 'thread'
4
+ require 'erb'
5
+
6
+ require 'sauce-test/runner'
7
+
8
+ module SauceTest
9
+ module Collection
10
+
11
+ class << self
12
+ include ERB::Util
13
+
14
+ def run(files, browsers, workers, config, report, type)
15
+ bin_path = File.expand_path(File.dirname(__FILE__) + '/../../bin')
16
+ ENV['PATH'] = bin_path + ':' + ENV['PATH']
17
+ test_array = []
18
+ test_array_mutex = Mutex.new
19
+ @test_result = []
20
+ test_result_mutex = Mutex.new
21
+
22
+ Dir.glob(files) do |file|
23
+ sauce_test = 'sauce_test -l -t ' + type.to_s + ' ' + file
24
+ result = `#{sauce_test}`
25
+
26
+ groups = YAML::load(StringIO.new result)['groups']
27
+
28
+ groups.each do |group|
29
+ group['examples'].each do |example|
30
+ test_array << [file,
31
+ group['name'],
32
+ example['name'],
33
+ example['full_name']]
34
+ end
35
+ end
36
+ end
37
+
38
+ browser_threads = []
39
+ worker_threads = []
40
+
41
+ browsers.each do |b|
42
+ browser_threads << Thread.new(b) do |browser|
43
+ test_count = 0
44
+ test_count_mutex = Mutex.new
45
+ (1..workers).each do
46
+ worker_threads << Thread.new do
47
+ loop do
48
+ test = nil
49
+ test_count_mutex.synchronize do
50
+ test_array_mutex.synchronize{test = test_array[test_count]}
51
+ test_count += 1
52
+ end
53
+ break unless test
54
+
55
+ file = test[0]
56
+ group = test[1]
57
+ example = test[3]
58
+ report_file = '/' + file + '/' + example + '/' + browser['name'] +
59
+ '/' + browser['version'].to_s + '/' + browser['os'] + '/report.html'
60
+
61
+ sauce_test = 'sauce_test -t ' + type.to_s + ' ' +
62
+ '-c ' + config + ' ' +
63
+ '-r "' + report + report_file + '" ' +
64
+ '-b ' + browser['name'] + ' ' +
65
+ '-v ' + browser['version'].to_s + ' ' +
66
+ '-o "' + browser['os'] + '" ' +
67
+ '-e "' + example + '" ' + file
68
+
69
+ result = `#{sauce_test}`
70
+
71
+ test_result_mutex.synchronize do
72
+ example = test[2]
73
+ status = YAML::load(StringIO.new result)['status']
74
+ duration = YAML::load(StringIO.new result)['duration']
75
+ job_id = YAML::load(StringIO.new result)['groups'][0]['examples'][0]['job_id']
76
+ @test_result << [file,
77
+ group,
78
+ example,
79
+ browser,
80
+ status,
81
+ duration,
82
+ job_id,
83
+ report_file]
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ worker_threads.each{|t| t.join}
92
+ browser_threads.each{|t| t.join}
93
+
94
+ template_file = File.dirname(__FILE__) + '/templates/collection_report.erb'
95
+ template_str = IO.readlines(template_file).join
96
+ template = ERB.new(template_str)
97
+ File.new(report + '/report.html', 'w') << template.result(binding)
98
+
99
+ end
100
+ end
101
+
102
+
103
+ end
104
+ end
@@ -0,0 +1,77 @@
1
+ require 'yaml'
2
+
3
+ module SauceTest
4
+ module Helpers
5
+
6
+ class SauceTestOptions
7
+
8
+ attr_reader :user,
9
+ :key,
10
+ :timeout,
11
+ :browser
12
+
13
+ attr_accessor :job_name
14
+
15
+ def initialize(browser = nil)
16
+ set_browser(browser || "firefox")
17
+ end
18
+
19
+ def parse_config(config_file)
20
+ config = YAML::load_file config_file
21
+ @user = config['login']
22
+ @key = config['key']
23
+ @timeout = config['timeout'] || 180
24
+
25
+ if(@user and @key) then true
26
+ else false end
27
+ end
28
+
29
+ def browser_json
30
+ %W({ "username": "#{@user}",) +
31
+ %W("access-key": "#{@key}",) +
32
+ %W("job-name": "#{@job_name}",) +
33
+ %W("os": "#{@browser['os']}",) +
34
+ %W("browser": "#{@browser['name']}",) +
35
+ %W("browser-major-version": "#{@browser['version']}" })
36
+ end
37
+
38
+ def set_browser_version(version)
39
+ @browser['version'] = version
40
+ end
41
+
42
+ def set_os(os)
43
+ @browser['os'] = os
44
+ end
45
+
46
+ protected
47
+
48
+ def set_browser(name)
49
+ @browser = {}
50
+ case name
51
+ when "firefox", "chrome"
52
+ @browser['name'] = "firefox"
53
+ @browser['version'] = 3
54
+ @browser['os'] = "Linux"
55
+ when "iehta", "iexplore"
56
+ @browser['name'] = "iexplore"
57
+ @browser['version'] = 7
58
+ @browser['os'] = "Windows 2003"
59
+ when "safari"
60
+ @browser['name'] = name
61
+ @browser['version'] = 4
62
+ @browser['os'] = "Windows 2003"
63
+ when "opera"
64
+ @browser['name'] = name
65
+ @browser['version'] = 9
66
+ @browser['os'] = "Windows 2003"
67
+ when "googlechrome"
68
+ @browser['name'] = name
69
+ @browser['version'] = 1
70
+ @browser['os'] = "Windows 2003"
71
+ end
72
+ end
73
+
74
+ end
75
+
76
+ end
77
+ end
@@ -0,0 +1,35 @@
1
+ require 'sauce-test/collection'
2
+
3
+ module SauceTest
4
+ module Rake
5
+
6
+ class BaseTask
7
+
8
+ attr_accessor :files, :browsers, :report, :workers, :config
9
+
10
+ def initialize(name)
11
+ @name = name
12
+ @browsers = [{'os' => "Linux", 'name' => "firefox", 'version' => 3},
13
+ {'os' => "Windows 2003", 'name' => "iexplore", 'version' => 7}]
14
+ @workers = 1
15
+ @config = 'config/sauce.yml'
16
+ @report = 'reports/sauce_test'
17
+
18
+ yield self if block_given?
19
+
20
+ define_task
21
+ end
22
+
23
+ def define_task
24
+ task @name do
25
+ SauceTest::Collection.run(@files, @browsers, @workers, @config, @report, @type)
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+ end
33
+
34
+ require 'sauce-test/rspec/rake_tasks'
35
+ require 'sauce-test/testunit/rake_tasks'
@@ -0,0 +1,14 @@
1
+ module SauceTest
2
+ module Rake
3
+
4
+ class RSpecTask < BaseTask
5
+
6
+ def initialize(name = :'sauce:spec')
7
+ @type = :spec
8
+ super(name)
9
+ end
10
+
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,49 @@
1
+ require 'stringio'
2
+
3
+ require 'rubygems'
4
+ require 'spec'
5
+
6
+ require 'sauce-test/rspec/sauce_formatter'
7
+ require 'sauce-test/selenium/client_driver_extension'
8
+
9
+ module SauceTest
10
+ module RSpec
11
+
12
+ module Runner
13
+
14
+ class << self
15
+ def run(options)
16
+ @options = options
17
+ rspec_init
18
+ Spec::Runner.run
19
+ report = SauceTest::RSpec::Runner::SauceFormatter.report
20
+ report.test_file = @options.test_file
21
+ report
22
+ end
23
+
24
+ def rspec_init
25
+ out_str = StringIO.new
26
+ err_str = StringIO.new
27
+ spec_opt = Spec::Runner::Options.new(@err_str, @out_str)
28
+
29
+ if @options.list
30
+ spec_opt.dry_run = true
31
+ else
32
+ SauceTest::RSpec::Runner::SauceFormatter.set_sauce_test_options @options.sauce_options
33
+ end
34
+
35
+ if @options.example
36
+ spec_opt.parse_example @options.example
37
+ end
38
+
39
+ spec_opt.parse_format SauceTest::RSpec::Runner::SauceFormatter.to_s
40
+ spec_opt.files << @options.test_file
41
+
42
+ Spec::Runner.use spec_opt
43
+ end
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,76 @@
1
+ require 'spec/runner/formatter/base_formatter'
2
+
3
+ module SauceTest
4
+ module RSpec
5
+ module Runner
6
+
7
+ class SauceFormatter < Spec::Runner::Formatter::BaseFormatter
8
+
9
+ def initialize(options, output)
10
+ @dry_run = !!options.dry_run
11
+ @selenium = Selenium::Client::Driver
12
+ @selenium.set_sauce_options(@@sauce_options) unless @dry_run
13
+ @@report = SauceTest::Runner::Report.new
14
+ @@report.browser = @@sauce_options.browser unless @dry_run
15
+ end
16
+
17
+ def example_group_started(group_proxy)
18
+ @group = group_proxy.description
19
+ end
20
+
21
+ def example_started(example_proxy)
22
+ example = example_proxy.description
23
+ if @dry_run
24
+ @@report.add_example(@group,
25
+ {'name' => example,
26
+ 'status' => 'passed'})
27
+ else
28
+ @@sauce_options.job_name = @group + ' ' + example unless @dry_run
29
+ end
30
+ end
31
+
32
+ def example_pending(example_proxy, message)
33
+ @@report.add_example(@group,
34
+ {'name' => example_proxy.description,
35
+ 'status' => 'pending',
36
+ 'message' => message})
37
+ end
38
+
39
+ def example_passed(example_proxy)
40
+ @@report.add_example(@group,
41
+ {'name' => example_proxy.description,
42
+ 'status' => 'passed',
43
+ 'job_id' => @selenium.last_session_id }
44
+ ) unless @dry_run
45
+ end
46
+
47
+ def example_failed(example_proxy, counter, failure)
48
+ failure.exception.backtrace[0] =~ /(.*):(\d+)/
49
+ file = $1
50
+ line = $2.to_i
51
+ @@report.add_example(@group,
52
+ {'name' => example_proxy.description,
53
+ 'status' => 'failed',
54
+ 'job_id' => @selenium.last_session_id,
55
+ 'message' => failure.exception.message,
56
+ 'file' => file,
57
+ 'line' => line})
58
+ end
59
+
60
+ def dump_summary(duration, example_count, failure_count, pending_count)
61
+ @@report.duration = duration
62
+ end
63
+
64
+ def self.report
65
+ @@report
66
+ end
67
+
68
+ def self.set_sauce_test_options(options)
69
+ @@sauce_options = options.clone
70
+ end
71
+
72
+ end
73
+
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,32 @@
1
+ require 'yaml'
2
+ require 'fileutils'
3
+
4
+ require 'sauce-test/runner/options'
5
+ require 'sauce-test/runner/report'
6
+ require 'sauce-test/rspec/runner'
7
+ require 'sauce-test/testunit/runner'
8
+
9
+ module SauceTest
10
+ module Runner
11
+
12
+ class << self
13
+ def run(opts = nil)
14
+ options = opts || SauceTest::Runner::Options.new
15
+
16
+ case options.test_type
17
+ when :unit then runner = SauceTest::TestUnit::Runner
18
+ when :spec then runner = SauceTest::RSpec::Runner
19
+ end
20
+
21
+ report = runner.run(options)
22
+ YAML.dump(report.to_hash, $stdout)
23
+
24
+ if report_name = options.report_file and !options.list
25
+ FileUtils.mkdir_p File.dirname(report_name)
26
+ File.new(report_name, 'w') << report.to_html
27
+ end
28
+ end
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,116 @@
1
+ require 'optparse'
2
+
3
+ require 'sauce-test/version'
4
+ require 'sauce-test/helpers/sauce_test_options'
5
+
6
+ module SauceTest
7
+ module Runner
8
+
9
+ class Options
10
+
11
+ attr_reader :list,
12
+ :test_type,
13
+ :example,
14
+ :report_file,
15
+ :test_file,
16
+ :sauce_options
17
+
18
+ def initialize(opt_array = ARGV)
19
+ @browser = {}
20
+
21
+ @opt_parser = OptionParser.new
22
+
23
+ @opt_parser.banner = "Usage: sauce_test [options] FILE"
24
+
25
+ @opt_parser.on(*OPTIONS[:list]) {|list| @list = true}
26
+ @opt_parser.on(*OPTIONS[:type]) {|type| parse_type type}
27
+ @opt_parser.on(*OPTIONS[:example]) {|example| @example = example}
28
+ @opt_parser.on(*OPTIONS[:report]) {|report| @report_file = File.expand_path report}
29
+ @opt_parser.on(*OPTIONS[:browser]) {|browser| @browser['name'] = browser}
30
+ @opt_parser.on(*OPTIONS[:version]) {|version| @browser['version'] = version}
31
+ @opt_parser.on(*OPTIONS[:os]) {|os| @browser['os'] = os}
32
+ @opt_parser.on(*OPTIONS[:config]) {|config| parse_config(config)}
33
+ @opt_parser.on(*OPTIONS[:help]) {show_help}
34
+
35
+ @opt_parser.separator EXAMPLES
36
+
37
+ opt_rest = @opt_parser.parse(opt_array)
38
+
39
+ create_sauce_options unless list
40
+
41
+ parse_test_file(opt_rest[0])
42
+ end
43
+
44
+ protected
45
+
46
+ def create_sauce_options
47
+ @sauce_options = SauceTest::Helpers::SauceTestOptions.new(@browser['name'])
48
+ parse_config(DEFAULT_CFG) unless @config_file
49
+ show_help unless @sauce_options.parse_config(@config_file)
50
+ @sauce_options.set_os @browser['os'] if @browser['os']
51
+ @sauce_options.set_browser_version @browser['version'] if @browser['version']
52
+ end
53
+
54
+ def show_help
55
+ puts SauceTest::VERSION::SUMMARY
56
+ puts @opt_parser
57
+ exit
58
+ end
59
+
60
+ def parse_config(path)
61
+ @config_file = File.expand_path path
62
+ show_help unless File.file?(@config_file)
63
+ end
64
+
65
+ def parse_test_file(path)
66
+ if path and File.file?(path)
67
+ then @test_file = File.expand_path path
68
+ else show_help end
69
+
70
+ unless @test_type
71
+ case File.basename @test_file
72
+ when /_test\.rb/ then @test_type = :unit
73
+ when /_spec\.rb/ then @test_type = :spec
74
+ else show_help
75
+ end
76
+ end
77
+ end
78
+
79
+ def parse_type(type_str)
80
+ case type_str
81
+ when 'unit', 'u' then @test_type = :unit
82
+ when 'spec', 's'then @test_type = :spec
83
+ else show_help
84
+ end
85
+ end
86
+
87
+ DEFAULT_CFG = './config/sauce.yml'
88
+
89
+ OPTIONS = {
90
+ :example => ["-e", "--example NAME", "Run single test case. Use -l to list NAMEs"],
91
+ :list => ["-l", "--list", "List all tests"],
92
+ :type => ["-t", "--type TYPE", "Specify type of test file(optional)",
93
+ "spec|s :RSpec",
94
+ "unit|u :Test::Unit"],
95
+ :report => ["-r", "--report PATH", "HTML report directory path"],
96
+ :config => ["-c", "--config PATH", "config file path(#{DEFAULT_CFG} by default)"],
97
+ :browser => ["-b", "--browser STRING", "Sauce Labs JSON web browser string(firefox by default)"],
98
+ :os => ["-o", "--os STRING", "Sauce Labs JSON operating system string(optional)"],
99
+ :version => ["-v", "--version NUM", "Sauce Labs JSON browser version number(optional)"],
100
+ :help => ["-h", "--help", "You're looking at it"]
101
+ }
102
+
103
+ EXAMPLES = [ "\nUsage Examples:\n",
104
+ " sauce_test example_test.rb",
105
+ ' sauce_test -r "./reports/" example_spec.rb',
106
+ " sauce_test -l example_test.rb",
107
+ ' sauce_test -b "iexplore" example_test.rb',
108
+ ' sauce_test -b "firefox" -v 2 -o "Windows 2003" example_spec.rb',
109
+ ' sauce_test -t unit -e "test_something(ExampleTest)" example_test.rb',
110
+ ' sauce_test -t s -e "ExampleTest can do something" example_spec.rb']
111
+
112
+
113
+ end
114
+
115
+ end
116
+ end
@@ -0,0 +1,65 @@
1
+ require 'erb'
2
+
3
+ module SauceTest
4
+ module Runner
5
+
6
+ class Report
7
+
8
+ include ERB::Util
9
+
10
+ attr_accessor :test_file, :browser, :duration
11
+
12
+ def initialize
13
+ @groups = []
14
+ @status = 'passed'
15
+ @count = {'total' => 0,
16
+ 'pending' => 0,
17
+ 'failed' => 0}
18
+ end
19
+
20
+ def add_example(group_name, descripton)
21
+ descripton['full_name'] = group_name + ' ' + descripton['name']
22
+ @count['total'] += 1
23
+ status = descripton['status']
24
+ @count['pending'] += 1 if status == 'pending'
25
+ @count['failed'] += 1 if status == 'failed'
26
+
27
+ group = nil
28
+ @groups.each do |g|
29
+ if g['name'] == group_name
30
+ group = g
31
+ g['examples'] << descripton
32
+ g['status'] = status if status != 'passed' and g['status'] != 'failed'
33
+ end
34
+ end
35
+
36
+ unless group
37
+ group = {'name' => group_name,
38
+ 'status' => status,
39
+ 'examples' => [descripton]}
40
+ @groups << group
41
+ end
42
+
43
+ @status = status if status != 'passed' and @status != 'failed'
44
+ end
45
+
46
+ def to_hash
47
+ {'file' => test_file,
48
+ 'browser' => browser,
49
+ 'duration' => duration,
50
+ 'status' => @status,
51
+ 'count' => @count,
52
+ 'groups' => @groups}
53
+ end
54
+
55
+ def to_html
56
+ template_file = File.dirname(__FILE__) + '/../templates/test_report.erb'
57
+ template_str = IO.readlines(template_file).join
58
+ template = ERB.new(template_str)
59
+ template.result(binding)
60
+ end
61
+
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,35 @@
1
+ require "rubygems"
2
+ require "selenium/client"
3
+
4
+ module Selenium
5
+ module Client
6
+
7
+ class Driver
8
+
9
+ def start_new_browser_session(options={})
10
+ sauce_init
11
+ super(options)
12
+ @@last_session_id = @session_id
13
+ end
14
+
15
+ def self.set_sauce_options(sauce_options)
16
+ @@sauce_options = sauce_options
17
+ end
18
+
19
+ def self.last_session_id
20
+ @@last_session_id
21
+ end
22
+
23
+ protected
24
+
25
+ def sauce_init
26
+ @host = "saucelabs.com"
27
+ @port = 4444
28
+ @browser_string = @@sauce_options.browser_json
29
+ @default_timeout_in_seconds = @@sauce_options.timeout
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,57 @@
1
+ <!DOCTYPE html
2
+ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5
+ <head>
6
+ <title>SauceTest Report</title>
7
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
8
+ <meta http-equiv="Expires" content="-1" />
9
+ <meta http-equiv="Pragma" content="no-cache" />
10
+ </head>
11
+ <body>
12
+
13
+
14
+
15
+ <div class="sauce-report">
16
+
17
+ <div class="results">
18
+
19
+
20
+ <% @test_result.each do |result| %>
21
+
22
+ <div>
23
+ <div>
24
+ File: <a href="<%=u(result[7])%>"><%=result[0]%></a>
25
+ </div>
26
+
27
+ <div>
28
+ Test: <%=result[1] + ' ' + result[2]%>
29
+ </div>
30
+
31
+ <div>
32
+ Browser: <%=result[3]['name'] + ' ' + result[3]['version'].to_s + ' on ' + result[3]['os']%>
33
+ </div>
34
+
35
+ <div>
36
+ Status: <%=result[4]%>
37
+ </div>
38
+
39
+
40
+ <div>
41
+ Duration: <%=result[5]%> sec
42
+ </div>
43
+
44
+ <div>
45
+ <a href="http://saucelabs.com/jobs/<%=result[6]%>">Sauce Labs Report</a>
46
+ </div>
47
+
48
+ </br>
49
+ </div>
50
+
51
+ <% end %>
52
+
53
+ </div>
54
+
55
+
56
+ </body>
57
+ </html>
@@ -0,0 +1,81 @@
1
+ <!DOCTYPE html
2
+ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5
+ <head>
6
+ <title>SauceTest Report</title>
7
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
8
+ <meta http-equiv="Expires" content="-1" />
9
+ <meta http-equiv="Pragma" content="no-cache" />
10
+ </head>
11
+ <body>
12
+
13
+
14
+
15
+ <div class="sauce-report">
16
+
17
+ <div id="sauce-header">
18
+ <div id="summary">
19
+ <p id="file"><%= test_file %></p>
20
+ <p id="browser">
21
+ <%= browser['name'] + ' ' + browser['version'].to_s + ' on ' + browser['os'] %>
22
+ </p>
23
+ <p id="totals">
24
+ <%= @count['total'].to_s + ' examples' %>
25
+ <%= ', ' + @count['failed'].to_s + ' FAILED' %>
26
+ <%= ', ' + @count['pending'].to_s + ' pending' %>
27
+ </p>
28
+ <p id="duration">Duration: <%= duration %> sec</p>
29
+ </div>
30
+ </div>
31
+
32
+ <div class="results">
33
+ <div class=example_group">
34
+
35
+ <% @groups.each do |g| %>
36
+
37
+ <dl>
38
+ <dt><%= h(g['name']) %></dt>
39
+
40
+ <% g['examples'].each do |e| %>
41
+
42
+ <% if e['status'] == 'failed' %>
43
+ <dd class="failed">
44
+ <span class="failed_name"><%= h(e['name']) %>
45
+ <a class="job_link" href="<%= 'http://saucelabs.com/jobs/' + e['job_id'] %>">(Sauce Labs Job)</a></span>
46
+ <div class="failure">
47
+ <div class="message"><pre>
48
+ <%= h(e['message']) %>
49
+ </pre></div>
50
+ <div class="backtrace"><pre>
51
+ <%= e['file'] + ':' + e['line'].to_s %>
52
+ </pre></div>
53
+ </div>
54
+ </dd>
55
+ <% end %>
56
+
57
+ <% if e['status'] == 'passed' %>
58
+ <dd class="passed">
59
+ <span class="passed_name"><%= h(e['name']) %>
60
+ <a class="job_link" href="<%= 'http://saucelabs.com/jobs/' + e['job_id'] %>">(Sauce Labs Job)</a></span>
61
+ </dd>
62
+ <% end %>
63
+
64
+ <% if e['status'] == 'pending' %>
65
+ <dd class="pending">
66
+ <span class="pending_name"><%= h(e['name'] + ' PENDING: ' + e['message']) %></span>
67
+ </dd>
68
+ <% end %>
69
+
70
+ <% end %>
71
+
72
+ </dl>
73
+
74
+ <% end %>
75
+
76
+ </div>
77
+ </div>
78
+
79
+
80
+ </body>
81
+ </html>
@@ -0,0 +1,14 @@
1
+ module SauceTest
2
+ module Rake
3
+
4
+ class TestUnitTask < BaseTask
5
+
6
+ def initialize(name = :'sauce:unit')
7
+ @type = :unit
8
+ super(name)
9
+ end
10
+
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ module SauceTest
2
+ module TestUnit
3
+
4
+ module Runner
5
+
6
+ class << self
7
+ def run(options)
8
+ end
9
+ end
10
+
11
+ end
12
+
13
+ end
14
+ end
15
+
@@ -0,0 +1,13 @@
1
+ module SauceTest # :nodoc:
2
+ module VERSION # :nodoc:
3
+
4
+ MAJOR = 0
5
+ MINOR = 1
6
+ TINY = 0
7
+
8
+ STRING = [MAJOR, MINOR, TINY].compact.join('.')
9
+
10
+ SUMMARY = "sauce_test #{STRING}"
11
+
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sauce-test
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Bart Wadolowski
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-25 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: selenium-client
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description:
36
+ email: bart@saucelabs.com
37
+ executables:
38
+ - sauce_test
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - bin/sauce_test
45
+ - lib/sauce-test
46
+ - lib/sauce-test/rake
47
+ - lib/sauce-test/rake/tasks.rb
48
+ - lib/sauce-test/runner.rb
49
+ - lib/sauce-test/rspec
50
+ - lib/sauce-test/rspec/runner.rb
51
+ - lib/sauce-test/rspec/sauce_formatter.rb
52
+ - lib/sauce-test/rspec/rake_tasks.rb
53
+ - lib/sauce-test/templates
54
+ - lib/sauce-test/templates/test_report.erb
55
+ - lib/sauce-test/templates/collection_report.erb
56
+ - lib/sauce-test/templates/img
57
+ - lib/sauce-test/templates/img/saucelabs.jpg
58
+ - lib/sauce-test/collection.rb
59
+ - lib/sauce-test/selenium
60
+ - lib/sauce-test/selenium/client_driver_extension.rb
61
+ - lib/sauce-test/version.rb
62
+ - lib/sauce-test/runner
63
+ - lib/sauce-test/runner/report.rb
64
+ - lib/sauce-test/runner/options.rb
65
+ - lib/sauce-test/testunit
66
+ - lib/sauce-test/testunit/runner.rb
67
+ - lib/sauce-test/testunit/rake_tasks.rb
68
+ - lib/sauce-test/helpers
69
+ - lib/sauce-test/helpers/sauce_test_options.rb
70
+ - examples/google_search
71
+ - examples/google_search/spec
72
+ - examples/google_search/spec/selenium
73
+ - examples/google_search/spec/selenium/google_spec.rb
74
+ - examples/google_search/spec/selenium/r.html
75
+ - examples/google_search/spec/spec_helper.rb
76
+ - examples/google_search/Rakefile
77
+ - examples/google_search/config
78
+ - examples/google_search/config/sauce.yml
79
+ - examples/google_search/helpers
80
+ - examples/google_search/helpers/google_test_helper.rb
81
+ - README.rdoc
82
+ - TODO.rdoc
83
+ has_rdoc: true
84
+ homepage: http://www.saucelabs.com
85
+ post_install_message:
86
+ rdoc_options: []
87
+
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: "0"
95
+ version:
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: "0"
101
+ version:
102
+ requirements: []
103
+
104
+ rubyforge_project: sauce-test
105
+ rubygems_version: 1.3.1
106
+ signing_key:
107
+ specification_version: 2
108
+ summary: Run your Selenium tests on Sauce Labs cloud
109
+ test_files: []
110
+