kraken-mobile 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 +7 -0
- data/LICENSE +8 -0
- data/README.md +169 -0
- data/bin/kraken-mobile +91 -0
- data/bin/kraken-mobile-calabash-android.rb +85 -0
- data/bin/kraken-mobile-generate.rb +19 -0
- data/bin/kraken-mobile-helpers.rb +48 -0
- data/bin/kraken-mobile-setup.rb +50 -0
- data/calabash-android-features-skeleton/my_first.feature +11 -0
- data/calabash-android-features-skeleton/step_definitions/kraken_steps.rb +1 -0
- data/calabash-android-features-skeleton/support/app_installation_hooks.rb +25 -0
- data/calabash-android-features-skeleton/support/app_life_cycle_hooks.rb +10 -0
- data/calabash-android-features-skeleton/support/env.rb +1 -0
- data/lib/kraken-mobile.rb +29 -0
- data/lib/kraken-mobile/constants.rb +25 -0
- data/lib/kraken-mobile/helpers/command_helper.rb +38 -0
- data/lib/kraken-mobile/helpers/devices_helper/adb_helper.rb +157 -0
- data/lib/kraken-mobile/helpers/devices_helper/manager.rb +43 -0
- data/lib/kraken-mobile/helpers/feature_analyzer.rb +28 -0
- data/lib/kraken-mobile/helpers/feature_grouper.rb +48 -0
- data/lib/kraken-mobile/helpers/reporter.rb +381 -0
- data/lib/kraken-mobile/models/device.rb +32 -0
- data/lib/kraken-mobile/protocols/file_protocol.rb +126 -0
- data/lib/kraken-mobile/runners/calabash/android/android_runner.rb +130 -0
- data/lib/kraken-mobile/runners/calabash/android/apk_signer.rb +14 -0
- data/lib/kraken-mobile/runners/calabash/android/cucumber.rb +27 -0
- data/lib/kraken-mobile/runners/calabash/android/kraken_hooks.rb +15 -0
- data/lib/kraken-mobile/runners/calabash/android/kraken_steps.rb +3 -0
- data/lib/kraken-mobile/runners/calabash/android/monkey_helper.rb +139 -0
- data/lib/kraken-mobile/runners/calabash/android/operations.rb +44 -0
- data/lib/kraken-mobile/runners/calabash/android/steps/communication_steps.rb +57 -0
- data/lib/kraken-mobile/runners/calabash/monkey/monkey_runner.rb +113 -0
- data/lib/kraken-mobile/runners/runner.rb +18 -0
- data/lib/kraken-mobile/version.rb +5 -0
- data/reporter/assets/css/bootstrap.min.css +6 -0
- data/reporter/assets/css/dataTables.bootstrap.min.css +1 -0
- data/reporter/assets/css/feature_index.css +449 -0
- data/reporter/assets/css/font-awesome.min.css +4 -0
- data/reporter/assets/css/responsive.dataTables.min.css +1 -0
- data/reporter/assets/css/scenario_index.css +461 -0
- data/reporter/assets/fonts/FontAwesome.otf +0 -0
- data/reporter/assets/fonts/fontawesome-webfont.eot +0 -0
- data/reporter/assets/fonts/fontawesome-webfont.svg +2671 -0
- data/reporter/assets/fonts/fontawesome-webfont.ttf +0 -0
- data/reporter/assets/fonts/fontawesome-webfont.woff +0 -0
- data/reporter/assets/fonts/fontawesome-webfont.woff2 +0 -0
- data/reporter/assets/fonts/glyphicons-halflings-regular.eot +0 -0
- data/reporter/assets/fonts/glyphicons-halflings-regular.svg +288 -0
- data/reporter/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/reporter/assets/fonts/glyphicons-halflings-regular.woff +0 -0
- data/reporter/assets/fonts/glyphicons-halflings-regular.woff2 +0 -0
- data/reporter/assets/images/kraken.png +0 -0
- data/reporter/assets/js/Chart.min.js +14 -0
- data/reporter/assets/js/bootstrap.min.js +7 -0
- data/reporter/assets/js/d3.chart.min.js +7 -0
- data/reporter/assets/js/d3.v3.min.js +5 -0
- data/reporter/assets/js/dataTables.bootstrap.min.js +8 -0
- data/reporter/assets/js/dataTables.responsive.min.js +26 -0
- data/reporter/assets/js/first-sankey.js +292 -0
- data/reporter/assets/js/gitgraph.min.js +10 -0
- data/reporter/assets/js/html5shiv.min.js +4 -0
- data/reporter/assets/js/jquery-3.2.1.min.js +4 -0
- data/reporter/assets/js/jquery.dataTables.min.js +167 -0
- data/reporter/assets/js/respond.min.js +5 -0
- data/reporter/assets/js/sankey.js +512 -0
- data/reporter/feature_report.html.erb +274 -0
- data/reporter/index.html.erb +711 -0
- data/reporter/scenario_report.html.erb +174 -0
- metadata +169 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
module KrakenMobile
|
2
|
+
module Models
|
3
|
+
class Device
|
4
|
+
|
5
|
+
#-------------------------------
|
6
|
+
# Fields
|
7
|
+
#-------------------------------
|
8
|
+
attr_accessor :id
|
9
|
+
attr_accessor :model
|
10
|
+
attr_accessor :position
|
11
|
+
attr_accessor :config
|
12
|
+
|
13
|
+
#-------------------------------
|
14
|
+
# Constructors
|
15
|
+
#-------------------------------
|
16
|
+
def initialize(id, model, position, config = {})
|
17
|
+
@id = id
|
18
|
+
@model = model
|
19
|
+
@position = position
|
20
|
+
@config = config
|
21
|
+
end
|
22
|
+
|
23
|
+
#-------------------------------
|
24
|
+
# Helpers
|
25
|
+
#-------------------------------
|
26
|
+
def screenshot_prefix
|
27
|
+
@id.gsub('.', '_').gsub(/:(.*)/, '').to_s + '_'
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'kraken-mobile/helpers/devices_helper/manager'
|
2
|
+
require 'kraken-mobile/constants'
|
3
|
+
require 'calabash-android/operations'
|
4
|
+
require 'digest'
|
5
|
+
|
6
|
+
module KrakenMobile
|
7
|
+
module Protocol
|
8
|
+
module FileProtocol
|
9
|
+
def readSignal(channel, content, timeout)
|
10
|
+
devices_helper = DevicesHelper::Manager.new({runner: ENV["RUNNER"], config_path: ENV["CONFIG_PATH"]}).device_helper
|
11
|
+
device_id = channel_to_device_id(channel)
|
12
|
+
Timeout::timeout(timeout, RuntimeError) do
|
13
|
+
sleep(1) until devices_helper.read_file_content(KrakenMobile::Constants::DEVICE_INBOX_NAME, device_id) == content
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def readLastSignal(channel)
|
18
|
+
devices_helper = DevicesHelper::Manager.new({runner: ENV["RUNNER"], config_path: ENV["CONFIG_PATH"]}).device_helper
|
19
|
+
device_id = channel_to_device_id(channel)
|
20
|
+
devices_helper.read_file_content(KrakenMobile::Constants::DEVICE_INBOX_NAME, device_id)
|
21
|
+
end
|
22
|
+
|
23
|
+
def readAnySignal(channel, timeout)
|
24
|
+
devices_helper = DevicesHelper::Manager.new({runner: ENV["RUNNER"], config_path: ENV["CONFIG_PATH"]}).device_helper
|
25
|
+
device_id = channel_to_device_id(channel)
|
26
|
+
Timeout::timeout(timeout, RuntimeError) do
|
27
|
+
sleep(1) until devices_helper.read_file_content(KrakenMobile::Constants::DEVICE_INBOX_NAME, device_id) != ""
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def readSignalWithKeyworkd(channel, keyword, timeout)
|
32
|
+
devices_helper = DevicesHelper::Manager.new({runner: ENV["RUNNER"], config_path: ENV["CONFIG_PATH"]}).device_helper
|
33
|
+
device_id = channel_to_device_id(channel)
|
34
|
+
Timeout::timeout(timeout, RuntimeError) do
|
35
|
+
sleep(1) until devices_helper.read_file_content(KrakenMobile::Constants::DEVICE_INBOX_NAME, device_id).include?(keyword)
|
36
|
+
return devices_helper.read_file_content(KrakenMobile::Constants::DEVICE_INBOX_NAME, device_id)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def writeSignal(channel, content)
|
41
|
+
devices_helper = DevicesHelper::Manager.new({runner: ENV["RUNNER"], config_path: ENV["CONFIG_PATH"]}).device_helper
|
42
|
+
device_id = channel_to_device_id(channel)
|
43
|
+
devices_helper.write_content_to_file(content, KrakenMobile::Constants::DEVICE_INBOX_NAME, device_id)
|
44
|
+
end
|
45
|
+
|
46
|
+
def writeSignalToAll(content)
|
47
|
+
devices_manager = DevicesHelper::Manager.new({runner: ENV["RUNNER"], config_path: ENV["CONFIG_PATH"]})
|
48
|
+
devices_manager.connected_devices.each do |device|
|
49
|
+
devices_manager.device_helper.write_content_to_file(content, KrakenMobile::Constants::DEVICE_INBOX_NAME, device.id)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def writeSignalToAnyDevice(content)
|
54
|
+
devices_manager = DevicesHelper::Manager.new({runner: ENV["RUNNER"], config_path: ENV["CONFIG_PATH"]})
|
55
|
+
device = devices_manager.connected_devices.sample
|
56
|
+
devices_manager.device_helper.write_content_to_file(content, KrakenMobile::Constants::DEVICE_INBOX_NAME, device.id)
|
57
|
+
device
|
58
|
+
end
|
59
|
+
|
60
|
+
def start_setup channel, scenario
|
61
|
+
devices_manager = DevicesHelper::Manager.new({runner: ENV["RUNNER"], config_path: ENV["CONFIG_PATH"]})
|
62
|
+
device_id = channel_to_device_id(channel)
|
63
|
+
scenario_id = build_scenario_id(scenario)
|
64
|
+
devices_manager.device_helper.write_content_to_file "ready_#{scenario_id}", KrakenMobile::Constants::KRAKEN_CONFIGURATION_FILE_NAME, device_id
|
65
|
+
ordered_tags = ordered_feature_tags scenario
|
66
|
+
while true
|
67
|
+
compare_criteria = devices_manager.connected_devices.count >= ordered_tags.count ? ordered_tags.count : devices_manager.connected_devices.count
|
68
|
+
break if devices_ready_start(devices_manager, scenario_id).count >= compare_criteria
|
69
|
+
sleep(1)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def end_setup channel, scenario
|
74
|
+
devices_manager = DevicesHelper::Manager.new({runner: ENV["RUNNER"], config_path: ENV["CONFIG_PATH"]})
|
75
|
+
device_id = channel_to_device_id(channel)
|
76
|
+
scenario_id = build_scenario_id(scenario)
|
77
|
+
devices_manager.device_helper.write_content_to_file "end_#{scenario_id}", KrakenMobile::Constants::KRAKEN_CONFIGURATION_FILE_NAME, device_id
|
78
|
+
ordered_tags = ordered_feature_tags scenario
|
79
|
+
while true
|
80
|
+
compare_criteria = devices_manager.connected_devices.count >= ordered_tags.count ? ordered_tags.count : devices_manager.connected_devices.count
|
81
|
+
break if devices_ready_to_finish(devices_manager, scenario_id).count >= compare_criteria
|
82
|
+
sleep(1)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# helpers
|
87
|
+
def build_scenario_id scenario
|
88
|
+
location = scenario.location.to_s
|
89
|
+
index_of_line_number_start = location.index(":")
|
90
|
+
real_location = location[0..index_of_line_number_start-1]
|
91
|
+
Digest::SHA256.hexdigest(real_location)
|
92
|
+
end
|
93
|
+
|
94
|
+
def feature_tags scenario
|
95
|
+
tag_objects = scenario.feature.children.map { |e| e.tags if e.tags }.compact
|
96
|
+
tags = []
|
97
|
+
tag_objects.each do |tag_object|
|
98
|
+
names = tag_object.map { |tag| tag.name if tag.name }
|
99
|
+
tags.concat names
|
100
|
+
end
|
101
|
+
tags.uniq.select{ |tag| tag.start_with? "@user" }.sort
|
102
|
+
end
|
103
|
+
|
104
|
+
def ordered_feature_tags scenario
|
105
|
+
tags = feature_tags scenario
|
106
|
+
ordered_tags = []
|
107
|
+
tags.count.times do |index|
|
108
|
+
if tags[index].include? "@user#{index+1}"
|
109
|
+
ordered_tags << tags[index]
|
110
|
+
else
|
111
|
+
break
|
112
|
+
end
|
113
|
+
end
|
114
|
+
ordered_tags
|
115
|
+
end
|
116
|
+
|
117
|
+
def devices_ready_start devices_manager, scenario_id
|
118
|
+
devices_manager.connected_devices.select { |device| devices_manager.device_helper.read_file_content(KrakenMobile::Constants::KRAKEN_CONFIGURATION_FILE_NAME, device.id) == "ready_#{scenario_id}" }
|
119
|
+
end
|
120
|
+
|
121
|
+
def devices_ready_to_finish devices_manager, scenario_id
|
122
|
+
devices_manager.connected_devices.select { |device| devices_manager.device_helper.read_file_content(KrakenMobile::Constants::KRAKEN_CONFIGURATION_FILE_NAME, device.id) == "end_#{scenario_id}" }
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'kraken-mobile/helpers/devices_helper/manager'
|
2
|
+
require 'kraken-mobile/helpers/feature_grouper'
|
3
|
+
require 'kraken-mobile/helpers/reporter'
|
4
|
+
require 'kraken-mobile/runners/runner'
|
5
|
+
require 'kraken-mobile/constants'
|
6
|
+
require 'kraken-mobile/runners/calabash/android/apk_signer.rb'
|
7
|
+
require 'parallel'
|
8
|
+
require 'digest'
|
9
|
+
require 'fileutils'
|
10
|
+
require 'erb'
|
11
|
+
|
12
|
+
module KrakenMobile
|
13
|
+
module Runner
|
14
|
+
class CalabashAndroidRunner < KrakenRunner
|
15
|
+
BASE_COMMAND = "calabash-android run"
|
16
|
+
|
17
|
+
def initialize(options)
|
18
|
+
super(options)
|
19
|
+
default_runner = KrakenMobile::Constants::CALABASH_ANDROID
|
20
|
+
@devices_manager = DevicesHelper::Manager.new({runner: default_runner, config_path: @options[:config_path]})
|
21
|
+
@adb_helper = @devices_manager.device_helper
|
22
|
+
@execution_id = Digest::SHA256.hexdigest("#{Time.now.to_f}")
|
23
|
+
@reporter = KrakenMobile::Reporter.new(@execution_id, options)
|
24
|
+
end
|
25
|
+
|
26
|
+
#-------------------------------
|
27
|
+
# Hooks
|
28
|
+
#-------------------------------
|
29
|
+
def before_all
|
30
|
+
Dir.mkdir(KrakenMobile::Constants::REPORT_PATH) unless File.exists?(KrakenMobile::Constants::REPORT_PATH)
|
31
|
+
Dir.mkdir("#{KrakenMobile::Constants::REPORT_PATH}/#{@execution_id}")
|
32
|
+
devices_id_list = []
|
33
|
+
@devices_manager.connected_devices.each_with_index do |device, index|
|
34
|
+
height, width = @adb_helper.screen_size device.id
|
35
|
+
sdk_version = @adb_helper.sdk_version device.id
|
36
|
+
devices_id_list << { user: (index+1), id: device.id, model: device.model, screen_height: height, screen_width: width, sdk: sdk_version }
|
37
|
+
Dir.mkdir("#{KrakenMobile::Constants::REPORT_PATH}/#{@execution_id}/#{device.id}")
|
38
|
+
end
|
39
|
+
file = open("#{KrakenMobile::Constants::REPORT_PATH}/#{@execution_id}/#{KrakenMobile::Constants::REPORT_DEVICES_FILE_NAME}.json", 'w')
|
40
|
+
file.puts(devices_id_list.to_json)
|
41
|
+
file.close
|
42
|
+
source_dir = File.expand_path("../../../../../../reporter/assets/", __FILE__)
|
43
|
+
FileUtils.cp_r(source_dir, "#{KrakenMobile::Constants::REPORT_PATH}/#{@execution_id}/")
|
44
|
+
end
|
45
|
+
|
46
|
+
def before_execution process_number
|
47
|
+
device = @devices_manager.connected_devices[process_number]
|
48
|
+
raise "There is no device for process #{process_number}" unless device
|
49
|
+
@adb_helper.create_file KrakenMobile::Constants::DEVICE_INBOX_NAME, device.id
|
50
|
+
@adb_helper.create_file KrakenMobile::Constants::KRAKEN_CONFIGURATION_FILE_NAME, device.id
|
51
|
+
end
|
52
|
+
|
53
|
+
def after_execution process_number
|
54
|
+
device = @devices_manager.connected_devices[process_number]
|
55
|
+
raise "There is no device for process #{process_number}" unless device
|
56
|
+
@adb_helper.delete_file KrakenMobile::Constants::DEVICE_INBOX_NAME, device.id
|
57
|
+
@adb_helper.delete_file KrakenMobile::Constants::KRAKEN_CONFIGURATION_FILE_NAME, device.id
|
58
|
+
end
|
59
|
+
|
60
|
+
#-------------------------------
|
61
|
+
# Execution
|
62
|
+
#-------------------------------
|
63
|
+
def run_in_parallel
|
64
|
+
ensure_apks_signed
|
65
|
+
before_all
|
66
|
+
feature_folder = @options[:feature_folder]
|
67
|
+
devices_connected = @devices_manager.connected_devices
|
68
|
+
groups = FeatureGrouper.file_groups(feature_folder, devices_connected.size)
|
69
|
+
threads = groups.size
|
70
|
+
puts "Running with #{threads} threads: #{groups}"
|
71
|
+
test_results = Parallel.map_with_index(
|
72
|
+
groups,
|
73
|
+
:in_threads => threads,
|
74
|
+
:start => lambda { |group, index|
|
75
|
+
before_execution(index)
|
76
|
+
},
|
77
|
+
:finish => lambda { |group, index, _|
|
78
|
+
after_execution(index)
|
79
|
+
}
|
80
|
+
) do |group, index|
|
81
|
+
run_tests(group, index, @options)
|
82
|
+
@reporter.generate_device_report devices_connected[index]
|
83
|
+
end
|
84
|
+
@reporter.generate_general_report
|
85
|
+
end
|
86
|
+
|
87
|
+
def run_tests(test_files, process_number, options)
|
88
|
+
command = build_execution_command(process_number, options[:apk_path], test_files)
|
89
|
+
puts "\n****** PROCESS #{process_number} STARTED ******\n\n"
|
90
|
+
@command_helper.execute_command(process_number, command)
|
91
|
+
puts "\n****** PROCESS #{process_number} COMPLETED ******\n\n"
|
92
|
+
end
|
93
|
+
|
94
|
+
#-------------------------------
|
95
|
+
# Helpers
|
96
|
+
#-------------------------------
|
97
|
+
def build_execution_command process_number, general_apk, test_files
|
98
|
+
device = @devices_manager.connected_devices[process_number]
|
99
|
+
raise "Theres not a device for process #{process_number}" unless device
|
100
|
+
apk_path = device.config["apk_path"] ? device.config["apk_path"] : general_apk
|
101
|
+
raise "Invalid apk path" unless apk_path
|
102
|
+
cucumber_options = "--format pretty --format json -o #{KrakenMobile::Constants::REPORT_PATH}/#{@execution_id}/#{device.id}/#{KrakenMobile::Constants::REPORT_FILE_NAME}.json"
|
103
|
+
execution_command = @command_helper.build_command [BASE_COMMAND, apk_path, cucumber_options, *test_files, "--tags @user#{device.position}"]
|
104
|
+
env_variables = {
|
105
|
+
AUTOTEST: '1',
|
106
|
+
ADB_DEVICE_ARG: device.id,
|
107
|
+
DEVICE_INFO: device.model,
|
108
|
+
TEST_PROCESS_NUMBER: (process_number+1).to_s,
|
109
|
+
SCREENSHOT_PATH: "#{KrakenMobile::Constants::REPORT_PATH}/#{@execution_id}/#{device.id}/#{device.screenshot_prefix}",
|
110
|
+
PROTOCOL: @options[:protocol],
|
111
|
+
RUNNER: KrakenMobile::Constants::CALABASH_ANDROID
|
112
|
+
}
|
113
|
+
env_variables[:CONFIG_PATH] = @options[:config_path] if @options[:config_path]
|
114
|
+
env_variables[:PROPERTIES_PATH] = @options[:properties_path] if @options[:properties_path]
|
115
|
+
exports = @command_helper.build_export_env_command env_variables
|
116
|
+
exports + @command_helper.terminal_command_separator + execution_command
|
117
|
+
end
|
118
|
+
|
119
|
+
def ensure_apks_signed
|
120
|
+
checked_apks = {}
|
121
|
+
@devices_manager.connected_devices.each do |device|
|
122
|
+
apk_path = device.config["apk_path"] ? device.config["apk_path"] : @options[:apk_path]
|
123
|
+
next if checked_apks[apk_path] # Dont check already checked apks
|
124
|
+
raise "APK is not signed, you can resign the app by running kraken-mobile resign #{apk_path}" if !KrakenMobile::CalabashAndroid::ApkSigner.is_apk_signed? apk_path
|
125
|
+
checked_apks[apk_path] = apk_path
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'calabash-android/helpers'
|
2
|
+
require 'calabash-android/java_keystore'
|
3
|
+
|
4
|
+
module KrakenMobile
|
5
|
+
module CalabashAndroid
|
6
|
+
module ApkSigner
|
7
|
+
def self.is_apk_signed? apk_path
|
8
|
+
keystores = JavaKeystore.get_keystores
|
9
|
+
apk_fingerprint = fingerprint_from_apk(apk_path)
|
10
|
+
keystores.select { |k| k.fingerprint == apk_fingerprint}.any?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'calabash-android/cucumber'
|
2
|
+
require 'calabash-android/operations'
|
3
|
+
require 'kraken-mobile/runners/calabash/android/kraken_hooks'
|
4
|
+
require 'kraken-mobile/runners/calabash/android/operations'
|
5
|
+
require 'kraken-mobile/runners/calabash/android/monkey_helper'
|
6
|
+
require 'kraken-mobile/constants'
|
7
|
+
require 'kraken-mobile/protocols/file_protocol'
|
8
|
+
|
9
|
+
def requested_protocol
|
10
|
+
case ENV["PROTOCOL"]
|
11
|
+
when KrakenMobile::Constants::FILE_PROTOCOL
|
12
|
+
KrakenMobile::Protocol::FileProtocol
|
13
|
+
else
|
14
|
+
raise "Invalid Kraken protocol."
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
World(Calabash::Android::ColorHelper)
|
19
|
+
World(Calabash::Android::Operations)
|
20
|
+
World(KrakenMobile::CalabashAndroid::Operations)
|
21
|
+
World(KrakenMobile::CalabashAndroid::MonkeyHelper)
|
22
|
+
World(requested_protocol())
|
23
|
+
|
24
|
+
AfterConfiguration do
|
25
|
+
require 'calabash-android/calabash_steps'
|
26
|
+
require 'kraken-mobile/runners/calabash/android/kraken_steps'
|
27
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'calabash-android/management/adb'
|
2
|
+
require 'calabash-android/operations'
|
3
|
+
|
4
|
+
Before do |scenario|
|
5
|
+
install_app_with_calabash()
|
6
|
+
@scenario_tags = scenario.source_tag_names
|
7
|
+
end
|
8
|
+
|
9
|
+
After do |scenario|
|
10
|
+
@scenario_tags = scenario.source_tag_names
|
11
|
+
end
|
12
|
+
|
13
|
+
AfterStep do |scenario|
|
14
|
+
screenshot_embed
|
15
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'calabash-android/monkey_helpers'
|
2
|
+
require 'kraken-mobile/constants'
|
3
|
+
|
4
|
+
module KrakenMobile
|
5
|
+
module CalabashAndroid
|
6
|
+
module MonkeyHelper
|
7
|
+
|
8
|
+
# Runs inteligent monkey
|
9
|
+
def run_intelligent_monkey channel, number_of_events
|
10
|
+
device_id = channel_to_device_id channel
|
11
|
+
logger = open("./#{device_id}.txt", 'w')
|
12
|
+
number_of_events.times do |i|
|
13
|
+
handle_random_action channel, logger
|
14
|
+
end
|
15
|
+
logger.close
|
16
|
+
end
|
17
|
+
|
18
|
+
# Runs adb monkey
|
19
|
+
def run_monkey channel, number_of_events
|
20
|
+
devices_helper = DevicesHelper::Manager.new({runner: ENV["RUNNER"], config_path: ENV["CONFIG_PATH"]}).device_helper
|
21
|
+
device_id = channel_to_device_id channel
|
22
|
+
height, width = devices_helper.screen_size device_id
|
23
|
+
start_monkey
|
24
|
+
actions = [:move, :down, :up]
|
25
|
+
number_of_events.times do |i|
|
26
|
+
monkey_touch(actions.sample, rand(5..(width-5)) , rand(5..(height-5)))
|
27
|
+
end
|
28
|
+
kill_existing_monkey_processes
|
29
|
+
end
|
30
|
+
|
31
|
+
# Runs monkey in an speciic part of the screen
|
32
|
+
def run_small_monkey channel, number_of_events, height_start, height_end, width_start, width_end
|
33
|
+
devices_helper = DevicesHelper::Manager.new({runner: ENV["RUNNER"], config_path: ENV["CONFIG_PATH"]}).device_helper
|
34
|
+
device_id = channel_to_device_id channel
|
35
|
+
height, width = devices_helper.screen_size device_id
|
36
|
+
start_monkey
|
37
|
+
actions = [:move, :down, :up]
|
38
|
+
numb_height_start = (height*(height_start/100.0)).to_i+5
|
39
|
+
numb_height_end = (height*(height_end/100.0)).to_i-5
|
40
|
+
numb_width_start = (width*(width_start/100.0)).to_i+5
|
41
|
+
numb_width_end = (width*(width_end/100.0)).to_i-5
|
42
|
+
number_of_events.times do |i|
|
43
|
+
pos_x = rand(numb_width_start..numb_width_end)
|
44
|
+
pos_y = rand(numb_height_start..numb_height_end)
|
45
|
+
monkey_touch(actions.sample,pos_x,pos_y)
|
46
|
+
end
|
47
|
+
kill_existing_monkey_processes
|
48
|
+
end
|
49
|
+
|
50
|
+
###########################################
|
51
|
+
############## Events #####################
|
52
|
+
###########################################
|
53
|
+
def handle_random_action channel, logger
|
54
|
+
begin
|
55
|
+
Timeout::timeout(KrakenMobile::Constants::MONKEY_DEFAULT_TIMEOUT, RuntimeError) do
|
56
|
+
arr = [method(:enter_last_signal_in_random_input), method(:send_random_signal), method(:random_click)]
|
57
|
+
arr.sample.call(channel, logger)
|
58
|
+
end
|
59
|
+
rescue => e
|
60
|
+
puts "#{ENV['TEST_PROCESS_NUMBER']}> e"
|
61
|
+
logger.puts(e)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def random_click channel, logger
|
66
|
+
elements = query("*")
|
67
|
+
element = elements.sample if elements
|
68
|
+
return if !element
|
69
|
+
x = element["rect"]["x"]
|
70
|
+
y = element["rect"]["y"]
|
71
|
+
begin
|
72
|
+
perform_action(random_touch_action, x, y)
|
73
|
+
puts "#{ENV['TEST_PROCESS_NUMBER']}> random_click - Coordinates: #{x},#{y}"
|
74
|
+
logger.puts("random_click - Coordinates: #{x},#{y}")
|
75
|
+
rescue => e
|
76
|
+
puts "#{ENV['TEST_PROCESS_NUMBER']}> #{e}"
|
77
|
+
logger.puts(e)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def enter_last_signal_in_random_input channel, logger
|
82
|
+
last_signal = readLastSignal(channel)
|
83
|
+
enter_text_in_random_input last_signal, logger
|
84
|
+
puts "#{ENV['TEST_PROCESS_NUMBER']}> enter_last_signal_in_random_input - Signal: #{last_signal}"
|
85
|
+
logger.puts("enter_last_signal_in_random_input - Signal: #{last_signal}")
|
86
|
+
end
|
87
|
+
|
88
|
+
def enter_text_in_random_input text, logger
|
89
|
+
return if input_texts.count <= 0
|
90
|
+
input = input_texts.sample
|
91
|
+
x = input["rect"]["x"]
|
92
|
+
y = input["rect"]["y"]
|
93
|
+
perform_action(random_touch_action, x, y)
|
94
|
+
enter_text text
|
95
|
+
end
|
96
|
+
|
97
|
+
def send_random_signal channel, logger
|
98
|
+
return if app_texts.count <= 0
|
99
|
+
text = app_texts.sample
|
100
|
+
# TODO Remove all special characters
|
101
|
+
text.slice!("(")
|
102
|
+
text.slice!(")")
|
103
|
+
text.slice!("'")
|
104
|
+
text.slice!("\"")
|
105
|
+
send_signal_method = [method(:writeSignalToAnyDevice), method(:writeSignalToAll)]
|
106
|
+
ans = send_signal_method.sample.call(text)
|
107
|
+
if ans
|
108
|
+
puts "#{ENV['TEST_PROCESS_NUMBER']}> send_random_signal to #{ans.id} - Signal: #{text}"
|
109
|
+
logger.puts("send_random_signal to #{ans.id} - Signal: #{text}")
|
110
|
+
else
|
111
|
+
puts "#{ENV['TEST_PROCESS_NUMBER']}> send_random_signal - Signal: #{text}"
|
112
|
+
logger.puts("send_random_signal - Signal: #{text}")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def random_touch_action
|
117
|
+
actions = ["touch_coordinate"]
|
118
|
+
actions.sample
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
def app_texts
|
123
|
+
query("*", "text").select{ |e| !e["error"]}
|
124
|
+
end
|
125
|
+
|
126
|
+
def buttons
|
127
|
+
query("android.support.v7.widget.AppCompatButton")
|
128
|
+
end
|
129
|
+
|
130
|
+
def enter_text text
|
131
|
+
perform_action('keyboard_enter_text', text) if keyboard_visible?
|
132
|
+
end
|
133
|
+
|
134
|
+
def input_texts
|
135
|
+
query("android.support.v7.widget.AppCompatEditText")
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|