lib/xcmonkey/driver.rb in xcmonkey-1.2.0 vs lib/xcmonkey/driver.rb in xcmonkey-1.3.0

- old
+ new

@@ -1,14 +1,16 @@ class Driver - attr_accessor :udid, :bundle_id, :enable_simulator_keyboard, :session_duration, :session_path, :session_actions + attr_accessor :udid, :bundle_id, :disable_simulator_keyboard, :event_count, :session_path, :session_actions, :ignore_crashes, :throttle def initialize(params) self.udid = params[:udid] + self.throttle = params[:throttle] self.bundle_id = params[:bundle_id] - self.session_duration = params[:duration] + self.event_count = params[:event_count] self.session_path = params[:session_path] - self.enable_simulator_keyboard = params[:enable_simulator_keyboard] + self.ignore_crashes = params[:ignore_crashes] + self.disable_simulator_keyboard = params[:disable_simulator_keyboard] self.session_actions = params[:session_actions] @session = { params: params, actions: [] } ensure_driver_installed end @@ -21,14 +23,12 @@ @running_apps = list_running_apps end def monkey_test(gestures) monkey_test_precondition - app_elements = describe_ui.shuffle - current_time = Time.now - counter = 0 - while Time.now < current_time + session_duration + event_count.times do |counter| + app_elements = describe_ui.shuffle el1_coordinates = central_coordinates(app_elements.first) el2_coordinates = central_coordinates(app_elements.last) case gestures.sample when :precise_tap tap(coordinates: el1_coordinates) @@ -51,22 +51,18 @@ duration: swipe_duration ) else next end - detect_app_state_change - track_running_apps if counter % 5 == 0 # Track running apps after every 5th action to speed up the test - counter += 1 - app_elements = describe_ui.shuffle + checkup(counter) end save_session end def repeat_monkey_test monkey_test_precondition - counter = 0 - session_actions.each do |action| + session_actions.each_with_index do |action, counter| case action['type'] when 'tap' tap(coordinates: { x: action['x'], y: action['y'] }) when 'press' press(coordinates: { x: action['x'], y: action['y'] }, duration: action['duration']) @@ -77,16 +73,22 @@ duration: action['duration'] ) else next end - detect_app_state_change - track_running_apps if counter % 5 == 0 - counter += 1 + checkup(counter) end end + def checkup(counter) + detect_app_state_change + if counter % 5 == 0 || throttle.to_i > 0 # Track running apps after every 5th action + track_running_apps # (unless `throttle` was provided) to speed up the test + end + check_speed_limit + end + def describe_ui JSON.parse(`idb ui describe-all --udid #{udid}`) end def describe_point(x, y) @@ -113,11 +115,11 @@ `idb shutdown #{udid}` end def configure_simulator_keyboard shutdown_simulator - keyboard_status = enable_simulator_keyboard ? 0 : 1 + keyboard_status = disable_simulator_keyboard ? 1 : 0 `defaults write com.apple.iphonesimulator ConnectHardwareKeyboard #{keyboard_status}` end def list_targets @targets ||= `idb list-targets --json`.split("\n").map! { |target| JSON.parse(target) } @@ -163,14 +165,12 @@ @session[:actions] << { type: :press, x: coordinates[:x], y: coordinates[:y], duration: duration } unless session_actions `idb ui tap --udid #{udid} --duration #{duration} #{coordinates[:x]} #{coordinates[:y]}` end def swipe(start_coordinates:, end_coordinates:, duration:) - Logger.info( - "Swipe (#{duration}s):", - payload: "#{JSON.pretty_generate(start_coordinates)} => #{JSON.pretty_generate(end_coordinates)}" - ) + payload = "#{JSON.pretty_generate(start_coordinates)} => #{JSON.pretty_generate(end_coordinates)}" + Logger.info("Swipe (#{duration}s):", payload: payload) unless session_actions @session[:actions] << { type: :swipe, x: start_coordinates[:x], y: start_coordinates[:y], @@ -186,12 +186,12 @@ def central_coordinates(element) frame = element['frame'] x = (frame['x'] + (frame['width'] / 2)).abs.to_i y = (frame['y'] + (frame['height'] / 2)).abs.to_i { - x: x > screen_size[:width].to_i ? rand(0..screen_size[:width].to_i) : x, - y: y > screen_size[:height].to_i ? rand(0..screen_size[:height].to_i) : y + x: x > screen_size[:width].to_i ? random_coordinates[:x] : x, + y: y > screen_size[:height].to_i ? random_coordinates[:y] : y } end def random_coordinates { @@ -220,10 +220,12 @@ def press_duration rand(0.5..1.5).ceil(1) end def save_session + return if session_path.nil? + File.write("#{session_path}/xcmonkey-session.json", JSON.pretty_generate(@session)) end # This function takes ≈200ms def track_running_apps @@ -234,10 +236,11 @@ new_apps = currently_running_bundle_ids - previously_running_bundle_ids return if new_apps.empty? launch_app(target_bundle_id: bundle_id) + new_apps.each do |id| Logger.warn("Shutting down: #{id}") terminate_app(id) end end @@ -247,20 +250,24 @@ def detect_app_state_change return unless detect_app_in_background target_app_is_running = list_running_apps.any? { |app| app['bundle_id'] == bundle_id } - if target_app_is_running + if target_app_is_running || ignore_crashes launch_app(target_bundle_id: bundle_id) else save_session Logger.error("Target app has crashed or been terminated") end end def detect_app_in_background current_app_label = describe_ui.detect { |el| el['type'] == 'Application' }['AXLabel'] current_app_label.nil? || current_app_label.strip.empty? + end + + def check_speed_limit + sleep(throttle / 1000.0) if throttle.to_i > 0 end private def ensure_driver_installed