saucer 0.6.5 → 1.0.0.alpha
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile +3 -1
- data/LICENSE.txt +1 -1
- data/README.md +70 -59
- data/Rakefile +5 -3
- data/lib/saucer.rb +17 -4
- data/lib/saucer/asset_management.rb +113 -0
- data/lib/saucer/custom_commands.rb +21 -0
- data/lib/saucer/data_collection.rb +47 -0
- data/lib/saucer/job_update.rb +26 -0
- data/lib/saucer/options.rb +85 -0
- data/lib/saucer/runners.rb +5 -0
- data/lib/saucer/runners/cucumber.rb +23 -0
- data/lib/saucer/runners/rspec.rb +23 -0
- data/lib/saucer/runners/unknown.rb +23 -0
- data/lib/saucer/session.rb +134 -0
- data/lib/saucer/version.rb +3 -1
- data/saucer.gemspec +25 -25
- metadata +38 -57
- data/lib/saucer/annotations.rb +0 -44
- data/lib/saucer/api.rb +0 -57
- data/lib/saucer/config/common.rb +0 -23
- data/lib/saucer/config/sauce.rb +0 -67
- data/lib/saucer/config/selenium.rb +0 -39
- data/lib/saucer/driver.rb +0 -48
- data/lib/saucer/parallel.rb +0 -57
- data/lib/saucer/patches/sauce_whisk.rb +0 -7
- data/lib/saucer/platform_configuration.rb +0 -22
- data/lib/saucer/sauce.rb +0 -20
data/lib/saucer/annotations.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
module Saucer
|
2
|
-
module Annotations
|
3
|
-
|
4
|
-
def comment=(comment)
|
5
|
-
driver.execute_script("sauce:context=#{comment}")
|
6
|
-
end
|
7
|
-
|
8
|
-
def job_result=(result)
|
9
|
-
raise ArgumentError, "invalid value for result" unless ['passed', 'failed', true, false].include?(result)
|
10
|
-
driver.execute_script("sauce:job-result=#{result}")
|
11
|
-
end
|
12
|
-
|
13
|
-
def job_name=(name)
|
14
|
-
driver.execute_script("sauce:job-name=#{name}")
|
15
|
-
end
|
16
|
-
|
17
|
-
def job_tags=(tags)
|
18
|
-
tags = tags.join(',') if tags.is_a?(Array)
|
19
|
-
driver.execute_script("sauce:job-tags=#{tags}")
|
20
|
-
end
|
21
|
-
|
22
|
-
def job_info=(info)
|
23
|
-
raise ArgumentError, "job info must be JSON" unless info.is_a? JSON
|
24
|
-
driver.execute_script("sauce:job-info=#{info}")
|
25
|
-
end
|
26
|
-
|
27
|
-
def build_name=(name)
|
28
|
-
driver.execute_script("sauce:job-build=#{name}")
|
29
|
-
end
|
30
|
-
|
31
|
-
def stop_vm
|
32
|
-
driver.execute_script("sauce: stop network")
|
33
|
-
end
|
34
|
-
|
35
|
-
def start_vm
|
36
|
-
driver.execute_script("sauce: start network")
|
37
|
-
end
|
38
|
-
|
39
|
-
def breakpoint
|
40
|
-
driver.execute_script("sauce: break")
|
41
|
-
end
|
42
|
-
|
43
|
-
end
|
44
|
-
end
|
data/lib/saucer/api.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
module Saucer
|
2
|
-
class API
|
3
|
-
|
4
|
-
def initialize(driver, config)
|
5
|
-
@driver = driver
|
6
|
-
@config = config
|
7
|
-
end
|
8
|
-
|
9
|
-
def jobs
|
10
|
-
SauceWhisk::Jobs
|
11
|
-
end
|
12
|
-
|
13
|
-
def assets
|
14
|
-
SauceWhisk::Assets
|
15
|
-
end
|
16
|
-
|
17
|
-
def accounts
|
18
|
-
SauceWhisk::Accounts
|
19
|
-
end
|
20
|
-
|
21
|
-
def tunnels
|
22
|
-
SauceWhisk::Tunnels.all
|
23
|
-
end
|
24
|
-
|
25
|
-
def job
|
26
|
-
jobs.fetch(@driver.session_id)
|
27
|
-
end
|
28
|
-
|
29
|
-
def account
|
30
|
-
accounts.fetch(@config.username)
|
31
|
-
end
|
32
|
-
|
33
|
-
def concurrency
|
34
|
-
accounts.concurrency_for(@config.username)
|
35
|
-
end
|
36
|
-
|
37
|
-
def tunnel(id)
|
38
|
-
tunnels.fetch(id)
|
39
|
-
end
|
40
|
-
|
41
|
-
def platforms
|
42
|
-
SauceWhisk::Sauce.platforms
|
43
|
-
end
|
44
|
-
|
45
|
-
def storage
|
46
|
-
@storage ||= SauceWhisk::Storage.new
|
47
|
-
end
|
48
|
-
|
49
|
-
def service_status
|
50
|
-
SauceWhisk::Sauce.service_status
|
51
|
-
end
|
52
|
-
|
53
|
-
def total_job_count
|
54
|
-
SauceWhisk::Sauce.total_job_count
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
data/lib/saucer/config/common.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
module Saucer
|
2
|
-
module Config
|
3
|
-
class Common
|
4
|
-
|
5
|
-
CONFIG_PARAMS = %i(auto_accept_alerts name build tags custom_data max_duration
|
6
|
-
command_timeout idle_timeout prerun executable args background
|
7
|
-
timeout tunnel_identifier parent_tunnel screen_resolution timezone
|
8
|
-
avoid_proxy public record_video video_upload_on_pass record_screenshots
|
9
|
-
record_logs capture_html priority webdriver_remote_quiet_exceptions).freeze
|
10
|
-
|
11
|
-
attr_reader :config_params, :username, :access_key, :url
|
12
|
-
|
13
|
-
def initialize(opts = {})
|
14
|
-
@username = opts.delete(:username) || ENV['SAUCE_USERNAME']
|
15
|
-
@access_key = opts.delete(:access_key) || ENV['SAUCE_ACCESS_KEY']
|
16
|
-
@url = opts.delete(:url) || "https://#{@username}:#{@access_key}@ondemand.saucelabs.com:443/wd/hub"
|
17
|
-
|
18
|
-
@opts = opts
|
19
|
-
@config_params = CONFIG_PARAMS
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
data/lib/saucer/config/sauce.rb
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
require 'bundler'
|
2
|
-
|
3
|
-
module Saucer
|
4
|
-
module Config
|
5
|
-
class Sauce
|
6
|
-
|
7
|
-
def self.scenario=(scenario)
|
8
|
-
@@scenario = scenario
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.scenario
|
12
|
-
@@scenario
|
13
|
-
end
|
14
|
-
|
15
|
-
DATA_PARAMS = %i(name build language host_os version ci ip gems framework page_object harness selenium).freeze
|
16
|
-
|
17
|
-
FRAMEWORKS = %w(capybara watir).freeze
|
18
|
-
PAGE_OBJECTS = %w(site_prism page-object watirsome watir_drops).freeze
|
19
|
-
|
20
|
-
def initialize(opt = {})
|
21
|
-
opt[:browser_name] ||= ENV['BROWSER']
|
22
|
-
opt[:platform] ||= ENV['PLATFORM']
|
23
|
-
opt[:version] ||= ENV['VERSION']
|
24
|
-
|
25
|
-
@gems = {}
|
26
|
-
Bundler.definition.specs.map(&:name).each do |gem_name|
|
27
|
-
next if Bundler.environment.specs.to_hash[gem_name].empty?
|
28
|
-
@gems[gem_name] = Bundler.environment.specs.to_hash[gem_name].first.version.version
|
29
|
-
end
|
30
|
-
|
31
|
-
@selenium = @gems['selenium-webdriver']
|
32
|
-
|
33
|
-
frameworks = @gems.select { |gem| FRAMEWORKS.include? gem }
|
34
|
-
@framework = frameworks.first if frameworks.size == 1
|
35
|
-
|
36
|
-
page_objects = @gems.select { |gem| PAGE_OBJECTS.include? gem }
|
37
|
-
@page_object = page_objects.first if page_objects.size == 1
|
38
|
-
|
39
|
-
@name = opt[:name] if opt.key? :name
|
40
|
-
@build = opt[:build] || ENV['BUILD_TAG'] || "Build - #{Time.now.to_i}"
|
41
|
-
|
42
|
-
if RSpec.respond_to?(:current_example) && !RSpec.current_example.nil?
|
43
|
-
@name ||= RSpec.current_example.full_description
|
44
|
-
@location = RSpec.current_example.location
|
45
|
-
@harness = ["rspec", @gems["rspec"]]
|
46
|
-
elsif @@scenario
|
47
|
-
@name ||= @@scenario.source.map(&:name).join(" ")
|
48
|
-
@location = @@scenario.location.to_s
|
49
|
-
@harness = ["cucumber", @gems["cucumber"]]
|
50
|
-
end
|
51
|
-
|
52
|
-
@language = 'Ruby'
|
53
|
-
@host_os = ::Selenium::WebDriver::Platform.os
|
54
|
-
@version = ::Selenium::WebDriver::Platform.ruby_version
|
55
|
-
@ci = ::Selenium::WebDriver::Platform.ci
|
56
|
-
@ip = ::Selenium::WebDriver::Platform.ip
|
57
|
-
end
|
58
|
-
|
59
|
-
def to_hash
|
60
|
-
DATA_PARAMS.each_with_object({}) do |name, hash|
|
61
|
-
var = eval("@#{name}")
|
62
|
-
hash[name] = var if var
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
module Saucer
|
2
|
-
module Config
|
3
|
-
class Selenium < Common
|
4
|
-
|
5
|
-
attr_reader :sauce
|
6
|
-
|
7
|
-
CONFIG_PARAMS = %i(browser_name version platform selenium_version
|
8
|
-
chromedriver_version iedriver_version).freeze
|
9
|
-
|
10
|
-
def initialize(opt = {})
|
11
|
-
super
|
12
|
-
@config_params += CONFIG_PARAMS
|
13
|
-
end
|
14
|
-
|
15
|
-
def url
|
16
|
-
"https://#{@username}:#{@access_key}@ondemand.saucelabs.com:443/wd/hub"
|
17
|
-
end
|
18
|
-
|
19
|
-
def capabilities
|
20
|
-
caps = @opts[:desired_capabilities]
|
21
|
-
caps ||= begin
|
22
|
-
caps = @config_params.each_with_object({}) do |param, hash|
|
23
|
-
hash[param] = @opts[param] if @opts.key?(param)
|
24
|
-
hash[param] ||= ENV[param.to_s] if ENV[param.to_s]
|
25
|
-
end
|
26
|
-
browser_name = @opts[:browser_name] || :chrome
|
27
|
-
::Selenium::WebDriver::Remote::Capabilities.send(browser_name, caps)
|
28
|
-
end
|
29
|
-
|
30
|
-
@sauce = Sauce.new.to_hash
|
31
|
-
caps[:"sauce:data"] = @sauce.to_hash
|
32
|
-
caps[:name] = @sauce[:name]
|
33
|
-
caps[:build] = @sauce[:build]
|
34
|
-
caps
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
end
|
data/lib/saucer/driver.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
module Saucer
|
2
|
-
class Driver < Selenium::WebDriver::Remote::Driver
|
3
|
-
|
4
|
-
attr_reader :driver, :config
|
5
|
-
|
6
|
-
def initialize(*args)
|
7
|
-
browser = args.shift if args.first.is_a? Symbol
|
8
|
-
browser = nil if browser == :remote
|
9
|
-
opt = args.first || {}
|
10
|
-
unless opt[:desired_capabilities].is_a? Selenium::WebDriver::Remote::Capabilities
|
11
|
-
opts = opt[:desired_capabilities] || {}
|
12
|
-
browser = opt.key?(:browser_name) ? opt[:browser_name].downcase.to_sym : browser || :chrome
|
13
|
-
opt[:desired_capabilities] = Selenium::WebDriver::Remote::Capabilities.send(browser, opts)
|
14
|
-
end
|
15
|
-
@config = Config::Selenium.new(opt)
|
16
|
-
|
17
|
-
opt[:url] = @config.url
|
18
|
-
opt[:desired_capabilities] = @config.capabilities
|
19
|
-
|
20
|
-
super(opt)
|
21
|
-
end
|
22
|
-
|
23
|
-
def sauce
|
24
|
-
@sauce ||= Sauce.new(self, @config)
|
25
|
-
end
|
26
|
-
|
27
|
-
def quit
|
28
|
-
if RSpec.current_example
|
29
|
-
exception = RSpec.current_example.exception
|
30
|
-
result = exception.nil?
|
31
|
-
elsif Saucer::Config::Sauce.scenario
|
32
|
-
exception = Saucer::Config::Sauce.scenario.exception
|
33
|
-
result = Saucer::Config::Sauce.scenario.passed?
|
34
|
-
end
|
35
|
-
|
36
|
-
if exception
|
37
|
-
sauce.comment = "Error: #{exception.inspect}"
|
38
|
-
sauce.comment = "Error Location: #{exception.backtrace.first}"
|
39
|
-
end
|
40
|
-
|
41
|
-
sauce.job_result = result unless result.nil?
|
42
|
-
results = sauce.api.job.log_url[/(.*)\/.*$/, 1]
|
43
|
-
Selenium::WebDriver.logger.warn("Sauce Labs results: #{results}")
|
44
|
-
|
45
|
-
super
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
data/lib/saucer/parallel.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'sauce_platforms'
|
2
|
-
require 'yaml'
|
3
|
-
|
4
|
-
module Saucer
|
5
|
-
class Parallel
|
6
|
-
|
7
|
-
attr_accessor :number, :path, :output
|
8
|
-
|
9
|
-
def initialize(opt = {})
|
10
|
-
@number = opt[:number] || ENV['PARALLEL_PROCESSES']
|
11
|
-
@path = opt[:path] || ENV['TEST_PATH'] || "spec"
|
12
|
-
@output = opt[:output] || ENV['REPORT_OUTPUT'] || 'output'
|
13
|
-
@platforms = opt[:platforms] || []
|
14
|
-
if File.exist?('configs/platform_configs.yml')
|
15
|
-
yaml = YAML.load_file('configs/platform_configs.yml')
|
16
|
-
@platforms ||= yaml.map { |c| Saucer::PlatformConfiguration.new(c) }
|
17
|
-
end
|
18
|
-
@success = true
|
19
|
-
end
|
20
|
-
|
21
|
-
def run
|
22
|
-
if @platforms.empty?
|
23
|
-
raise StandardError, "Tests failed!" unless execute_test
|
24
|
-
return
|
25
|
-
end
|
26
|
-
|
27
|
-
@platforms.each do |platform|
|
28
|
-
Rake::Task.define_task(platform.name) {
|
29
|
-
ENV['platform'] = platform.to_hash[:platform]
|
30
|
-
ENV['browser_name'] = platform.to_hash[:browserName]
|
31
|
-
ENV['version'] = platform.to_hash[:version]
|
32
|
-
|
33
|
-
begin
|
34
|
-
@result = execute_test
|
35
|
-
ensure
|
36
|
-
@success &= @result
|
37
|
-
end
|
38
|
-
}
|
39
|
-
end
|
40
|
-
|
41
|
-
Rake::MultiTask.define_task(sauce_tests: @platforms.map(&:name)) {
|
42
|
-
raise StandardError, "Tests failed!" unless @success
|
43
|
-
}.invoke
|
44
|
-
end
|
45
|
-
|
46
|
-
def execute_test
|
47
|
-
if path.include?('spec')
|
48
|
-
ENV['PARALLEL_SPLIT_TEST_PROCESSES'] = number.to_s if number
|
49
|
-
system "parallel_split_test #{path} --out #{@output}.xml"
|
50
|
-
elsif path.include?('features')
|
51
|
-
system "parallel_cucumber #{path} -o \"--format junit --out #{@output} --format pretty\" -n #{number.to_s}"
|
52
|
-
else
|
53
|
-
raise ArgumentError, "Unable to determine if using rspec or cucumber"
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'sauce_platforms'
|
2
|
-
|
3
|
-
module Saucer
|
4
|
-
class PlatformConfiguration
|
5
|
-
attr_accessor :browser, :os, :browser_version
|
6
|
-
|
7
|
-
def initialize(opt = {})
|
8
|
-
@browser = opt[:browser]
|
9
|
-
@os = opt[:os] || opt['os'].downcase.tr(' ', '_').tr(',', '_')
|
10
|
-
@browser_version = opt[:browser_version] || opt['short_version']
|
11
|
-
end
|
12
|
-
|
13
|
-
def to_hash
|
14
|
-
Platform.send(@os).send(@browser).send("v#{@browser_version}")
|
15
|
-
end
|
16
|
-
|
17
|
-
def name
|
18
|
-
"#{@os}_#{@browser}_#{@browser_version}".to_sym
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
22
|
-
end
|
data/lib/saucer/sauce.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
module Saucer
|
2
|
-
class Sauce
|
3
|
-
|
4
|
-
include Annotations
|
5
|
-
|
6
|
-
def initialize(driver, config)
|
7
|
-
@driver = driver
|
8
|
-
@config = config
|
9
|
-
end
|
10
|
-
|
11
|
-
def api
|
12
|
-
@api ||= API.new(@driver, @config)
|
13
|
-
end
|
14
|
-
|
15
|
-
def driver
|
16
|
-
@driver
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
20
|
-
end
|