fastlane-plugin-automated_test_emulator_run_next 1.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 27b646d002da322ae2a1b3b78901c8c1bcd37ce1034101c6ee7d48a90c7f4d7e
4
+ data.tar.gz: a1ca615cb563af564f750ec0248c5e8b48700f62035758f7b6899e487eeed826
5
+ SHA512:
6
+ metadata.gz: c4a7e1d9ec62d6dc7e29a87711f99354d65b6f35ab12529e8c71cc6d9679b28265224f34aeb5abc6280c9f30788062f44ae507bd69a18993b98d1fc1ea3374fa
7
+ data.tar.gz: 33af3bd42137dc73fc7ffbb550efacbdbe4fd1b7e8b7823ab31784f74182d09a1435845c04369fb3ad3f3037f4d2d8fe472ce7a64baf699c6df486665677e32a
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright for portions of this project are held by [Kamil Krzyk, 2016] as part of project Automated Test Emulator Run. All other copyright for this project are held by [Hiroto Nakamura <hiroto.nakamura95@gmail.com>, 2022].
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # automated_test_emulator_run plugin
2
+
3
+ [![fastlane Plugin Badge](https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg)](https://rubygems.org/gems/fastlane-plugin-automated_test_emulator_run)
4
+
5
+ ## About this fork
6
+
7
+ Forked from original gem as it looks to be abandoned by its original author(s). This fork aims to add support for the [Android Command line tools](https://developer.android.com/studio/command-line) as well as include some improvements that would be useful additions to the base functionality of the plugin.
8
+
9
+ ## About automated_test_emulator_run
10
+
11
+ Starts any number of AVDs. AVDs are created and configured automatically according to user liking before instrumentation test process starts (started either via shell command or from gradle) and killed/deleted after test process finishes.
12
+
13
+ ## Getting Started
14
+
15
+ This project is a [fastlane](https://github.com/fastlane/fastlane) plugin.
16
+
17
+ 1. To get started with `fastlane-plugin-automated_test_emulator_run`, add it to your project by running:
18
+
19
+ ```bash
20
+ fastlane add_plugin automated_test_emulator_run
21
+ ```
22
+ 2. Create your \*.JSON config file to create AVD launch plan according to schema below/provided example.
23
+
24
+ 3. Wrap your test launch command with plugin and provide link to \*.JSON config.
25
+
26
+ ## Example of Fastfile
27
+
28
+ Check out the [example `Fastfile`](fastlane/Fastfile) to see how to use this plugin. Try it by cloning the repo, running `fastlane install_plugins` and `bundle exec fastlane test`.
29
+
30
+ ## JSON config
31
+
32
+ What is JSON config?
33
+
34
+ It is a core of this plugin. User can specify any number of AVD devices in JSON file. Each AVD can be configured separately. Plugin will read JSON file and create fresh, new, untouched AVDs on host - use them in tests - and then delete them after test process finishes.
35
+
36
+ JSON file scheme:
37
+ ```
38
+ {
39
+ "avd_list":
40
+ [
41
+ {
42
+ "avd_name": "",
43
+
44
+ "create_avd_package": "",
45
+ "create_avd_device": "",
46
+ "create_avd_tag": "",
47
+ "create_avd_abi": "",
48
+ "create_avd_additional_options": "",
49
+ "create_avd_hardware_config_filepath": "",
50
+
51
+ "launch_avd_port": "",
52
+ "launch_avd_snapshot_filepath": "",
53
+ "launch_avd_launch_binary_name": "",
54
+ "launch_avd_additional_options": ""
55
+ }
56
+ ]
57
+ }
58
+ ```
59
+
60
+ Parameters:
61
+ <br>For official help refer to `avdmanager` binary file: `<sdk_root>/cmdline-tools/latest/bin/avdmanager create avd`
62
+ - `avd_name` - name of your AVD, avoid using spaces, this field is necessary
63
+ - `create_avd_package` - path to system image in example "system-images;android-23;google_apis;x86_64"
64
+ - `create_avd_device` - name of your device visible on `avdmanager list device` list
65
+ - `create_avd_tag` - the sys-img tag to use for the AVD. e.g. if you are using Google Apis then set it to "google_apis"
66
+ - `create_avd_abi` - abi for AVD e.g. "x86" or "x86_64" (https://developer.android.com/ndk/guides/abis.html)
67
+ - `create_avd_hardware_config_filepath` - path to config.ini file containing custom config for your AVD. After AVD is created this file will be copied into AVD location before it launches.
68
+ - `create_avd_additional_options` - if you think that you need something more you can just add your create parameters here (e.g. "--sdcard 128M", https://developer.android.com/studio/tools/help/android.html)
69
+ - `launch_avd_snapshot_filepath` - plugin might (if you set it) delete and re-create AVD before test start. That means all your permissions and settings will be lost on each emulator run. If you want to apply qemu image with saved AVD state you can put path to it in this field. It will be applied by using "-wipe-data -initdata <path to your file>"
70
+ - `launch_avd_launch_binary_name` - depending on your CPU architecture you need to choose binary file which should launch your AVD (e.g. "emulator", "emulator64-arm")
71
+ - `launch_avd_port` - port on which you wish your AVD should be launched, if you leave this field empty it will be assigned automatically
72
+ - `launch_avd_additional_options` - if you need more customization add your parameters here (e.g. "-gpu on -no-boot-anim -no-window", https://developer.android.com/studio/run/emulator-commandline.html)
73
+
74
+ Note:
75
+ - parameter `--path` is not supported, if you want to change directory to where your AVD are created edit your env variable ANDROID_SDK_HOME. Which is set to `~/.android/avd` by default.
76
+
77
+ Hints:
78
+ - <b> After change from `android` bin to `avdmanager` bin, default settings of AVD created from terminal has changed. No resolution is set. We highly recommend to use config.ini files which you can set to `create_avd_hardware_config_filepath` or specify resolution in `create_avd_additional_options`. </b>
79
+ - all fields need to be present in JSON, if you don't need any of the parameters just leave it empty
80
+ - pick even ports for your AVDs
81
+ - if you can't launch more than 2 AVDs be sure to check how much memory is your HAXM allowed to use (by default it is 2GB and that will allow you to launch around 2 AVDs) If you face any problems with freezing AVDs then be sure to reinstall your HAXM and allow it to use more of RAM (https://software.intel.com/en-us/android/articles/intel-hardware-accelerated-execution-manager)
82
+ - make sure you have all targets/abis installed on your PC if you want to use them (type in terminal: `android list targets`)
83
+ - we recommend adding `-gpu on` to your launching options for each device, it helps when working with many AVDs
84
+
85
+ Example:
86
+
87
+ [Example of complete JSON file can be found here.](fastlane/examples/AVD_setup.json)
88
+
89
+ ## Issues and Feedback
90
+
91
+ For any other issues and feedback about this plugin, please submit it to this repository.
92
+
93
+ ## Troubleshooting
94
+
95
+ If you have trouble using plugins, check out the [Plugins Troubleshooting](https://github.com/fastlane/fastlane/blob/master/fastlane/docs/PluginsTroubleshooting.md) doc in the main `fastlane` repo.
96
+
97
+ ## Using `fastlane` Plugins
98
+
99
+ For more information about how the `fastlane` plugin system works, check out the [Plugins documentation](https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Plugins.md).
100
+
101
+ ## About `fastlane`
102
+
103
+ `fastlane` is the easiest way to automate building and releasing your iOS and Android apps. To learn more, check out [fastlane.tools](https://fastlane.tools).
104
+
@@ -0,0 +1,518 @@
1
+ require 'open3'
2
+ require 'json'
3
+
4
+ module Fastlane
5
+ module Actions
6
+
7
+ class AutomatedTestEmulatorRunAction < Action
8
+ def self.run(params)
9
+ UI.message("The automated_test_emulator_run plugin is working!")
10
+
11
+ # Parse JSON with AVD launch confing to array of AVD_scheme objects
12
+ avd_schemes = Provider::AvdSchemeProvider.get_avd_schemes(params)
13
+
14
+ # ADB, AVD helper classes
15
+ adb_controller = Factory::AdbControllerFactory.get_adb_controller(params)
16
+ avd_controllers = []
17
+
18
+ # Create AVD_Controller class for each AVD_scheme
19
+ for i in 0...avd_schemes.length
20
+ avd_controller = Factory::AvdControllerFactory.get_avd_controller(params, avd_schemes[i])
21
+ avd_controllers << avd_controller
22
+
23
+ if params[:verbose]
24
+ # Checking for output files
25
+ if File.exists?(avd_controller.output_file.path)
26
+ UI.message([
27
+ "Successfully created tmp output file for AVD:",
28
+ avd_schemes[i].avd_name + ".",
29
+ "File: " + avd_controller.output_file.path].join(" ").green)
30
+ else
31
+ UI.message([
32
+ "Unable to create output file for AVD:",
33
+ avd_schemes[i].avd_name + ".",
34
+ "Output will be delegated to null and lost. Check your save/read permissions."].join(" ").red)
35
+ end
36
+ end
37
+ end
38
+
39
+ # Reseting wait states
40
+ all_avd_launched = false
41
+ adb_launch_complete = false
42
+ param_launch_complete = false
43
+
44
+ while(!all_avd_launched)
45
+ # Preparation
46
+ UI.message("Configuring environment in order to launch emulators: ".yellow)
47
+ UI.message("Getting avaliable AVDs".yellow)
48
+ devices = Action.sh(adb_controller.command_get_avds)
49
+
50
+ for i in 0...avd_schemes.length
51
+ unless devices.match(avd_schemes[i].avd_name).nil?
52
+ UI.message(["AVD with name '", avd_schemes[i].avd_name, "' currently exists."].join("").yellow)
53
+ if params[:AVD_recreate_new]
54
+ # Delete existing AVDs
55
+ UI.message("AVD_create_new parameter set to true.".yellow)
56
+ UI.message(["Deleting existing AVD with name:", avd_schemes[i].avd_name].join(" ").yellow)
57
+ Action.sh(avd_controllers[i].command_delete_avd)
58
+
59
+ # Re-create AVD
60
+ UI.message(["Re-creating new AVD."].join(" ").yellow)
61
+ Action.sh(avd_controllers[i].command_create_avd)
62
+ else
63
+ # Use existing AVD
64
+ UI.message("AVD_recreate_new parameter set to false.".yellow)
65
+ UI.message("Using existing AVD for tests.".yellow)
66
+ end
67
+ else
68
+ # Create AVD
69
+ UI.message(["AVD with name '", avd_schemes[i].avd_name, "' does not exist. Creating new AVD."].join("").yellow)
70
+ Action.sh(avd_controllers[i].command_create_avd)
71
+ end
72
+ end
73
+
74
+ # Restart ADB
75
+ if params[:ADB_restart]
76
+ UI.message("Restarting adb".yellow)
77
+ Action.sh(adb_controller.command_stop)
78
+ Action.sh(adb_controller.command_start)
79
+ else
80
+ UI.message("ADB won't be restarted. 'ADB_restart' set to false.".yellow)
81
+ end
82
+
83
+ # Applying custom configs (it's not done directly after create because 'cat' operation seems to fail overwrite)
84
+ for i in 0...avd_schemes.length
85
+ UI.message(["Attemting to apply custom config to ", avd_schemes[i].avd_name].join("").yellow)
86
+ if avd_controllers[i].command_apply_config_avd.eql? ""
87
+ UI.message(["No config file found for AVD '", avd_schemes[i].avd_name, "'. AVD won't have config.ini applied."].join("").yellow)
88
+ else
89
+ UI.message(["Config file found! Applying custom config to: ", avd_schemes[i].avd_name].join("").yellow)
90
+ Action.sh(avd_controllers[i].command_apply_config_avd)
91
+ end
92
+ end
93
+
94
+ # Launching AVDs
95
+ UI.message("Launching all AVDs at the same time.".yellow)
96
+ for i in 0...avd_controllers.length
97
+ Process.fork do
98
+ Action.sh(avd_controllers[i].command_start_avd)
99
+ end
100
+ end
101
+
102
+ # Wait for AVDs finish booting
103
+ UI.message("Waiting for AVDs to finish booting.".yellow)
104
+ UI.message("Performing wait for ADB boot".yellow)
105
+ adb_launch_complete = wait_for_emulator_boot_by_adb(adb_controller, avd_schemes, "#{params[:AVD_adb_launch_timeout]}")
106
+
107
+ # Wait for AVD params finish booting
108
+ if adb_launch_complete
109
+ UI.message("Wait for ADB boot completed with success".yellow)
110
+
111
+ if (params[:AVD_wait_for_bootcomplete] || params[:AVD_wait_for_boot_completed] || params[:AVD_wait_for_bootanim])
112
+ message = "Performing wait for params: "
113
+
114
+ if params[:AVD_wait_for_bootcomplete]
115
+ message += "'dev.bootcomplete', "
116
+ end
117
+
118
+ if params[:AVD_wait_for_boot_completed]
119
+ message += "'sys.boot_completed', "
120
+ end
121
+
122
+ if params[:AVD_wait_for_bootanim]
123
+ message += "'init.svc.bootanim', "
124
+ end
125
+
126
+ message = message[0...-2] + "."
127
+ UI.message(message.yellow)
128
+
129
+ param_launch_complete = wait_for_emulator_boot_by_params(params, adb_controller, avd_controllers, avd_schemes, "#{params[:AVD_param_launch_timeout]}")
130
+ else
131
+ UI.message("Wait for AVD launch params was turned off. Skipping...".yellow)
132
+ param_launch_complete = true
133
+ end
134
+ else
135
+ UI.message("Wait for ADB boot failed".yellow)
136
+ end
137
+
138
+ all_avd_launched = adb_launch_complete && param_launch_complete
139
+
140
+ # Deciding if AVD launch should be restarted
141
+ devices_output = Action.sh(adb_controller.command_get_devices)
142
+
143
+ devices = ""
144
+ devices_output.each_line do |line|
145
+ if line.include?("emulator-")
146
+ devices += line.sub(/\t/, " ")
147
+ end
148
+ end
149
+
150
+ if all_avd_launched
151
+ UI.message("AVDs Booted!".green)
152
+ if params[:logcat]
153
+ for i in 0...avd_schemes.length
154
+ device = ["emulator-", avd_schemes[i].launch_avd_port].join('')
155
+ cmd = [adb_controller.adb_path, '-s', device, 'logcat -c'].join(' ')
156
+ Action.sh(cmd) unless devices.match(device).nil?
157
+ end
158
+ end
159
+ else
160
+ for i in 0...avd_schemes.length
161
+ if params[:verbose]
162
+ # Display AVD output
163
+ if (File.exists?(avd_controllers[i].output_file.path))
164
+ UI.message(["Displaying log for AVD:", avd_schemes[i].avd_name].join(" ").red)
165
+ UI.message(avd_controllers[i].output_file.read.blue)
166
+ end
167
+ end
168
+
169
+ # Killing devices
170
+ unless devices.match(["emulator-", avd_schemes[i].launch_avd_port].join("")).nil?
171
+ Action.sh(avd_controllers[i].command_kill_device)
172
+ end
173
+ end
174
+ end
175
+ end
176
+
177
+ # Launching tests
178
+ shell_task = "#{params[:shell_task]}" unless params[:shell_task].nil?
179
+ gradle_task = "#{params[:gradle_task]}" unless params[:gradle_task].nil?
180
+ lane_task = params[:lane] unless params[:lane].nil?
181
+
182
+ UI.message("Starting tests".green)
183
+ begin
184
+ unless lane_task.nil?
185
+ UI.message("Using lane task.".green)
186
+ Fastlane::LaneManager.cruise_lane(params[:lane_platform], lane_task, params[:lane_options])
187
+ end
188
+
189
+ unless shell_task.nil?
190
+ UI.message("Using shell task.".green)
191
+ Action.sh(shell_task)
192
+ end
193
+
194
+ unless gradle_task.nil?
195
+ gradle = Helper::GradleHelper.new(gradle_path: Dir["./gradlew"].last)
196
+
197
+ UI.message("Using gradle task.".green)
198
+ gradle.trigger(task: params[:gradle_task], flags: params[:gradle_flags], serial: nil)
199
+ end
200
+ ensure
201
+ # Clean up
202
+ for i in 0...avd_schemes.length
203
+ # Kill all emulators
204
+ device = ["emulator-", avd_schemes[i].launch_avd_port].join("")
205
+ unless devices.match(device).nil?
206
+ if params[:logcat]
207
+ file = [device, '.log'].join('')
208
+ cmd = [adb_controller.adb_path, '-s', device, 'logcat -d >', file].join(' ')
209
+ Action.sh(cmd)
210
+ end
211
+ Action.sh(avd_controllers[i].command_kill_device)
212
+ end
213
+
214
+ if params[:verbose]
215
+ # Display AVD output
216
+ if (File.exists?(avd_controllers[i].output_file.path))
217
+ UI.message("Displaying log from AVD to console:".green)
218
+ UI.message(avd_controllers[i].output_file.read.blue)
219
+
220
+ UI.message("Removing temp file.".green)
221
+ avd_controllers[i].output_file.close
222
+ avd_controllers[i].output_file.unlink
223
+ end
224
+ end
225
+
226
+ # Delete AVDs
227
+ if params[:AVD_clean_after]
228
+ UI.message("AVD_clean_after param set to true. Deleting AVDs.".green)
229
+ Action.sh(avd_controllers[i].command_delete_avd)
230
+ else
231
+ UI.message("AVD_clean_after param set to false. Created AVDs won't be deleted.".green)
232
+ end
233
+ end
234
+ end
235
+ end
236
+
237
+ def self.wait_for_emulator_boot_by_adb(adb_controller, avd_schemes, timeout)
238
+ timeoutInSeconds= timeout.to_i
239
+ interval = 1000 * 10
240
+ startTime = Time.now
241
+ lastCheckTime = Time.now
242
+ launch_status_hash = Hash.new
243
+ device_visibility_hash = Hash.new
244
+
245
+ for i in 0...avd_schemes.length
246
+ device_name = ["emulator-", avd_schemes[i].launch_avd_port].join("")
247
+ launch_status_hash.store(device_name, false)
248
+ device_visibility_hash.store(device_name, false)
249
+ end
250
+
251
+ launch_status = false
252
+ loop do
253
+ currentTime = Time.now
254
+ if ((currentTime - lastCheckTime) * 1000) > interval
255
+ lastCheckTime = currentTime
256
+ devices_output = Action.sh(adb_controller.command_get_devices)
257
+
258
+ devices = ""
259
+ devices_output.each_line do |line|
260
+ if line.include?("emulator-")
261
+ devices += line.sub(/\t/, " ")
262
+ end
263
+ end
264
+
265
+ # Check if device is visible
266
+ all_devices_visible = true
267
+ device_visibility_hash.each do |name, is_visible|
268
+ unless (devices.match(name).nil? || is_visible)
269
+ device_visibility_hash[name] = true
270
+ end
271
+ all_devices_visible = false unless is_visible
272
+ end
273
+
274
+ # Check if device is booted
275
+ all_devices_booted = true
276
+ launch_status_hash.each do |name, is_booted|
277
+ unless (devices.match(name + " device").nil? || is_booted)
278
+ launch_status_hash[name] = true
279
+ end
280
+ all_devices_booted = false unless launch_status_hash[name]
281
+ end
282
+
283
+ # Quit if timeout reached
284
+ if ((currentTime - startTime) >= timeoutInSeconds)
285
+ UI.message(["AVD ADB loading took more than ", timeout, ". Attempting to re-launch."].join("").red)
286
+ launch_status = false
287
+ break
288
+ end
289
+
290
+ # Quit if all devices booted
291
+ if (all_devices_booted && all_devices_visible)
292
+ launch_status = true
293
+ break
294
+ end
295
+ end
296
+ end
297
+ return launch_status
298
+ end
299
+
300
+ def self.wait_for_emulator_boot_by_params(params, adb_controller, avd_controllers, avd_schemes, timeout)
301
+ timeout_in_seconds= timeout.to_i
302
+ interval = 1000 * 10
303
+ all_params_launched = false
304
+ start_time = last_scan_ended = Time.now
305
+ device_boot_statuses = Hash.new
306
+
307
+ loop do
308
+ current_time = Time.now
309
+
310
+ # Performing single scan over each device
311
+ if (((current_time - last_scan_ended) * 1000) >= interval || start_time == last_scan_ended)
312
+ for i in 0...avd_schemes.length
313
+ avd_schema = avd_schemes[i]
314
+ avd_controller = avd_controllers[i]
315
+ avd_param_boot_hash = Hash.new
316
+ avd_param_status_hash = Hash.new
317
+ avd_booted = false
318
+
319
+ # Retreiving device parameters according to config
320
+ if params[:AVD_wait_for_bootcomplete]
321
+ dev_bootcomplete, _stdeerr, _status = Open3.capture3([avd_controller.command_get_property, "dev.bootcomplete"].join(" "))
322
+ avd_param_boot_hash.store("dev.bootcomplete", dev_bootcomplete.strip.eql?("1"))
323
+ avd_param_status_hash.store("dev.bootcomplete", dev_bootcomplete)
324
+ end
325
+
326
+ if params[:AVD_wait_for_boot_completed]
327
+ sys_boot_completed, _stdeerr, _status = Open3.capture3([avd_controller.command_get_property, "sys.boot_completed"].join(" "))
328
+ avd_param_boot_hash.store("sys.boot_completed", sys_boot_completed.strip.eql?("1"))
329
+ avd_param_status_hash.store("sys.boot_completed", sys_boot_completed)
330
+ end
331
+
332
+ if params[:AVD_wait_for_bootanim]
333
+ bootanim, _stdeerr, _status = Open3.capture3([avd_controller.command_get_property, "init.svc.bootanim"].join(" "))
334
+ avd_param_boot_hash.store("init.svc.bootanim", bootanim.strip.eql?("stopped"))
335
+ avd_param_status_hash.store("init.svc.bootanim", bootanim)
336
+ end
337
+
338
+ # Checking for param statuses
339
+ avd_param_boot_hash.each do |name, is_booted|
340
+ if !is_booted
341
+ break
342
+ end
343
+ avd_booted = true
344
+ end
345
+ device_boot_statuses.store(avd_schema.avd_name, avd_booted)
346
+
347
+ # Plotting current wait results
348
+ device_log = "Device 'emulator-" + avd_schemes[i].launch_avd_port.to_s + "' launch status:"
349
+ UI.message(device_log.magenta)
350
+ avd_param_boot_hash.each do |name, is_booted|
351
+ device_log = "'" + name + "' - '" + avd_param_status_hash[name].strip + "' (launched: " + is_booted.to_s + ")"
352
+ UI.message(device_log.magenta)
353
+ end
354
+ end
355
+ last_scan_ended = Time.now
356
+ end
357
+
358
+ # Checking if wait doesn't last too long
359
+ if (current_time - start_time) >= timeout_in_seconds
360
+ UI.message(["AVD param loading took more than ", timeout, ". Attempting to re-launch."].join("").red)
361
+ all_params_launched = false
362
+ break
363
+ end
364
+
365
+ # Finishing wait with success if all params are loaded for every device
366
+ device_boot_statuses.each do |name, is_booted|
367
+ if !is_booted
368
+ break
369
+ end
370
+ all_params_launched = true
371
+ end
372
+ if all_params_launched
373
+ break
374
+ end
375
+ end
376
+ return all_params_launched
377
+ end
378
+
379
+ def self.available_options
380
+ [
381
+ #paths
382
+ FastlaneCore::ConfigItem.new(key: :AVD_path,
383
+ env_name: "AVD_PATH",
384
+ description: "The path to your android AVD directory (root). ANDROID_SDK_HOME by default",
385
+ default_value: (ENV['ANDROID_SDK_HOME'].nil? or ENV['ANDROID_SDK_HOME'].eql?("")) ? "~/.android/avd" : ENV['ANDROID_SDK_HOME'],
386
+ is_string: true,
387
+ optional: true),
388
+ FastlaneCore::ConfigItem.new(key: :AVD_setup_path,
389
+ env_name: "AVD_SETUP_PATH",
390
+ description: "Location to AVD_setup.json file which contains info about how many AVD should be launched and their configs",
391
+ is_string: true,
392
+ optional: false),
393
+ FastlaneCore::ConfigItem.new(key: :SDK_path,
394
+ env_name: "SDK_PATH",
395
+ description: "The path to your android sdk directory (root). ANDROID_SDK_HOME by default",
396
+ default_value: ENV['ANDROID_SDK_HOME'] || ENV['ANDROID_HOME'],
397
+ is_string: true,
398
+ optional: true),
399
+
400
+
401
+ #launch config params
402
+ FastlaneCore::ConfigItem.new(key: :AVD_param_launch_timeout,
403
+ env_name: "AVD_PARAM_LAUNCH_TIMEOUT",
404
+ description: "Timeout in seconds. Even though ADB might find all devices you still might want to wait for animations to finish and system to boot. Default 60 seconds",
405
+ default_value: 60,
406
+ is_string: true,
407
+ optional: true),
408
+ FastlaneCore::ConfigItem.new(key: :AVD_adb_launch_timeout,
409
+ env_name: "AVD_ADB_LAUNCH_TIMEOUT",
410
+ description: "Timeout in seconds. Wait until ADB finds all devices specified in config and sets their value to 'device'. Default 240 seconds",
411
+ default_value: 240,
412
+ is_string: true,
413
+ optional: true),
414
+ FastlaneCore::ConfigItem.new(key: :AVD_recreate_new,
415
+ env_name: "AVD_RECREATE_NEW",
416
+ description: "Allow to decide if AVDs from AVD_setup.json (in case they already exist) should be deleted and created from scratch",
417
+ default_value: true,
418
+ is_string: false,
419
+ optional: true),
420
+ FastlaneCore::ConfigItem.new(key: :AVD_clean_after,
421
+ env_name: "AVD_CLEAN_AFTER",
422
+ description: "Allow to decide if AVDs should be deleted from PC after test session ends",
423
+ default_value: true,
424
+ is_string: false,
425
+ optional: true),
426
+ FastlaneCore::ConfigItem.new(key: :ADB_restart,
427
+ env_name: "ADB_RESTART",
428
+ description: "Allows to switch adb restarting on/off",
429
+ default_value: true,
430
+ is_string: false,
431
+ optional: true),
432
+ FastlaneCore::ConfigItem.new(key: :AVD_wait_for_bootcomplete,
433
+ env_name: "AVD_BOOTCOMPLETE_WAIT",
434
+ description: "Allows to switch wait for 'dev.bootcomplete' AVD launch param on/off",
435
+ default_value: true,
436
+ is_string: false,
437
+ optional: true),
438
+ FastlaneCore::ConfigItem.new(key: :AVD_wait_for_boot_completed,
439
+ env_name: "AVD_BOOT_COMPLETED_WAIT",
440
+ description: "Allows to switch wait for 'sys.boot_completed' AVD launch param on/off",
441
+ default_value: true,
442
+ is_string: false,
443
+ optional: true),
444
+ FastlaneCore::ConfigItem.new(key: :AVD_wait_for_bootanim,
445
+ env_name: "ABD_BOOTANIM_WAIT",
446
+ description: "Allows to switch wait for 'init.svc.bootanim' AVD launch param on/off",
447
+ default_value: true,
448
+ is_string: false,
449
+ optional: true),
450
+
451
+ #launch commands
452
+ FastlaneCore::ConfigItem.new(key: :shell_task,
453
+ env_name: "SHELL_TASK",
454
+ description: "The shell command you want to execute",
455
+ conflicting_options: [:gradle_task, :lane],
456
+ is_string: true,
457
+ optional: true),
458
+ FastlaneCore::ConfigItem.new(key: :gradle_task,
459
+ env_name: "GRADLE_TASK",
460
+ description: "The gradle task you want to execute",
461
+ conflicting_options: [:shell_command, :lane],
462
+ is_string: true,
463
+ optional: true),
464
+ FastlaneCore::ConfigItem.new(key: :gradle_flags,
465
+ env_name: "GRADLE_FLAGS",
466
+ description: "All parameter flags you want to pass to the gradle command, e.g. `--exitcode --xml file.xml`",
467
+ conflicting_options: [:shell_command, :lane],
468
+ optional: true,
469
+ is_string: true),
470
+ FastlaneCore::ConfigItem.new(key: :lane,
471
+ env_name: "LANE",
472
+ description: "The lane you want to execute",
473
+ conflicting_options: [:shell_command, :gradle_task],
474
+ is_string: true,
475
+ optional: true),
476
+ FastlaneCore::ConfigItem.new(key: :lane_platform,
477
+ env_name: "LANE_PLATFORM",
478
+ description: "The platform of the lane you want to execute",
479
+ conflicting_options: [:shell_command, :gradle_task],
480
+ is_string: true,
481
+ optional: true),
482
+ FastlaneCore::ConfigItem.new(key: :lane_options,
483
+ env_name: "LANE_OPTIONS",
484
+ description: "The options of the lane you want to execute",
485
+ conflicting_options: [:shell_command, :gradle_task],
486
+ is_string: false,
487
+ optional: true),
488
+
489
+ #mode
490
+ FastlaneCore::ConfigItem.new(key: :verbose,
491
+ env_name: "AVD_VERBOSE",
492
+ description: "Allows to turn on/off mode verbose which displays output of AVDs",
493
+ default_value: false,
494
+ is_string: false,
495
+ optional: true),
496
+ FastlaneCore::ConfigItem.new(key: :logcat,
497
+ env_name: "ADB_LOGCAT",
498
+ description: "Allows to turn logcat on/off so you can debug crashes and such",
499
+ default_value: false,
500
+ is_string: false,
501
+ optional: true),
502
+ ]
503
+ end
504
+
505
+ def self.description
506
+ "Starts AVD, based on AVD_setup.json file, before test launch and kills it after testing is done."
507
+ end
508
+
509
+ def self.authors
510
+ ["F1sherKK"]
511
+ end
512
+
513
+ def self.is_supported?(platform)
514
+ platform == :android
515
+ end
516
+ end
517
+ end
518
+ end
@@ -0,0 +1,62 @@
1
+ module Fastlane
2
+ module Factory
3
+
4
+ class ADB_Controller
5
+ attr_accessor :command_stop,
6
+ :command_start,
7
+ :command_get_devices,
8
+ :command_wait_for_device,
9
+ :command_get_avds,
10
+ :adb_path
11
+ end
12
+
13
+ class AdbControllerFactory
14
+
15
+ def self.get_adb_controller(params)
16
+ UI.message(["Preparing commands for Android ADB"].join(" ").yellow)
17
+
18
+ # Get paths
19
+ sdk_helper = Helper::SdkHelper.new(params)
20
+ path_avdmanager_binary = sdk_helper.avd_manager
21
+ path_adb = sdk_helper.adb
22
+
23
+ # ADB shell command parts
24
+ sh_stop_adb = "kill-server"
25
+ sh_start_adb = "start-server"
26
+ sh_devices_adb = "devices"
27
+ sh_wait_for_device_adb = "wait-for-device"
28
+ sh_list_avd_adb = "list avd"
29
+
30
+ # Assemble ADB controller
31
+ adb_controller = ADB_Controller.new
32
+ adb_controller.command_stop = [
33
+ path_adb,
34
+ sh_stop_adb
35
+ ].join(" ")
36
+
37
+ adb_controller.command_start = [
38
+ path_adb,
39
+ sh_start_adb
40
+ ].join(" ")
41
+
42
+ adb_controller.command_get_devices = [
43
+ path_adb,
44
+ sh_devices_adb
45
+ ].join(" ")
46
+
47
+ adb_controller.command_wait_for_device = [
48
+ path_adb,
49
+ sh_wait_for_device_adb
50
+ ].join(" ")
51
+
52
+ adb_controller.adb_path = path_adb
53
+
54
+ adb_controller.command_get_avds = [
55
+ path_avdmanager_binary,
56
+ sh_list_avd_adb].join(" ").chomp
57
+
58
+ return adb_controller
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,129 @@
1
+ require 'tempfile'
2
+
3
+ module Fastlane
4
+ module Factory
5
+
6
+ class AVD_Controller
7
+ attr_accessor :command_create_avd, :command_start_avd, :command_delete_avd, :command_apply_config_avd, :command_get_property, :command_kill_device,
8
+ :output_file
9
+
10
+ def self.create_output_file(params)
11
+ output_file = Tempfile.new('emulator_output', '#{params[:AVD_path]}')
12
+ end
13
+ end
14
+
15
+ class AvdControllerFactory
16
+
17
+ def self.get_avd_controller(params, avd_scheme)
18
+ UI.message(["Preparing parameters and commands for emulator:", avd_scheme.avd_name].join(" ").yellow)
19
+
20
+ # Get paths
21
+ sdk_helper = Helper::SdkHelper.new(params)
22
+ path_avdmanager_binary = sdk_helper.avd_manager
23
+ path_adb = sdk_helper.adb
24
+ path_avd = "#{params[:AVD_path]}"
25
+
26
+ # Create AVD shell command parts
27
+ sh_create_answer_no = "echo \"no\" |"
28
+ sh_create_avd = "create avd"
29
+ sh_create_avd_name = ["--name \"", avd_scheme.avd_name, "\""].join("")
30
+ sh_create_avd_package = ["--package \"", avd_scheme.create_avd_package, "\""].join("")
31
+
32
+ if avd_scheme.create_avd_device.eql? ""
33
+ sh_create_avd_device = ""
34
+ else
35
+ sh_create_avd_device = ["--device \"", avd_scheme.create_avd_device, "\""].join("")
36
+ end
37
+
38
+ if avd_scheme.create_avd_abi.eql? ""
39
+ sh_create_avd_abi = ""
40
+ else
41
+ sh_create_avd_abi = ["--abi ", avd_scheme.create_avd_abi].join("")
42
+ end
43
+
44
+ if avd_scheme.create_avd_tag.eql? ""
45
+ sh_create_avd_tag = ""
46
+ else
47
+ sh_create_avd_tag = ["--tag ", avd_scheme.create_avd_tag].join("")
48
+ end
49
+
50
+ sh_create_avd_additional_options = avd_scheme.create_avd_additional_options
51
+ sh_create_config_loc = "#{path_avd}/#{avd_scheme.avd_name}.avd/config.ini"
52
+
53
+ # Launch AVD shell command parts
54
+ sh_launch_emulator_binary = [sdk_helper.emulator_dir, avd_scheme.launch_avd_launch_binary_name].join("")
55
+ sh_launch_avd_name = ["-avd ", avd_scheme.avd_name].join("")
56
+ sh_launch_avd_additional_options = avd_scheme.launch_avd_additional_options
57
+ sh_launch_avd_port = ["-port", avd_scheme.launch_avd_port].join(" ")
58
+
59
+ if avd_scheme.launch_avd_snapshot_filepath.eql? ""
60
+ sh_launch_avd_snapshot = ""
61
+ else
62
+ sh_launch_avd_snapshot = ["-wipe-data -initdata ", avd_scheme.launch_avd_snapshot_filepath].join("")
63
+ end
64
+
65
+ # Re-create AVD shell command parts
66
+ sh_delete_avd = ["delete avd -n ", avd_scheme.avd_name].join("")
67
+
68
+ # ADB related shell command parts
69
+ sh_specific_device = "-s"
70
+ sh_device_name_adb = ["emulator-", avd_scheme.launch_avd_port].join("")
71
+ sh_get_property = "shell getprop"
72
+ sh_kill_device = "emu kill"
73
+
74
+ # Assemble AVD controller
75
+ avd_controller = AVD_Controller.new
76
+ avd_controller.command_create_avd = [
77
+ sh_create_answer_no,
78
+ path_avdmanager_binary,
79
+ sh_create_avd,
80
+ sh_create_avd_name,
81
+ sh_create_avd_package,
82
+ sh_create_avd_device,
83
+ sh_create_avd_tag,
84
+ sh_create_avd_abi,
85
+ sh_create_avd_additional_options].join(" ")
86
+
87
+ avd_controller.output_file = Tempfile.new('emulator_output')
88
+ avd_output = File.exists?(avd_controller.output_file) ? ["&>", avd_controller.output_file.path, "&"].join("") : "&>/dev/null &"
89
+
90
+ avd_controller.command_start_avd = [
91
+ sh_launch_emulator_binary,
92
+ sh_launch_avd_port,
93
+ sh_launch_avd_name,
94
+ sh_launch_avd_snapshot,
95
+ sh_launch_avd_additional_options,
96
+ avd_output].join(" ")
97
+
98
+ avd_controller.command_delete_avd = [
99
+ path_avdmanager_binary,
100
+ sh_delete_avd].join(" ")
101
+
102
+ if path_avd.nil? || (avd_scheme.create_avd_hardware_config_filepath.eql? "")
103
+ avd_controller.command_apply_config_avd = ""
104
+ else
105
+ avd_controller.command_apply_config_avd = [
106
+ "cat",
107
+ avd_scheme.create_avd_hardware_config_filepath,
108
+ ">",
109
+ sh_create_config_loc].join(" ")
110
+ end
111
+
112
+ avd_controller.command_get_property = [
113
+ path_adb,
114
+ sh_specific_device,
115
+ sh_device_name_adb,
116
+ sh_get_property].join(" ")
117
+
118
+ avd_controller.command_kill_device = [
119
+ path_adb,
120
+ sh_specific_device,
121
+ sh_device_name_adb,
122
+ sh_kill_device,
123
+ "&>/dev/null"].join(" ")
124
+
125
+ return avd_controller
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,35 @@
1
+ module Fastlane
2
+ module Helper
3
+ class SdkHelper
4
+ def initialize(params)
5
+ @sdk_root_path = params[:SDK_path]
6
+ end
7
+
8
+ def command_line_tools_dir
9
+ return "#{@sdk_root_path}/cmdline-tools/latest/bin" if File.exist?("#{@sdk_root_path}/cmdline-tools/latest/bin")
10
+
11
+ return tools_dir # Fallback on old tools path
12
+ end
13
+
14
+ def tools_dir
15
+ return "#{@sdk_root_path}/tools/bin"
16
+ end
17
+
18
+ def platform_tools_dir
19
+ return "#{@sdk_root_path}/platform-tools"
20
+ end
21
+
22
+ def emulator_dir
23
+ return "#{@sdk_root_path}/emulator/"
24
+ end
25
+
26
+ def adb
27
+ return "#{platform_tools_dir}/adb"
28
+ end
29
+
30
+ def avd_manager
31
+ return "#{command_line_tools_dir}/avdmanager"
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,172 @@
1
+ module Fastlane
2
+ module Provider
3
+
4
+ class AVD_scheme
5
+ attr_accessor :avd_name, :create_avd_package, :create_avd_device, :create_avd_tag, :create_avd_abi, :create_avd_hardware_config_filepath, :create_avd_additional_options,
6
+ :launch_avd_port, :launch_avd_launch_binary_name, :launch_avd_additional_options, :launch_avd_snapshot_filepath
7
+ end
8
+
9
+ class AvdSchemeProvider
10
+
11
+ def self.get_avd_schemes(params)
12
+
13
+ # Read JSON into string variable
14
+ avd_setup_json = read_avd_setup(params)
15
+ if avd_setup_json.nil?
16
+ throw_error("Unable to read AVD_setup.json. Check JSON file structure or file path.")
17
+ end
18
+
19
+ # Read JSON into Hash
20
+ avd_setup = JSON.parse(avd_setup_json)
21
+ avd_hash_list = avd_setup['avd_list']
22
+
23
+ # Create AVD_scheme objects and fill them with data
24
+ avd_scheme_list = []
25
+ for i in 0...avd_hash_list.length
26
+ avd_hash = avd_hash_list[i]
27
+
28
+ avd_scheme = AVD_scheme.new
29
+ avd_scheme.avd_name = avd_hash['avd_name']
30
+
31
+ avd_scheme.create_avd_package = avd_hash['create_avd_package']
32
+ avd_scheme.create_avd_device = avd_hash['create_avd_device']
33
+ avd_scheme.create_avd_tag = avd_hash['create_avd_tag']
34
+ avd_scheme.create_avd_abi = avd_hash['create_avd_abi']
35
+ avd_scheme.create_avd_hardware_config_filepath = avd_hash['create_avd_hardware_config_filepath']
36
+
37
+ avd_scheme.launch_avd_port = avd_hash['launch_avd_port']
38
+ avd_scheme.launch_avd_launch_binary_name = avd_hash['launch_avd_launch_binary_name']
39
+ avd_scheme.launch_avd_additional_options = avd_hash['launch_avd_additional_options']
40
+ avd_scheme.launch_avd_snapshot_filepath = avd_hash['launch_avd_snapshot_filepath']
41
+
42
+ errors = check_avd_fields(avd_scheme)
43
+ unless errors.empty?
44
+ error_log = "Error! Fields not found in JSON: \n"
45
+ errors.each { |error| error_log += error + "\n" }
46
+ throw_error(error_log)
47
+ end
48
+
49
+ avd_scheme_list << avd_scheme
50
+ end
51
+
52
+ # Prepare list of open ports for AVD_schemes without ports set in JSON
53
+ avaliable_ports = get_unused_even_tcp_ports(5556, 5586, avd_scheme_list)
54
+
55
+ # Fill empty AVD_schemes with open ports
56
+ for i in 0...avd_scheme_list.length
57
+ avd_scheme = avd_scheme_list[i]
58
+ if avd_scheme.launch_avd_port.eql? ""
59
+ avd_scheme.launch_avd_port = avaliable_ports[0]
60
+ avaliable_ports.delete(avaliable_ports[0])
61
+ end
62
+ end
63
+
64
+ return avd_scheme_list
65
+ end
66
+
67
+ def self.get_unused_even_tcp_ports(min_port, max_port, avd_scheme_list)
68
+ if min_port % 2 != 0
69
+ min_port += 1
70
+ end
71
+
72
+ if max_port % 2 != 0
73
+ max_port += 1
74
+ end
75
+
76
+ avaliable_ports = []
77
+ reserved_ports = []
78
+
79
+ # Gather ports requested in JSON config
80
+ for i in 0...avd_scheme_list.length
81
+ avd_scheme = avd_scheme_list[i]
82
+ unless avd_scheme.launch_avd_port.eql? ""
83
+ reserved_ports << avd_scheme.launch_avd_port
84
+ end
85
+ end
86
+
87
+ # Find next open port which wasn't reserved in JSON config
88
+ port = min_port
89
+ for i in 0...avd_scheme_list.length
90
+
91
+ while port < max_port do
92
+ if !system("lsof -i:#{port}", out: '/dev/null')
93
+
94
+ is_port_reserved = false
95
+ for j in 0...reserved_ports.length
96
+ if reserved_ports[j].eql?(port.to_s)
97
+ is_port_reserved = true
98
+ break
99
+ end
100
+ end
101
+
102
+ if is_port_reserved
103
+ port = port + 2
104
+ break
105
+ end
106
+
107
+ avaliable_ports << port
108
+ port = port + 2
109
+ break
110
+ else
111
+ port = port + 2
112
+ end
113
+ end
114
+ end
115
+
116
+ return avaliable_ports
117
+ end
118
+
119
+ def self.read_avd_setup(params)
120
+ if File.exists?(File.expand_path("#{params[:AVD_setup_path]}"))
121
+ file = File.open(File.expand_path("#{params[:AVD_setup_path]}"), "rb")
122
+ json = file.read
123
+ file.close
124
+ return json
125
+ else
126
+ return nil
127
+ end
128
+ end
129
+
130
+ def self.check_avd_fields(avd_scheme)
131
+ errors = []
132
+
133
+ if avd_scheme.avd_name.nil?
134
+ errors.push("avd_name not found")
135
+ end
136
+ if avd_scheme.create_avd_package.nil?
137
+ errors.push("create_avd_package not found")
138
+ end
139
+ if avd_scheme.create_avd_device.nil?
140
+ errors.push("create_avd_device not found")
141
+ end
142
+ if avd_scheme.create_avd_tag.nil?
143
+ errors.push("create_avd_tag not found")
144
+ end
145
+ if avd_scheme.create_avd_abi.nil?
146
+ errors.push("create_avd_abi not found")
147
+ end
148
+ if avd_scheme.create_avd_hardware_config_filepath.nil?
149
+ errors.push("create_avd_hardware_config_filepath not found")
150
+ end
151
+ if avd_scheme.launch_avd_snapshot_filepath.nil?
152
+ errors.push("launch_avd_snapshot_filepath not found")
153
+ end
154
+ if avd_scheme.launch_avd_launch_binary_name.nil?
155
+ errors.push("launch_avd_launch_binary_name not found")
156
+ end
157
+ if avd_scheme.launch_avd_port.nil?
158
+ errors.push("launch_avd_port not found")
159
+ end
160
+ if avd_scheme.launch_avd_additional_options.nil?
161
+ errors.push("launch_avd_additional_options not found")
162
+ end
163
+ return errors
164
+ end
165
+
166
+ def self.throw_error(message)
167
+ UI.message("Error: ".red + message.red)
168
+ raise Exception, "Lane was stopped by plugin"
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,5 @@
1
+ module Fastlane
2
+ module AutomatedTestEmulatorRun
3
+ VERSION = "1.0.1"
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ require 'fastlane/plugin/automated_test_emulator_run/version'
2
+
3
+ module Fastlane
4
+ module AutomatedTestEmulatorRunNext
5
+ def self.all_classes
6
+ Dir[File.expand_path('**/{actions,factory,provider,helper}/*.rb', File.dirname(__FILE__))]
7
+ end
8
+ end
9
+ end
10
+
11
+ Fastlane::AutomatedTestEmulatorRunNext.all_classes.each do |current|
12
+ require current
13
+ end
14
+
15
+
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fastlane-plugin-automated_test_emulator_run_next
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Hiroto Nakamura
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-03-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pry
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: fastlane
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 1.98.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 1.98.0
97
+ description:
98
+ email: hiroto.nakamura95@gmail.com
99
+ executables: []
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - LICENSE
104
+ - README.md
105
+ - lib/fastlane/plugin/automated_test_emulator_run/actions/automated_test_emulator_run_action.rb
106
+ - lib/fastlane/plugin/automated_test_emulator_run/factory/adb_controller_factory.rb
107
+ - lib/fastlane/plugin/automated_test_emulator_run/factory/avd_controller_factory.rb
108
+ - lib/fastlane/plugin/automated_test_emulator_run/helper/sdk_tools_helper.rb
109
+ - lib/fastlane/plugin/automated_test_emulator_run/provider/avd_setup_provider.rb
110
+ - lib/fastlane/plugin/automated_test_emulator_run/version.rb
111
+ - lib/fastlane/plugin/automated_test_emulator_run_next.rb
112
+ homepage: https://github.com/Hiroto-N/fastlane-plugin-automated-test-emulator-run
113
+ licenses:
114
+ - MIT
115
+ metadata: {}
116
+ post_install_message:
117
+ rdoc_options: []
118
+ require_paths:
119
+ - lib
120
+ required_ruby_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ requirements: []
131
+ rubygems_version: 3.1.6
132
+ signing_key:
133
+ specification_version: 4
134
+ summary: Starts multiple AVDs based on JSON file config. AVDs are created and configured
135
+ according to user liking before instrumentation test process (started either via
136
+ shell command or gradle) and killed/deleted after test process finishes.
137
+ test_files: []