xamarin-test-cloud 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +12 -1
- data/lib/xamarin-test-cloud/cli.rb +73 -42
- data/lib/xamarin-test-cloud/retriable_options.rb +26 -0
- data/lib/xamarin-test-cloud/version.rb +1 -1
- metadata +115 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 17f8c6ea03350ae24d3607f63bff1dfd571da5c9
|
4
|
+
data.tar.gz: 60ee93aec5aaaecb1423640398a62c1494a8108c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3fbc8ce41b25019819ed4684c8a5d7edea38b4709f9c88d7463ebf0979ccfcc851973469f2933a8935cd6846870b0e8d232348a74a076de23bacb76c77a47d8
|
7
|
+
data.tar.gz: d6f5ada84fcd0143b49369f28c041a7466786308d11c6e90d6f25b7789571b46d6602fc7e4ac1b89c40c78eab4a7f28aa11710ba8d74819e1d72044725e58a45
|
data/README.md
CHANGED
@@ -11,7 +11,10 @@ require 'tmpdir'
|
|
11
11
|
require 'fileutils'
|
12
12
|
require 'retriable'
|
13
13
|
require 'xamarin-test-cloud/version'
|
14
|
+
require 'xamarin-test-cloud/retriable_options'
|
14
15
|
require 'securerandom'
|
16
|
+
require 'open3'
|
17
|
+
|
15
18
|
|
16
19
|
trap "SIGINT" do
|
17
20
|
puts "Exiting"
|
@@ -28,7 +31,7 @@ module XamarinTestCloud
|
|
28
31
|
|
29
32
|
attr_accessor :app, :api_key, :appname, :test_parameters, :user,
|
30
33
|
:workspace, :config, :profile, :skip_config_check, :dry_run,
|
31
|
-
:device_selection, :pretty, :async, :priority, :endpoint_path,
|
34
|
+
:device_selection, :pretty, :async, :async_json, :priority, :endpoint_path,
|
32
35
|
:locale, :series,
|
33
36
|
:dsym, :session_id
|
34
37
|
|
@@ -113,6 +116,11 @@ module XamarinTestCloud
|
|
113
116
|
:type => :boolean,
|
114
117
|
:default => false
|
115
118
|
|
119
|
+
method_option 'async-json',
|
120
|
+
:desc => "Don't block waiting for test results. Output results in json format.",
|
121
|
+
:type => :boolean,
|
122
|
+
:default => false
|
123
|
+
|
116
124
|
method_option :priority,
|
117
125
|
:desc => "Run as priority test execution. Please note: This is only available for some tiers, and priority test executions cost double.",
|
118
126
|
:type => :boolean,
|
@@ -145,10 +153,23 @@ module XamarinTestCloud
|
|
145
153
|
:type => :string
|
146
154
|
|
147
155
|
|
148
|
-
|
149
156
|
def submit(app, api_key)
|
150
157
|
|
151
158
|
self.pretty = options[:pretty]
|
159
|
+
self.async_json = options['async-json']
|
160
|
+
self.async = options[:async] || self.async_json
|
161
|
+
|
162
|
+
# Async mode wraps all console output in a json object
|
163
|
+
# So we need to intercept all writes to $stdout
|
164
|
+
if self.async_json
|
165
|
+
@async_log = StringIO.new
|
166
|
+
@async_result = {
|
167
|
+
test_run_id: nil,
|
168
|
+
error_messages: [],
|
169
|
+
log: []
|
170
|
+
}
|
171
|
+
$stdout = @async_log
|
172
|
+
end
|
152
173
|
|
153
174
|
app_path = File.expand_path(app)
|
154
175
|
unless File.exist?(app_path)
|
@@ -173,8 +194,6 @@ module XamarinTestCloud
|
|
173
194
|
|
174
195
|
self.user = options['user']
|
175
196
|
|
176
|
-
self.async = options[:async]
|
177
|
-
|
178
197
|
self.dry_run = options['dry-run']
|
179
198
|
|
180
199
|
self.api_key = api_key
|
@@ -211,7 +230,7 @@ module XamarinTestCloud
|
|
211
230
|
|
212
231
|
workspace_basename = File.basename(workspace_path)
|
213
232
|
if workspace_basename.downcase == 'features'
|
214
|
-
self.workspace = File.expand_path(File.join(workspace_path,'..'))
|
233
|
+
self.workspace = File.expand_path(File.join(workspace_path, '..'))
|
215
234
|
puts "Deriving workspace #{self.workspace} from features folder #{workspace_basename}"
|
216
235
|
else
|
217
236
|
self.workspace = File.expand_path(workspace_path)
|
@@ -230,7 +249,7 @@ module XamarinTestCloud
|
|
230
249
|
|
231
250
|
parse_and_set_config_and_profile
|
232
251
|
unless self.skip_config_check
|
233
|
-
default_config = File.join(self.workspace,'config','cucumber.yml')
|
252
|
+
default_config = File.join(self.workspace, 'config', 'cucumber.yml')
|
234
253
|
if File.exist?(default_config) && self.config.nil?
|
235
254
|
log_header 'Warning: Detected cucumber.yml config file, but no --config specified'
|
236
255
|
puts "Please specify --config #{default_config}"
|
@@ -275,7 +294,7 @@ module XamarinTestCloud
|
|
275
294
|
rejected_devices = json['rejected_devices']
|
276
295
|
if rejected_devices && rejected_devices.size > 0
|
277
296
|
puts 'Skipping devices (you can update your selections via https://testcloud.xamarin.com)'
|
278
|
-
rejected_devices.each {|d| puts d}
|
297
|
+
rejected_devices.each { |d| puts d }
|
279
298
|
end
|
280
299
|
puts ''
|
281
300
|
|
@@ -290,10 +309,25 @@ module XamarinTestCloud
|
|
290
309
|
wait_for_job(json['id'])
|
291
310
|
else
|
292
311
|
log 'Async mode: not awaiting test results'
|
312
|
+
@async_result[:test_run_id] = json['id'] if self.async_json
|
293
313
|
end
|
294
314
|
|
315
|
+
rescue XamarinTestCloud::ValidationError => e
|
316
|
+
if self.async_json
|
317
|
+
@async_result[:error_messages] << e.message
|
318
|
+
else
|
319
|
+
raise
|
295
320
|
end
|
296
321
|
|
322
|
+
ensure
|
323
|
+
$stdout = STDOUT
|
324
|
+
if self.async_json
|
325
|
+
process_async_log
|
326
|
+
puts @async_result.to_json
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
|
297
331
|
default_task :submit
|
298
332
|
|
299
333
|
no_tasks do
|
@@ -302,13 +336,20 @@ module XamarinTestCloud
|
|
302
336
|
ENV['DEBUG'] == '1'
|
303
337
|
end
|
304
338
|
|
339
|
+
def process_async_log
|
340
|
+
@async_result[:log] = @async_log.string
|
341
|
+
.split(/\n/).map { |string| string.gsub(/\e\[(\d+)m/, '').strip }
|
342
|
+
.select { |string| string.length > 0 }
|
343
|
+
end
|
344
|
+
|
305
345
|
def exit_on_failure?
|
306
346
|
true
|
307
347
|
end
|
308
348
|
|
309
349
|
def wait_for_job(id)
|
350
|
+
retry_opts = XamarinTestCloud::RetriableOptions.tries_and_interval(60, 10)
|
310
351
|
while(true)
|
311
|
-
status_json = Retriable.retriable
|
352
|
+
status_json = Retriable.retriable(retry_opts) do
|
312
353
|
JSON.parse(http_post("status_v3", {'id' => id, 'api_key' => api_key, 'user' => user}))
|
313
354
|
end
|
314
355
|
|
@@ -367,7 +408,14 @@ module XamarinTestCloud
|
|
367
408
|
|
368
409
|
ENV['BUNDLE_GEMFILE'] = File.join(tmpdir, "Gemfile")
|
369
410
|
FileUtils.cd(self.workspace) do
|
370
|
-
|
411
|
+
if self.async_json
|
412
|
+
bundle_log, status = Open3.capture2e('bundle package --all')
|
413
|
+
puts bundle_log
|
414
|
+
else
|
415
|
+
system('bundle package --all')
|
416
|
+
status = $?
|
417
|
+
end
|
418
|
+
if status != 0
|
371
419
|
log_and_abort 'Bundler failed. Please check command: bundle package'
|
372
420
|
end
|
373
421
|
end
|
@@ -434,36 +482,17 @@ module XamarinTestCloud
|
|
434
482
|
when 200..202
|
435
483
|
response
|
436
484
|
when 400
|
437
|
-
|
438
|
-
|
439
|
-
puts response.body
|
440
|
-
end
|
485
|
+
error_message = JSON.parse(response.body)['error_message'] rescue 'Bad request'
|
486
|
+
log_and_abort(error_message)
|
441
487
|
when 403
|
442
|
-
|
443
|
-
|
444
|
-
puts JSON.parse(response.body)['message']
|
445
|
-
end
|
488
|
+
error_message = JSON.parse(response.body)['message'] rescue 'Forbidden'
|
489
|
+
log_and_abort(error_message)
|
446
490
|
when 413
|
447
|
-
|
448
|
-
|
449
|
-
end
|
491
|
+
error_message = 'Files are too large'
|
492
|
+
log_and_abort(error_message)
|
450
493
|
else
|
451
|
-
|
452
|
-
|
453
|
-
if r["invalid_platform"]
|
454
|
-
abort do
|
455
|
-
if r["invalid_platform"] == "android"
|
456
|
-
log "#{app} cannot be tested on Android devices. Please create a new device selection on the Xamarin Test Cloud website."
|
457
|
-
else
|
458
|
-
log "#{app} cannot be tested on iOS devices. Please create a new device selection on the Xamarin Test Cloud website."
|
459
|
-
end
|
460
|
-
end
|
461
|
-
end
|
462
|
-
rescue
|
463
|
-
end
|
464
|
-
abort do
|
465
|
-
log 'Unexpected Error. Please contact support at testcloud@xamarin.com.'
|
466
|
-
end
|
494
|
+
error_message = 'Unexpected Error. Please contact support at testcloud@xamarin.com.'
|
495
|
+
log_and_abort(error_message)
|
467
496
|
end
|
468
497
|
end
|
469
498
|
|
@@ -520,8 +549,8 @@ module XamarinTestCloud
|
|
520
549
|
|
521
550
|
dsym_digest= nil
|
522
551
|
if dsym
|
523
|
-
FileUtils.cp_r(dsym,tmpdir)
|
524
|
-
files_in_dwarf = Dir.glob(File.join(tmpdir, File.basename(dsym), 'Contents','Resources','DWARF','*'))
|
552
|
+
FileUtils.cp_r(dsym, tmpdir)
|
553
|
+
files_in_dwarf = Dir.glob(File.join(tmpdir, File.basename(dsym), 'Contents', 'Resources', 'DWARF', '*'))
|
525
554
|
unless files_in_dwarf.count == 1
|
526
555
|
raise ValidationError, "dSym #{dsym} contains more than one file in Contents/Resources/DWARF: #{files_in_dwarf}"
|
527
556
|
end
|
@@ -645,7 +674,7 @@ module XamarinTestCloud
|
|
645
674
|
files << config
|
646
675
|
end
|
647
676
|
|
648
|
-
files += Dir.glob(File.join(tmpdir,"vendor", 'cache', '*'))
|
677
|
+
files += Dir.glob(File.join(tmpdir, "vendor", 'cache', '*'))
|
649
678
|
|
650
679
|
if workspace and workspace.strip != ''
|
651
680
|
files += Dir.glob("#{workspace}Gemfile")
|
@@ -735,7 +764,7 @@ module XamarinTestCloud
|
|
735
764
|
|
736
765
|
def log(message)
|
737
766
|
if message.is_a? Array
|
738
|
-
message.each{ |m| log(m)}
|
767
|
+
message.each { |m| log(m) }
|
739
768
|
else
|
740
769
|
puts "#{Time.now } #{message}"
|
741
770
|
$stdout.flush
|
@@ -784,7 +813,9 @@ module XamarinTestCloud
|
|
784
813
|
end
|
785
814
|
|
786
815
|
def log_and_abort(message)
|
816
|
+
raise XamarinTestCloud::ValidationError.new(message) if self.async_json
|
787
817
|
abort do
|
818
|
+
print 'Error: '
|
788
819
|
puts message
|
789
820
|
end
|
790
821
|
end
|
@@ -795,7 +826,7 @@ module XamarinTestCloud
|
|
795
826
|
f.any? do |file|
|
796
827
|
filename = file[:filename]
|
797
828
|
if filename.end_with?("libmonodroid.so")
|
798
|
-
file[:size] < 120 * 1024 && f.none?{ |x| x[:filename] == filename.sub("libmonodroid.so", "libmonosgen-2.0.so")}
|
829
|
+
file[:size] < 120 * 1024 && f.none? { |x| x[:filename] == filename.sub("libmonodroid.so", "libmonosgen-2.0.so") }
|
799
830
|
end
|
800
831
|
end
|
801
832
|
end
|
@@ -803,7 +834,7 @@ module XamarinTestCloud
|
|
803
834
|
def files(app)
|
804
835
|
Zip::File.open(app) do |zip_file|
|
805
836
|
zip_file.collect do |entry|
|
806
|
-
{:filename => entry.to_s, :size => entry.size
|
837
|
+
{:filename => entry.to_s, :size => entry.size}
|
807
838
|
end
|
808
839
|
end
|
809
840
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'retriable'
|
2
|
+
|
3
|
+
module XamarinTestCloud
|
4
|
+
# A class to bridge the gap between retriable 1.x and 2.0.
|
5
|
+
class RetriableOptions
|
6
|
+
|
7
|
+
def self.retriable_version
|
8
|
+
parts = Retriable::VERSION.split('.')
|
9
|
+
{
|
10
|
+
:major => parts[0] ? parts[0].to_i : nil,
|
11
|
+
:minor => parts[1] ? parts[1].to_i : nil,
|
12
|
+
:patch => parts[2] ? parts[2].to_i : nil
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.tries_and_interval(tries, interval)
|
17
|
+
version = self.retriable_version[:major]
|
18
|
+
if version >= 2
|
19
|
+
{:intervals => Array.new(tries, interval)}
|
20
|
+
else
|
21
|
+
{:tries => tries, :interval => interval}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xamarin-test-cloud
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Karl Krukow
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-03-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: thor
|
@@ -18,6 +18,9 @@ dependencies:
|
|
18
18
|
- - '>='
|
19
19
|
- !ruby/object:Gem::Version
|
20
20
|
version: 0.18.1
|
21
|
+
- - <
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: '1.0'
|
21
24
|
type: :runtime
|
22
25
|
prerelease: false
|
23
26
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -25,6 +28,9 @@ dependencies:
|
|
25
28
|
- - '>='
|
26
29
|
- !ruby/object:Gem::Version
|
27
30
|
version: 0.18.1
|
31
|
+
- - <
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
28
34
|
- !ruby/object:Gem::Dependency
|
29
35
|
name: bundler
|
30
36
|
requirement: !ruby/object:Gem::Requirement
|
@@ -110,7 +116,7 @@ dependencies:
|
|
110
116
|
version: 1.3.3.1
|
111
117
|
- - <
|
112
118
|
- !ruby/object:Gem::Version
|
113
|
-
version: '2.
|
119
|
+
version: '2.1'
|
114
120
|
type: :runtime
|
115
121
|
prerelease: false
|
116
122
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -120,7 +126,7 @@ dependencies:
|
|
120
126
|
version: 1.3.3.1
|
121
127
|
- - <
|
122
128
|
- !ruby/object:Gem::Version
|
123
|
-
version: '2.
|
129
|
+
version: '2.1'
|
124
130
|
- !ruby/object:Gem::Dependency
|
125
131
|
name: rake
|
126
132
|
requirement: !ruby/object:Gem::Requirement
|
@@ -149,6 +155,110 @@ dependencies:
|
|
149
155
|
- - ~>
|
150
156
|
- !ruby/object:Gem::Version
|
151
157
|
version: 3.0.9
|
158
|
+
- !ruby/object:Gem::Dependency
|
159
|
+
name: rspec
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - ~>
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '3.0'
|
165
|
+
type: :development
|
166
|
+
prerelease: false
|
167
|
+
version_requirements: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - ~>
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '3.0'
|
172
|
+
- !ruby/object:Gem::Dependency
|
173
|
+
name: guard-rspec
|
174
|
+
requirement: !ruby/object:Gem::Requirement
|
175
|
+
requirements:
|
176
|
+
- - ~>
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: '4.3'
|
179
|
+
type: :development
|
180
|
+
prerelease: false
|
181
|
+
version_requirements: !ruby/object:Gem::Requirement
|
182
|
+
requirements:
|
183
|
+
- - ~>
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: '4.3'
|
186
|
+
- !ruby/object:Gem::Dependency
|
187
|
+
name: guard-bundler
|
188
|
+
requirement: !ruby/object:Gem::Requirement
|
189
|
+
requirements:
|
190
|
+
- - ~>
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: '2.0'
|
193
|
+
type: :development
|
194
|
+
prerelease: false
|
195
|
+
version_requirements: !ruby/object:Gem::Requirement
|
196
|
+
requirements:
|
197
|
+
- - ~>
|
198
|
+
- !ruby/object:Gem::Version
|
199
|
+
version: '2.0'
|
200
|
+
- !ruby/object:Gem::Dependency
|
201
|
+
name: growl
|
202
|
+
requirement: !ruby/object:Gem::Requirement
|
203
|
+
requirements:
|
204
|
+
- - ~>
|
205
|
+
- !ruby/object:Gem::Version
|
206
|
+
version: '1.0'
|
207
|
+
type: :development
|
208
|
+
prerelease: false
|
209
|
+
version_requirements: !ruby/object:Gem::Requirement
|
210
|
+
requirements:
|
211
|
+
- - ~>
|
212
|
+
- !ruby/object:Gem::Version
|
213
|
+
version: '1.0'
|
214
|
+
- !ruby/object:Gem::Dependency
|
215
|
+
name: stub_env
|
216
|
+
requirement: !ruby/object:Gem::Requirement
|
217
|
+
requirements:
|
218
|
+
- - '>='
|
219
|
+
- !ruby/object:Gem::Version
|
220
|
+
version: 1.0.1
|
221
|
+
- - <
|
222
|
+
- !ruby/object:Gem::Version
|
223
|
+
version: '2.0'
|
224
|
+
type: :development
|
225
|
+
prerelease: false
|
226
|
+
version_requirements: !ruby/object:Gem::Requirement
|
227
|
+
requirements:
|
228
|
+
- - '>='
|
229
|
+
- !ruby/object:Gem::Version
|
230
|
+
version: 1.0.1
|
231
|
+
- - <
|
232
|
+
- !ruby/object:Gem::Version
|
233
|
+
version: '2.0'
|
234
|
+
- !ruby/object:Gem::Dependency
|
235
|
+
name: pry
|
236
|
+
requirement: !ruby/object:Gem::Requirement
|
237
|
+
requirements:
|
238
|
+
- - '>='
|
239
|
+
- !ruby/object:Gem::Version
|
240
|
+
version: '0'
|
241
|
+
type: :development
|
242
|
+
prerelease: false
|
243
|
+
version_requirements: !ruby/object:Gem::Requirement
|
244
|
+
requirements:
|
245
|
+
- - '>='
|
246
|
+
- !ruby/object:Gem::Version
|
247
|
+
version: '0'
|
248
|
+
- !ruby/object:Gem::Dependency
|
249
|
+
name: pry-nav
|
250
|
+
requirement: !ruby/object:Gem::Requirement
|
251
|
+
requirements:
|
252
|
+
- - '>='
|
253
|
+
- !ruby/object:Gem::Version
|
254
|
+
version: '0'
|
255
|
+
type: :development
|
256
|
+
prerelease: false
|
257
|
+
version_requirements: !ruby/object:Gem::Requirement
|
258
|
+
requirements:
|
259
|
+
- - '>='
|
260
|
+
- !ruby/object:Gem::Version
|
261
|
+
version: '0'
|
152
262
|
description: Xamarin Test Cloud lets you automatically test your app on hundreds of
|
153
263
|
mobile devices
|
154
264
|
email:
|
@@ -163,6 +273,7 @@ files:
|
|
163
273
|
- README.md
|
164
274
|
- bin/test-cloud
|
165
275
|
- lib/xamarin-test-cloud/cli.rb
|
276
|
+
- lib/xamarin-test-cloud/retriable_options.rb
|
166
277
|
- lib/xamarin-test-cloud/version.rb
|
167
278
|
- test/ipa/features/step_definitions/calabash_steps.rb
|
168
279
|
- test/ipa/features/step_definitions/my_first_steps.rb
|