testingbot 0.0.9 → 0.1.0
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.
- data/.travis.yml +5 -0
- data/Gemfile +3 -1
- data/LICENSE +1 -1
- data/README.rdoc +89 -42
- data/Rakefile +15 -0
- data/examples/android.rb +14 -0
- data/examples/capybara.rb +10 -20
- data/examples/capybara_multiple_browsers.rb +38 -0
- data/examples/cucumber/README.rdoc +15 -0
- data/examples/cucumber/Rakefile +20 -0
- data/examples/cucumber/features/support/env.rb +5 -30
- data/examples/cucumber/features/youtube.feature +1 -0
- data/examples/test_rspec.rb +8 -30
- data/examples/test_rspec1.rb +1 -1
- data/examples/test_unit.rb +6 -13
- data/lib/testingbot.rb +3 -222
- data/lib/testingbot/api.rb +112 -0
- data/lib/testingbot/capybara.rb +49 -0
- data/lib/testingbot/config.rb +54 -2
- data/lib/testingbot/cucumber.rb +31 -26
- data/lib/testingbot/hooks.rb +255 -0
- data/lib/testingbot/selenium.rb +122 -0
- data/lib/testingbot/tunnel.rb +96 -8
- data/lib/testingbot/version.rb +2 -2
- data/spec/integration/api_spec.rb +88 -0
- data/spec/integration/selenium1_spec.rb +53 -0
- data/spec/integration/selenium2_spec.rb +60 -0
- data/spec/integration/tunnel_spec.rb +84 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/unit/api_spec.rb +17 -0
- data/spec/unit/config_spec.rb +73 -0
- data/spec/unit/tunnel_spec.rb +41 -0
- data/testingbot.gemspec +6 -1
- data/vendor/Testingbot-Tunnel.jar +0 -0
- metadata +86 -6
- data/examples/cucumber/README +0 -3
data/examples/test_rspec1.rb
CHANGED
data/examples/test_unit.rb
CHANGED
@@ -1,11 +1,7 @@
|
|
1
|
-
require
|
2
|
-
gem "selenium-client"
|
3
|
-
require "selenium/client"
|
4
|
-
gem 'test-unit'
|
1
|
+
require 'rubygems'
|
5
2
|
require 'test/unit'
|
6
|
-
|
7
|
-
|
8
|
-
require "testingbot"
|
3
|
+
require "selenium/client"
|
4
|
+
require 'testingbot'
|
9
5
|
|
10
6
|
class ExampleTest < TestingBot::TestCase
|
11
7
|
attr_reader :browser
|
@@ -17,12 +13,10 @@ class ExampleTest < TestingBot::TestCase
|
|
17
13
|
:browser => "firefox",
|
18
14
|
:platform => "WINDOWS",
|
19
15
|
:version => "10",
|
20
|
-
:url => "http://
|
16
|
+
:url => "http://www.google.com",
|
21
17
|
:timeout_in_second => 60
|
22
18
|
|
23
|
-
browser.
|
24
|
-
|
25
|
-
browser.start_new_browser_session(:captureNetworkTraffic => true)
|
19
|
+
browser.start_new_browser_session
|
26
20
|
end
|
27
21
|
|
28
22
|
def teardown
|
@@ -31,7 +25,6 @@ class ExampleTest < TestingBot::TestCase
|
|
31
25
|
|
32
26
|
def test_page_search
|
33
27
|
browser.open "/"
|
34
|
-
|
35
|
-
p browser.browser_network_traffic
|
28
|
+
assert_equal "Google", browser.title
|
36
29
|
end
|
37
30
|
end
|
data/lib/testingbot.rb
CHANGED
@@ -1,224 +1,5 @@
|
|
1
1
|
require "testingbot/version"
|
2
2
|
require "testingbot/config"
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
module Selenium
|
7
|
-
module Client
|
8
|
-
module Protocol
|
9
|
-
# add custom parameters for testingbot.com
|
10
|
-
def http_request_for_testingbot(verb, args)
|
11
|
-
data = http_request_for_original(verb, args)
|
12
|
-
data << "&client_key=#{TestingBot.get_config[:client_key]}&client_secret=#{TestingBot.get_config[:client_secret]}"
|
13
|
-
end
|
14
|
-
|
15
|
-
begin
|
16
|
-
alias http_request_for_original http_request_for
|
17
|
-
alias http_request_for http_request_for_testingbot
|
18
|
-
rescue
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
if defined?(Selenium) && defined?(Selenium::Client) && defined?(Selenium::Client::Base)
|
26
|
-
module Selenium
|
27
|
-
module Client
|
28
|
-
module Base
|
29
|
-
DEFAULT_OPTIONS = {
|
30
|
-
:screenshot => true
|
31
|
-
}
|
32
|
-
|
33
|
-
alias :close_current_browser_session_old :close_current_browser_session
|
34
|
-
alias :start_new_browser_session_old :start_new_browser_session
|
35
|
-
alias :initialize_old :initialize
|
36
|
-
|
37
|
-
attr_accessor :options
|
38
|
-
attr_accessor :session_id_backup
|
39
|
-
attr_accessor :extra
|
40
|
-
attr_accessor :platform
|
41
|
-
attr_accessor :version
|
42
|
-
|
43
|
-
def initialize(*args)
|
44
|
-
if args[0].kind_of?(Hash)
|
45
|
-
options = args[0]
|
46
|
-
@platform = options[:platform] || "WINDOWS"
|
47
|
-
@version = options[:version] if options[:version]
|
48
|
-
end
|
49
|
-
|
50
|
-
@options = DEFAULT_OPTIONS
|
51
|
-
initialize_old(*args)
|
52
|
-
@host = "hub.testingbot.com" if @host.nil?
|
53
|
-
@port = 4444 if @port.nil?
|
54
|
-
end
|
55
|
-
|
56
|
-
def close_current_browser_session
|
57
|
-
@session_id_backup = @session_id
|
58
|
-
close_current_browser_session_old
|
59
|
-
end
|
60
|
-
|
61
|
-
def start_new_browser_session(options={})
|
62
|
-
options = @options.merge options
|
63
|
-
options[:platform] = @platform
|
64
|
-
options[:version] = @version unless @version.nil?
|
65
|
-
start_new_browser_session_old(options)
|
66
|
-
end
|
67
|
-
|
68
|
-
def extra=(str)
|
69
|
-
@extra = str
|
70
|
-
end
|
71
|
-
|
72
|
-
def options=(opts = {})
|
73
|
-
@options = @options.merge opts
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
# rspec 1
|
81
|
-
begin
|
82
|
-
require 'spec'
|
83
|
-
require "selenium/rspec/spec_helper"
|
84
|
-
Spec::Runner.configure do |config|
|
85
|
-
config.prepend_after(:each) do
|
86
|
-
client_key = TestingBot.get_config[:client_key]
|
87
|
-
client_secret = TestingBot.get_config[:client_secret]
|
88
|
-
|
89
|
-
if !client_key.nil?
|
90
|
-
|
91
|
-
session_id = nil
|
92
|
-
|
93
|
-
if !@selenium_driver.nil?
|
94
|
-
session_id = @selenium_driver.session_id_backup
|
95
|
-
elsif defined?(Capybara)
|
96
|
-
begin
|
97
|
-
session_id = page.driver.browser.instance_variable_get("@bridge").instance_variable_get("@session_id")
|
98
|
-
rescue Exception => e
|
99
|
-
p "Could not determine sessionID, can not send results to TestingBot.com #{e.message}"
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
if !session_id.nil?
|
104
|
-
params = {
|
105
|
-
"session_id" => session_id,
|
106
|
-
"client_key" => client_key,
|
107
|
-
"client_secret" => client_secret,
|
108
|
-
"status_message" => @execution_error,
|
109
|
-
"success" => !actual_failure?,
|
110
|
-
"name" => description.to_s,
|
111
|
-
"kind" => 2,
|
112
|
-
"extra" => @selenium_driver.extra
|
113
|
-
}
|
114
|
-
|
115
|
-
url = URI.parse('http://testingbot.com/hq')
|
116
|
-
http = Net::HTTP.new(url.host, url.port)
|
117
|
-
response = http.post(url.path, params.map { |k, v| "#{k.to_s}=#{v}" }.join("&"))
|
118
|
-
end
|
119
|
-
else
|
120
|
-
puts "Can't post test results to TestingBot since I could not a .testingbot file in your home-directory."
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
rescue LoadError
|
125
|
-
end
|
126
|
-
|
127
|
-
# rspec 2
|
128
|
-
begin
|
129
|
-
require 'rspec'
|
130
|
-
|
131
|
-
::RSpec.configuration.after :each do
|
132
|
-
|
133
|
-
client_key = TestingBot.get_config[:client_key]
|
134
|
-
client_secret = TestingBot.get_config[:client_secret]
|
135
|
-
|
136
|
-
if !client_key.nil?
|
137
|
-
test_name = ""
|
138
|
-
if example.metadata && example.metadata[:example_group]
|
139
|
-
if example.metadata[:example_group][:description_args]
|
140
|
-
test_name = example.metadata[:example_group][:description_args].join(" ")
|
141
|
-
end
|
142
|
-
|
143
|
-
if example.metadata[:description_args]
|
144
|
-
test_name = test_name + " it " + example.metadata[:description_args].join(" ")
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
status_message = ""
|
149
|
-
status_message = example.exception.to_s if !example.exception.nil?
|
150
|
-
|
151
|
-
session_id = nil
|
152
|
-
|
153
|
-
if !@selenium_driver.nil?
|
154
|
-
session_id = @selenium_driver.session_id_backup
|
155
|
-
elsif defined?(Capybara)
|
156
|
-
begin
|
157
|
-
session_id = page.driver.browser.instance_variable_get("@bridge").instance_variable_get("@session_id")
|
158
|
-
rescue Exception => e
|
159
|
-
p "Could not determine sessionID, can not send results to TestingBot.com #{e.message}"
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
if !session_id.nil?
|
164
|
-
params = {
|
165
|
-
"session_id" => session_id,
|
166
|
-
"client_key" => client_key,
|
167
|
-
"client_secret" => client_secret,
|
168
|
-
"status_message" => status_message,
|
169
|
-
"success" => example.exception.nil?,
|
170
|
-
"name" => test_name,
|
171
|
-
"kind" => 2
|
172
|
-
}
|
173
|
-
|
174
|
-
if @selenium_driver && @selenium_driver.extra
|
175
|
-
params["extra"] = @selenium_driver.extra
|
176
|
-
end
|
177
|
-
|
178
|
-
url = URI.parse('http://testingbot.com/hq')
|
179
|
-
http = Net::HTTP.new(url.host, url.port)
|
180
|
-
response = http.post(url.path, params.map { |k, v| "#{k.to_s}=#{v}" }.join("&"))
|
181
|
-
end
|
182
|
-
else
|
183
|
-
puts "Can't post test results to TestingBot since I could not a .testingbot file in your home-directory."
|
184
|
-
end
|
185
|
-
end
|
186
|
-
rescue LoadError
|
187
|
-
end
|
188
|
-
|
189
|
-
if defined?(Test::Unit::TestCase) && (Test::Unit::TestCase.respond_to?('run_teardown'))
|
190
|
-
module TestingBot
|
191
|
-
class TestingBot::TestCase < Test::Unit::TestCase
|
192
|
-
alias :run_teardown_old :run_teardown
|
193
|
-
alias :handle_exception_old :handle_exception
|
194
|
-
|
195
|
-
attr_accessor :exception
|
196
|
-
|
197
|
-
def run_teardown
|
198
|
-
client_key = TestingBot.get_config[:client_key]
|
199
|
-
client_secret = TestingBot.get_config[:client_secret]
|
200
|
-
|
201
|
-
params = {
|
202
|
-
"session_id" => browser.session_id,
|
203
|
-
"client_key" => client_key,
|
204
|
-
"client_secret" => client_secret,
|
205
|
-
"status_message" => @exception,
|
206
|
-
"success" => passed?,
|
207
|
-
"name" => self.to_s,
|
208
|
-
"kind" => 2,
|
209
|
-
"extra" => browser.extra
|
210
|
-
}
|
211
|
-
|
212
|
-
url = URI.parse('http://testingbot.com/hq')
|
213
|
-
http = Net::HTTP.new(url.host, url.port)
|
214
|
-
response = http.post(url.path, params.map { |k, v| "#{k.to_s}=#{v}" }.join("&"))
|
215
|
-
run_teardown_old
|
216
|
-
end
|
217
|
-
|
218
|
-
def handle_exception(e)
|
219
|
-
@exception = e.to_s
|
220
|
-
handle_exception_old(e)
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
224
|
-
end
|
3
|
+
require "testingbot/selenium"
|
4
|
+
require "testingbot/api"
|
5
|
+
require "testingbot/hooks"
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'json'
|
2
|
+
module TestingBot
|
3
|
+
|
4
|
+
class Api
|
5
|
+
|
6
|
+
VERSION = 1
|
7
|
+
API_URL = "http://api.testingbot.com"
|
8
|
+
|
9
|
+
attr_reader :config
|
10
|
+
|
11
|
+
def initialize(opts = {})
|
12
|
+
@config = TestingBot::Config.new(opts)
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_user_info
|
16
|
+
get("/user")
|
17
|
+
end
|
18
|
+
|
19
|
+
def update_user_info(params = {})
|
20
|
+
new_params = {}
|
21
|
+
params.keys.each do |key|
|
22
|
+
new_params["user[#{key}]"] = params[key]
|
23
|
+
end
|
24
|
+
response = put("/user", new_params)
|
25
|
+
response["success"]
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_tests(offset = 0, count = 10)
|
29
|
+
get("/tests")
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_single_test(test_id)
|
33
|
+
get("/tests/#{test_id}")
|
34
|
+
end
|
35
|
+
|
36
|
+
def update_test(test_id, params = {})
|
37
|
+
new_params = {}
|
38
|
+
params.keys.each do |key|
|
39
|
+
new_params["test[#{key}]"] = params[key]
|
40
|
+
end
|
41
|
+
response = put("/tests/#{test_id}", new_params)
|
42
|
+
response["success"]
|
43
|
+
end
|
44
|
+
|
45
|
+
def delete_test(test_id)
|
46
|
+
response = delete("/tests/#{test_id}")
|
47
|
+
response["success"]
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def get(url)
|
53
|
+
uri = URI(API_URL + '/v' + VERSION.to_s + url)
|
54
|
+
req = Net::HTTP::Get.new(uri.request_uri)
|
55
|
+
req.basic_auth @config[:client_key], @config[:client_secret]
|
56
|
+
res = Net::HTTP.start(uri.hostname, uri.port) {|http|
|
57
|
+
http.request(req)
|
58
|
+
}
|
59
|
+
|
60
|
+
parsed = JSON.parse(res.body)
|
61
|
+
|
62
|
+
if !parsed["error"].nil? && !parsed["error"].empty?
|
63
|
+
raise parsed["error"]
|
64
|
+
end
|
65
|
+
|
66
|
+
parsed
|
67
|
+
end
|
68
|
+
|
69
|
+
def put(url, params = {})
|
70
|
+
uri = URI(API_URL + '/v' + VERSION.to_s + url)
|
71
|
+
req = Net::HTTP::Put.new(uri.request_uri)
|
72
|
+
req.basic_auth @config[:client_key], @config[:client_secret]
|
73
|
+
req.set_form_data(params)
|
74
|
+
res = Net::HTTP.start(uri.hostname, uri.port) {|http|
|
75
|
+
http.request(req)
|
76
|
+
}
|
77
|
+
|
78
|
+
parsed = JSON.parse(res.body)
|
79
|
+
|
80
|
+
if !parsed["error"].nil? && !parsed["error"].empty?
|
81
|
+
raise parsed["error"]
|
82
|
+
end
|
83
|
+
|
84
|
+
parsed
|
85
|
+
end
|
86
|
+
|
87
|
+
def delete(url, params = {})
|
88
|
+
uri = URI(API_URL + '/v' + VERSION.to_s + url)
|
89
|
+
req = Net::HTTP::Delete.new(uri.request_uri)
|
90
|
+
req.basic_auth @config[:client_key], @config[:client_secret]
|
91
|
+
req.set_form_data(params)
|
92
|
+
res = Net::HTTP.start(uri.hostname, uri.port) {|http|
|
93
|
+
http.request(req)
|
94
|
+
}
|
95
|
+
|
96
|
+
parsed = JSON.parse(res.body)
|
97
|
+
|
98
|
+
if !parsed["error"].nil? && !parsed["error"].empty?
|
99
|
+
raise parsed["error"]
|
100
|
+
end
|
101
|
+
|
102
|
+
parsed
|
103
|
+
end
|
104
|
+
|
105
|
+
def post(url, params = {})
|
106
|
+
url = URI.parse(API_URL + '/v' + VERSION + url)
|
107
|
+
http = Net::HTTP.new(url.host, url.port)
|
108
|
+
http.basic_auth @config[:client_key], @config[:client_secret]
|
109
|
+
response = http.post(url.path, params.map { |k, v| "#{k.to_s}=#{v}" }.join("&"))
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'capybara'
|
2
|
+
require 'testingbot/config'
|
3
|
+
require 'testingbot/tunnel'
|
4
|
+
require 'testingbot/selenium'
|
5
|
+
require 'capybara/dsl'
|
6
|
+
|
7
|
+
@tunnel = nil
|
8
|
+
|
9
|
+
module TestingBot
|
10
|
+
module Capybara
|
11
|
+
|
12
|
+
def self.start_tunnel
|
13
|
+
return @tunnel unless @tunnel.nil?
|
14
|
+
|
15
|
+
@tunnel = TestingBot::Tunnel.new(TestingBot.get_config[:tunnel_options] || {})
|
16
|
+
@tunnel.start
|
17
|
+
end
|
18
|
+
|
19
|
+
class CustomDriver < ::Capybara::Selenium::Driver
|
20
|
+
def browser
|
21
|
+
unless @browser
|
22
|
+
if TestingBot.get_config[:require_tunnel]
|
23
|
+
TestingBot::Capybara.start_tunnel
|
24
|
+
end
|
25
|
+
|
26
|
+
@browser = TestingBot::SeleniumWebdriver.new
|
27
|
+
|
28
|
+
main = Process.pid
|
29
|
+
at_exit do
|
30
|
+
if @browser
|
31
|
+
begin
|
32
|
+
@browser.quit
|
33
|
+
rescue
|
34
|
+
end
|
35
|
+
end
|
36
|
+
if TestingBot.get_config[:require_tunnel]
|
37
|
+
@tunnel.stop unless @tunnel.nil?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
@browser
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
Capybara.register_driver :testingbot do |app|
|
48
|
+
TestingBot::Capybara::CustomDriver.new(app)
|
49
|
+
end
|
data/lib/testingbot/config.rb
CHANGED
@@ -1,28 +1,50 @@
|
|
1
1
|
module TestingBot
|
2
2
|
@@config = nil
|
3
|
-
|
4
3
|
def self.get_config
|
5
4
|
@@config = TestingBot::Config.new if @@config.nil?
|
6
5
|
@@config
|
7
6
|
end
|
7
|
+
|
8
|
+
def self.reset_config!
|
9
|
+
@@config = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.config
|
13
|
+
yield self.get_config
|
14
|
+
end
|
8
15
|
|
9
16
|
class Config
|
10
17
|
|
11
18
|
attr_reader :options
|
12
19
|
|
13
20
|
def initialize(options = {})
|
14
|
-
@options =
|
21
|
+
@options = default_options
|
15
22
|
@options = @options.merge(load_config_file)
|
16
23
|
@options = @options.merge(load_config_environment)
|
24
|
+
@options = @options.merge(options)
|
17
25
|
end
|
18
26
|
|
19
27
|
def [](key)
|
20
28
|
@options[key]
|
21
29
|
end
|
22
30
|
|
31
|
+
def add_options(options = {})
|
32
|
+
@options = @options.merge(options)
|
33
|
+
end
|
34
|
+
|
23
35
|
def []=(key, value)
|
24
36
|
@options[key] = value
|
25
37
|
end
|
38
|
+
|
39
|
+
def options
|
40
|
+
@options
|
41
|
+
end
|
42
|
+
|
43
|
+
def require_tunnel(host = "127.0.0.1", port = 4445)
|
44
|
+
@options[:require_tunnel] = true
|
45
|
+
@options[:host] = host
|
46
|
+
@options[:port] = port
|
47
|
+
end
|
26
48
|
|
27
49
|
def client_key
|
28
50
|
@options[:client_key]
|
@@ -31,8 +53,38 @@ module TestingBot
|
|
31
53
|
def client_secret
|
32
54
|
@options[:client_secret]
|
33
55
|
end
|
56
|
+
|
57
|
+
def desired_capabilities
|
58
|
+
# check if instance of Selenium::WebDriver::Remote::Capabilities
|
59
|
+
unless @options[:desired_capabilities].instance_of?(Hash) || @options[:desired_capabilities].instance_of?(Array)
|
60
|
+
return symbolize_keys @options[:desired_capabilities].as_json
|
61
|
+
end
|
62
|
+
@options[:desired_capabilities]
|
63
|
+
end
|
34
64
|
|
35
65
|
private
|
66
|
+
|
67
|
+
def symbolize_keys(hash)
|
68
|
+
hash.inject({}) {|new_hash, key_value|
|
69
|
+
key, value = key_value
|
70
|
+
value = symbolize_keys(value) if value.is_a?(Hash)
|
71
|
+
new_hash[key.to_sym] = value
|
72
|
+
new_hash
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
def default_desired_capabilities
|
77
|
+
{ :browserName => "firefox", :version => 9, :platform => "WINDOWS" }
|
78
|
+
end
|
79
|
+
|
80
|
+
def default_options
|
81
|
+
{
|
82
|
+
:host => "hub.testingbot.com",
|
83
|
+
:port => 4444,
|
84
|
+
:jenkins_output => true,
|
85
|
+
:desired_capabilities => default_desired_capabilities
|
86
|
+
}
|
87
|
+
end
|
36
88
|
|
37
89
|
def load_config_file
|
38
90
|
options = {}
|