sauce-test 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+