fastlane-plugin-automated_test_emulator_run_beemo 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 937298268bd82c37e0433e6cf66acab865bc7015dad5cd3206d1b7562b38ed4b
4
+ data.tar.gz: 6cdb1d748ef4b96ea6f0a694045eb90f0c423d7d288ce4fdab3a8c0ba6fddcb6
5
+ SHA512:
6
+ metadata.gz: fab167c6e4e7c0378dd0b55caba789786aefb46aa3d42987be900310ed0ce8fc6c2f56faa347091699ed3c521b31b80dc619cc824c5290d98d245d927a5b5453
7
+ data.tar.gz: fdd13a5cf2d60fd3783eab259d6118b1eb61dc69946914bc5ae42490a038892a9e711eaa126919e859fa207a587a46d56f405131d9eb2ab5a5bc003dd8d9a0d9
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright for portions of project Automated Test Emulator Run Beemo are held by [Kamil Krzyk, 2016] as part of project Automated Test Emulator Run. All other copyright for project Foo are held by [Kai Eßmann <kai.essmann@beemo.eu>, 2001].
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,106 @@
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
+ <b>(article is deprecated - covered plugin version < 1.3.2 which doesn't support Build-Tools ver. >= 25.0.2)</b>
6
+ <br>See [blog post related to this plugin](https://medium.com/azimolabs/managing-android-virtual-devices-during-test-session-98a403acffc2#.upcmonil1). You can learn there how to create basic setup for this plugin step by step.
7
+
8
+ ## About automated_test_emulator_run
9
+
10
+ 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.
11
+
12
+ ## Getting Started
13
+
14
+ This project is a [fastlane](https://github.com/fastlane/fastlane) plugin.
15
+
16
+ 1. To get started with `fastlane-plugin-automated_test_emulator_run`, add it to your project by running:
17
+
18
+ ```bash
19
+ fastlane add_plugin automated_test_emulator_run_beemo
20
+ ```
21
+ 2. Create your \*.JSON config file to create AVD launch plan according to schema below/provided example.
22
+
23
+ 3. Wrap your test launch command with plugin and provide link to \*.JSON config.
24
+
25
+ ## Example of Fastfile
26
+
27
+ 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`.
28
+
29
+ ## JSON config
30
+
31
+ What is JSON config?
32
+
33
+ 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.
34
+
35
+ JSON file scheme:
36
+ ```
37
+ {
38
+ "avd_list":
39
+ [
40
+ {
41
+ "avd_name": "",
42
+
43
+ "create_avd_package": "",
44
+ "create_avd_device": "",
45
+ "create_avd_tag": "",
46
+ "create_avd_abi": "",
47
+ "create_avd_additional_options": "",
48
+ "create_avd_hardware_config_filepath": "",
49
+
50
+ "launch_avd_port": "",
51
+ "launch_avd_snapshot_filepath": "",
52
+ "launch_avd_launch_binary_name": "",
53
+ "launch_avd_additional_options": ""
54
+ }
55
+ ]
56
+ }
57
+ ```
58
+
59
+ Parameters:
60
+ <br>For official help refer to `avdmanager` binary file: `<sdk_root>/tools/bin/avdmanager create avd`
61
+ - `avd_name` - name of your AVD, avoid using spaces, this field is necessary
62
+ - `create_avd_package` - path to system image in example "system-images;android-23;google_apis;x86_64"
63
+ - `create_avd_device` - name of your device visible on `avdmanager list device` list
64
+ - `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"
65
+ - `create_avd_abi` - abi for AVD e.g. "x86" or "x86_64" (https://developer.android.com/ndk/guides/abis.html)
66
+ - `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.
67
+ - `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)
68
+ - `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>"
69
+ - `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")
70
+ - `launch_avd_port` - port on which you wish your AVD should be launched, if you leave this field empty it will be assigned automatically
71
+ - `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)
72
+
73
+ Note:
74
+ - 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.
75
+
76
+ Hints:
77
+ - <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>
78
+ - all fields need to be present in JSON, if you don't need any of the parameters just leave it empty
79
+ - pick even ports for your AVDs
80
+ - 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)
81
+ - make sure you have all targets/abis installed on your PC if you want to use them (type in terminal: `android list targets`)
82
+ - we recommend adding `-gpu on` to your launching options for each device, it helps when working with many AVDs
83
+
84
+ Example:
85
+
86
+ [Example of complete JSON file can be found here.](fastlane/examples/AVD_setup.json)
87
+
88
+ ## Issues and Feedback
89
+
90
+ For any other issues and feedback about this plugin, please submit it to this repository.
91
+
92
+ ## Troubleshooting
93
+
94
+ 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.
95
+
96
+ ## Using `fastlane` Plugins
97
+
98
+ 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).
99
+
100
+ ## About `fastlane`
101
+
102
+ `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).
103
+
104
+ ## Copyright and Licence
105
+
106
+ This Plugin is a fork of [AzimoLabs' Plugin](https://github.com/AzimoLabs/fastlane-plugin-automated-test-emulator-run)
@@ -0,0 +1,493 @@
1
+ require 'open3'
2
+ require 'json'
3
+
4
+ module Fastlane
5
+ module Actions
6
+
7
+ class AutomatedTestEmulatorRunBeemoAction < Action
8
+ def self.run(params)
9
+ UI.message("The automated_test_emulator_run_beemo 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
+
181
+ UI.message("Starting tests".green)
182
+ begin
183
+ unless shell_task.nil?
184
+ UI.message("Using shell task.".green)
185
+ Action.sh(shell_task)
186
+ end
187
+
188
+ unless gradle_task.nil?
189
+ gradle = Helper::GradleHelper.new(gradle_path: Dir["./gradlew"].last)
190
+
191
+ UI.message("Using gradle task.".green)
192
+ gradle.trigger(task: params[:gradle_task], flags: params[:gradle_flags], serial: nil)
193
+ end
194
+ ensure
195
+ # Clean up
196
+ for i in 0...avd_schemes.length
197
+ # Kill all emulators
198
+ device = ["emulator-", avd_schemes[i].launch_avd_port].join("")
199
+ unless devices.match(device).nil?
200
+ if params[:logcat]
201
+ file = [device, '.log'].join('')
202
+ cmd = [adb_controller.adb_path, '-s', device, 'logcat -d >', file].join(' ')
203
+ Action.sh(cmd)
204
+ end
205
+ Action.sh(avd_controllers[i].command_kill_device)
206
+ end
207
+
208
+ if params[:verbose]
209
+ # Display AVD output
210
+ if (File.exists?(avd_controllers[i].output_file.path))
211
+ UI.message("Displaying log from AVD to console:".green)
212
+ UI.message(avd_controllers[i].output_file.read.blue)
213
+
214
+ UI.message("Removing temp file.".green)
215
+ avd_controllers[i].output_file.close
216
+ avd_controllers[i].output_file.unlink
217
+ end
218
+ end
219
+
220
+ # Delete AVDs
221
+ if params[:AVD_clean_after]
222
+ UI.message("AVD_clean_after param set to true. Deleting AVDs.".green)
223
+ Action.sh(avd_controllers[i].command_delete_avd)
224
+ else
225
+ UI.message("AVD_clean_after param set to false. Created AVDs won't be deleted.".green)
226
+ end
227
+ end
228
+ end
229
+ end
230
+
231
+ def self.wait_for_emulator_boot_by_adb(adb_controller, avd_schemes, timeout)
232
+ timeoutInSeconds = timeout.to_i
233
+ interval = 1000 * 10
234
+ startTime = Time.now
235
+ lastCheckTime = Time.now
236
+ launch_status_hash = Hash.new
237
+ device_visibility_hash = Hash.new
238
+
239
+ for i in 0...avd_schemes.length
240
+ device_name = ["emulator-", avd_schemes[i].launch_avd_port].join("")
241
+ launch_status_hash.store(device_name, false)
242
+ device_visibility_hash.store(device_name, false)
243
+ end
244
+
245
+ launch_status = false
246
+ loop do
247
+ currentTime = Time.now
248
+ if ((currentTime - lastCheckTime) * 1000) > interval
249
+ lastCheckTime = currentTime
250
+ devices_output = Action.sh(adb_controller.command_get_devices)
251
+
252
+ devices = ""
253
+ devices_output.each_line do |line|
254
+ if line.include?("emulator-")
255
+ devices += line.sub(/\t/, " ")
256
+ end
257
+ end
258
+
259
+ # Check if device is visible
260
+ all_devices_visible = true
261
+ device_visibility_hash.each do |name, is_visible|
262
+ unless (devices.match(name).nil? || is_visible)
263
+ device_visibility_hash[name] = true
264
+ end
265
+ all_devices_visible = false unless is_visible
266
+ end
267
+
268
+ # Check if device is booted
269
+ all_devices_booted = true
270
+ launch_status_hash.each do |name, is_booted|
271
+ unless (devices.match(name + " device").nil? || is_booted)
272
+ launch_status_hash[name] = true
273
+ end
274
+ all_devices_booted = false unless launch_status_hash[name]
275
+ end
276
+
277
+ # Quit if timeout reached
278
+ if ((currentTime - startTime) >= timeoutInSeconds)
279
+ UI.message(["AVD ADB loading took more than ", timeout, ". Attempting to re-launch."].join("").red)
280
+ launch_status = false
281
+ break
282
+ end
283
+
284
+ # Quit if all devices booted
285
+ if (all_devices_booted && all_devices_visible)
286
+ launch_status = true
287
+ break
288
+ end
289
+ end
290
+ end
291
+ return launch_status
292
+ end
293
+
294
+ def self.wait_for_emulator_boot_by_params(params, adb_controller, avd_controllers, avd_schemes, timeout)
295
+ timeout_in_seconds = timeout.to_i
296
+ interval = 1000 * 10
297
+ all_params_launched = false
298
+ start_time = last_scan_ended = Time.now
299
+ device_boot_statuses = Hash.new
300
+
301
+ loop do
302
+ current_time = Time.now
303
+
304
+ # Performing single scan over each device
305
+ if (((current_time - last_scan_ended) * 1000) >= interval || start_time == last_scan_ended)
306
+ for i in 0...avd_schemes.length
307
+ avd_schema = avd_schemes[i]
308
+ avd_controller = avd_controllers[i]
309
+ avd_param_boot_hash = Hash.new
310
+ avd_param_status_hash = Hash.new
311
+ avd_booted = false
312
+
313
+ # Retreiving device parameters according to config
314
+ if params[:AVD_wait_for_bootcomplete]
315
+ dev_bootcomplete, _stdeerr, _status = Open3.capture3([avd_controller.command_get_property, "dev.bootcomplete"].join(" "))
316
+ avd_param_boot_hash.store("dev.bootcomplete", dev_bootcomplete.strip.eql?("1"))
317
+ avd_param_status_hash.store("dev.bootcomplete", dev_bootcomplete)
318
+ end
319
+
320
+ if params[:AVD_wait_for_boot_completed]
321
+ sys_boot_completed, _stdeerr, _status = Open3.capture3([avd_controller.command_get_property, "sys.boot_completed"].join(" "))
322
+ avd_param_boot_hash.store("sys.boot_completed", sys_boot_completed.strip.eql?("1"))
323
+ avd_param_status_hash.store("sys.boot_completed", sys_boot_completed)
324
+ end
325
+
326
+ if params[:AVD_wait_for_bootanim]
327
+ bootanim, _stdeerr, _status = Open3.capture3([avd_controller.command_get_property, "init.svc.bootanim"].join(" "))
328
+ avd_param_boot_hash.store("init.svc.bootanim", bootanim.strip.eql?("stopped"))
329
+ avd_param_status_hash.store("init.svc.bootanim", bootanim)
330
+ end
331
+
332
+ # Checking for param statuses
333
+ avd_param_boot_hash.each do |name, is_booted|
334
+ if !is_booted
335
+ break
336
+ end
337
+ avd_booted = true
338
+ end
339
+ device_boot_statuses.store(avd_schema.avd_name, avd_booted)
340
+
341
+ # Plotting current wait results
342
+ device_log = "Device 'emulator-" + avd_schemes[i].launch_avd_port.to_s + "' launch status:"
343
+ UI.message(device_log.magenta)
344
+ avd_param_boot_hash.each do |name, is_booted|
345
+ device_log = "'" + name + "' - '" + avd_param_status_hash[name].strip + "' (launched: " + is_booted.to_s + ")"
346
+ UI.message(device_log.magenta)
347
+ end
348
+ end
349
+ last_scan_ended = Time.now
350
+ end
351
+
352
+ # Checking if wait doesn't last too long
353
+ if (current_time - start_time) >= timeout_in_seconds
354
+ UI.message(["AVD param loading took more than ", timeout, ". Attempting to re-launch."].join("").red)
355
+ all_params_launched = false
356
+ break
357
+ end
358
+
359
+ # Finishing wait with success if all params are loaded for every device
360
+ device_boot_statuses.each do |name, is_booted|
361
+ if !is_booted
362
+ break
363
+ end
364
+ all_params_launched = true
365
+ end
366
+ if all_params_launched
367
+ break
368
+ end
369
+ end
370
+ return all_params_launched
371
+ end
372
+
373
+ def self.available_options
374
+ [
375
+ #paths
376
+ FastlaneCore::ConfigItem.new(key: :AVD_path,
377
+ env_name: "AVD_PATH",
378
+ description: "The path to your android AVD directory (root). ANDROID_SDK_HOME by default",
379
+ default_value: ENV['ANDROID_SDK_HOME'].to_s.empty? ? "~/.android/avd" : ENV['ANDROID_SDK_HOME'],
380
+ is_string: true,
381
+ optional: true),
382
+ FastlaneCore::ConfigItem.new(key: :AVD_setup_path,
383
+ env_name: "AVD_SETUP_PATH",
384
+ description: "Location to AVD_setup.json file which contains info about how many AVD should be launched and their configs",
385
+ is_string: true,
386
+ optional: false),
387
+ FastlaneCore::ConfigItem.new(key: :SDK_path,
388
+ env_name: "SDK_PATH",
389
+ description: "The path to your android sdk directory (root). Looks at ANDROID_HOME (deprecated), then ANDROID_SDK_ROOT",
390
+ default_value: ENV['ANDROID_HOME'] || ENV['ANDROID_SDK_ROOT'],
391
+ is_string: true,
392
+ optional: true),
393
+
394
+ #launch config params
395
+ FastlaneCore::ConfigItem.new(key: :AVD_param_launch_timeout,
396
+ env_name: "AVD_PARAM_LAUNCH_TIMEOUT",
397
+ 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",
398
+ default_value: 60,
399
+ is_string: true,
400
+ optional: true),
401
+ FastlaneCore::ConfigItem.new(key: :AVD_adb_launch_timeout,
402
+ env_name: "AVD_ADB_LAUNCH_TIMEOUT",
403
+ description: "Timeout in seconds. Wait until ADB finds all devices specified in config and sets their value to 'device'. Default 240 seconds",
404
+ default_value: 240,
405
+ is_string: true,
406
+ optional: true),
407
+ FastlaneCore::ConfigItem.new(key: :AVD_recreate_new,
408
+ env_name: "AVD_RECREATE_NEW",
409
+ description: "Allow to decide if AVDs from AVD_setup.json (in case they already exist) should be deleted and created from scratch",
410
+ default_value: true,
411
+ is_string: false,
412
+ optional: true),
413
+ FastlaneCore::ConfigItem.new(key: :AVD_clean_after,
414
+ env_name: "AVD_CLEAN_AFTER",
415
+ description: "Allow to decide if AVDs should be deleted from PC after test session ends",
416
+ default_value: true,
417
+ is_string: false,
418
+ optional: true),
419
+ FastlaneCore::ConfigItem.new(key: :ADB_restart,
420
+ env_name: "ADB_RESTART",
421
+ description: "Allows to switch adb restarting on/off",
422
+ default_value: true,
423
+ is_string: false,
424
+ optional: true),
425
+ FastlaneCore::ConfigItem.new(key: :AVD_wait_for_bootcomplete,
426
+ env_name: "AVD_BOOTCOMPLETE_WAIT",
427
+ description: "Allows to switch wait for 'dev.bootcomplete' AVD launch param on/off",
428
+ default_value: true,
429
+ is_string: false,
430
+ optional: true),
431
+ FastlaneCore::ConfigItem.new(key: :AVD_wait_for_boot_completed,
432
+ env_name: "AVD_BOOT_COMPLETED_WAIT",
433
+ description: "Allows to switch wait for 'sys.boot_completed' AVD launch param on/off",
434
+ default_value: true,
435
+ is_string: false,
436
+ optional: true),
437
+ FastlaneCore::ConfigItem.new(key: :AVD_wait_for_bootanim,
438
+ env_name: "ABD_BOOTANIM_WAIT",
439
+ description: "Allows to switch wait for 'init.svc.bootanim' AVD launch param on/off",
440
+ default_value: true,
441
+ is_string: false,
442
+ optional: true),
443
+
444
+ #launch commands
445
+ FastlaneCore::ConfigItem.new(key: :shell_task,
446
+ env_name: "SHELL_TASK",
447
+ description: "The shell command you want to execute",
448
+ conflicting_options: [:gradle_task],
449
+ is_string: true,
450
+ optional: true),
451
+ FastlaneCore::ConfigItem.new(key: :gradle_task,
452
+ env_name: "GRADLE_TASK",
453
+ description: "The gradle task you want to execute",
454
+ conflicting_options: [:shell_command],
455
+ is_string: true,
456
+ optional: true),
457
+ FastlaneCore::ConfigItem.new(key: :gradle_flags,
458
+ env_name: "GRADLE_FLAGS",
459
+ description: "All parameter flags you want to pass to the gradle command, e.g. `--exitcode --xml file.xml`",
460
+ conflicting_options: [:shell_command],
461
+ optional: true,
462
+ is_string: true),
463
+
464
+ #mode
465
+ FastlaneCore::ConfigItem.new(key: :verbose,
466
+ env_name: "AVD_VERBOSE",
467
+ description: "Allows to turn on/off mode verbose which displays output of AVDs",
468
+ default_value: false,
469
+ is_string: false,
470
+ optional: true),
471
+ FastlaneCore::ConfigItem.new(key: :logcat,
472
+ env_name: "ADB_LOGCAT",
473
+ description: "Allows to turn logcat on/off so you can debug crashes and such",
474
+ default_value: false,
475
+ is_string: false,
476
+ optional: true),
477
+ ]
478
+ end
479
+
480
+ def self.description
481
+ "Starts AVD, based on AVD_setup.json file, before test launch and kills it after testing is done."
482
+ end
483
+
484
+ def self.authors
485
+ ["F1sherKK"]
486
+ end
487
+
488
+ def self.is_supported?(platform)
489
+ platform == :android
490
+ end
491
+ end
492
+ end
493
+ 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
+ path_sdk = "#{params[:SDK_path]}"
20
+ path_avdmanager_binary = path_sdk + "/cmdline-tools/latest/bin/avdmanager"
21
+ path_adb = path_sdk + "/platform-tools/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
+ path_sdk = "#{params[:SDK_path]}"
22
+ path_avdmanager_binary = path_sdk + "/cmdline-tools/latest/bin/avdmanager"
23
+ path_adb = path_sdk + "/platform-tools/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 = [path_sdk, "/emulator/", 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,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 AutomatedTestEmulatorRunBeemo
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ require 'fastlane/plugin/automated_test_emulator_run/version'
2
+
3
+ module Fastlane
4
+ module AutomatedTestEmulatorRunBeemo
5
+ def self.all_classes
6
+ Dir[File.expand_path('**/{actions,factory,provider}/*.rb', File.dirname(__FILE__))]
7
+ end
8
+ end
9
+ end
10
+
11
+ Fastlane::AutomatedTestEmulatorRunBeemo.all_classes.each do |current|
12
+ require current
13
+ end
14
+
15
+
metadata ADDED
@@ -0,0 +1,138 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fastlane-plugin-automated_test_emulator_run_beemo
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Kai Eßmann
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-11-10 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: kai.essmann@beemo.eu
99
+ executables: []
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - LICENSE
104
+ - README.md
105
+ - lib/fastlane/plugin/automated_test_emulator_run_beemo.rb
106
+ - lib/fastlane/plugin/automated_test_emulator_run_beemo/actions/automated_test_emulator_run_beemo_action.rb
107
+ - lib/fastlane/plugin/automated_test_emulator_run_beemo/factory/adb_controller_factory.rb
108
+ - lib/fastlane/plugin/automated_test_emulator_run_beemo/factory/avd_controller_factory.rb
109
+ - lib/fastlane/plugin/automated_test_emulator_run_beemo/provider/avd_setup_provider.rb
110
+ - lib/fastlane/plugin/automated_test_emulator_run_beemo/version.rb
111
+ homepage: https://github.com/KaiEssmann/fastlane-plugin-automated-test-emulator-run
112
+ licenses:
113
+ - MIT
114
+ metadata: {}
115
+ post_install_message:
116
+ rdoc_options: []
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ requirements: []
130
+ rubygems_version: 3.2.22
131
+ signing_key:
132
+ specification_version: 4
133
+ summary: Starts n AVDs based on JSON file config. AVDs are created and configured
134
+ according to user liking before instrumentation test process (started either via
135
+ shell command or gradle) and killed/deleted after test process finishes. This fork
136
+ of https://github.com/AzimoLabs/fastlane-plugin-automated-test-emulator-run fixes
137
+ now deprecated android specifications.
138
+ test_files: []