xamarin-test-cloud 1.0.0 → 1.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.
- 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
|