Class: Flaky::Appium
- Inherits:
-
Object
- Object
- Flaky::Appium
- Includes:
- POSIX::Spawn
- Defined in:
- lib/flaky/appium.rb
Overview
noinspection RubyResolve
Constant Summary collapse
- @@thread =
nil
Instance Attribute Summary collapse
-
#android ⇒ Object
readonly
Returns the value of attribute android.
-
#err ⇒ Object
readonly
Returns the value of attribute err.
-
#in ⇒ Object
readonly
Returns the value of attribute in.
-
#ios ⇒ Object
readonly
Returns the value of attribute ios.
-
#log ⇒ Object
readonly
Returns the value of attribute log.
-
#out ⇒ Object
readonly
Returns the value of attribute out.
-
#pid ⇒ Object
readonly
Returns the value of attribute pid.
-
#ready ⇒ Object
readonly
Returns the value of attribute ready.
Class Method Summary collapse
Instance Method Summary collapse
- #end_all_instruments ⇒ Object
-
#end_all_nodes ⇒ Object
if this is defined using self, then instance methods must refer using self.class.end_all_nodes instead self.end_all_nodes is cleaner.
- #flush_buffer ⇒ Object
-
#initialize(opts = {}) ⇒ Appium
constructor
android: true to activate Android mode.
-
#launch ⇒ Object
Invoked inside a thread by ‘self.go`.
- #start ⇒ Object
- #stop ⇒ Object
- #update_buffer(data) ⇒ Object
-
#wait ⇒ Object
Internal methods.
Constructor Details
#initialize(opts = {}) ⇒ Appium
android: true to activate Android mode
64 65 66 67 68 69 70 71 |
# File 'lib/flaky/appium.rb', line 64 def initialize opts={} @ready = false @pid, @in, @out, @err = nil @log = '' @buffer = '' @android = opts.fetch(:android, false) @ios = ! @android end |
Instance Attribute Details
#android ⇒ Object (readonly)
Returns the value of attribute android.
26 27 28 |
# File 'lib/flaky/appium.rb', line 26 def android @android end |
#err ⇒ Object (readonly)
Returns the value of attribute err.
26 27 28 |
# File 'lib/flaky/appium.rb', line 26 def err @err end |
#in ⇒ Object (readonly)
Returns the value of attribute in.
26 27 28 |
# File 'lib/flaky/appium.rb', line 26 def in @in end |
#ios ⇒ Object (readonly)
Returns the value of attribute ios.
26 27 28 |
# File 'lib/flaky/appium.rb', line 26 def ios @ios end |
#log ⇒ Object (readonly)
Returns the value of attribute log.
26 27 28 |
# File 'lib/flaky/appium.rb', line 26 def log @log end |
#out ⇒ Object (readonly)
Returns the value of attribute out.
26 27 28 |
# File 'lib/flaky/appium.rb', line 26 def out @out end |
#pid ⇒ Object (readonly)
Returns the value of attribute pid.
26 27 28 |
# File 'lib/flaky/appium.rb', line 26 def pid @pid end |
#ready ⇒ Object (readonly)
Returns the value of attribute ready.
26 27 28 |
# File 'lib/flaky/appium.rb', line 26 def ready @ready end |
Class Method Details
.kill_all(process_name) ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/flaky/appium.rb', line 46 def self.kill_all process_name begin _pid, _in, _out, _err = POSIX::Spawn::popen4('killall', '-9', process_name) raise "Unable to kill #{process_name}" unless _pid _in.close _out.read _err.read rescue Errno::EAGAIN # POSIX::Spawn::popen4 may raise EAGAIN. If it does, retry after a second. sleep 1 retry ensure [_in, _out, _err].each { |io| io.close unless io.nil? || io.closed? } Process::waitpid(_pid) if _pid end end |
.remove_ios_apps ⇒ Object
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/flaky/appium.rb', line 29 def self.remove_ios_apps user = ENV['USER'] raise 'User must be defined' unless user # Must kill iPhone simulator or strange install errors will occur. self.kill_all 'iPhone Simulator' app_glob = "/Users/#{user}/Library/Application Support/iPhone Simulator/**/Applications" Dir.glob(app_glob) do |ios_app_folder| FileUtils.rm_rf ios_app_folder root = File.dirname ios_app_folder FileUtils.rm_rf File.join(root, 'Library/TCC') FileUtils.rm_rf File.join(root, 'Library/Caches') FileUtils.rm_rf File.join(root, 'Library/Media') end end |
Instance Method Details
#end_all_instruments ⇒ Object
154 155 156 |
# File 'lib/flaky/appium.rb', line 154 def end_all_instruments self.class.kill_all 'instruments' end |
#end_all_nodes ⇒ Object
if this is defined using self, then instance methods must refer using self.class.end_all_nodes instead self.end_all_nodes is cleaner. github.com/rtomayko/posix-spawn#posixspawn-as-a-mixin
150 151 152 |
# File 'lib/flaky/appium.rb', line 150 def end_all_nodes self.class.kill_all 'node' end |
#flush_buffer ⇒ Object
111 112 113 114 115 116 117 118 |
# File 'lib/flaky/appium.rb', line 111 def flush_buffer return @log if @buffer.nil? || @buffer.empty? File.open(@log, 'a') do |f| f.write @buffer end @buffer = '' @log end |
#launch ⇒ Object
Invoked inside a thread by ‘self.go`
159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/flaky/appium.rb', line 159 def launch self.end_all_nodes @ready = false appium_home = ENV['APPIUM_HOME'] raise "ENV['APPIUM_HOME'] must be set!" if appium_home.nil? || appium_home.empty? contains_appium = File.exists?(File.join(ENV['APPIUM_HOME'], 'bin', 'appium.js')) raise "Appium home `#{appium_home}` doesn't contain bin/appium.js!" unless contains_appium cmd = %Q(cd "#{appium_home}"; node .) @pid, @in, @out, @err = popen4 cmd @in.close self # used to chain `launch.wait` end |
#start ⇒ Object
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/flaky/appium.rb', line 73 def start self.stop # stop existing process @log = '/tmp/flaky/appium_tmp_log.txt' File.delete(@log) if File.exists? @log # appium should reset at startup @@thread.exit if @@thread @@thread = Thread.new do Thread.current.abort_on_exception = true self.launch.wait end begin timeout 60 do # timeout in seconds while !self.ready sleep 0.5 end end rescue Timeout::Error # try again if appium fails to become ready # sometimes the simulator never launches. # the sim crashes or any number of issues. self.start end # -e = -A = include other user's processes # -a = include your own processes # -x = include processes without a controlling terminal # ps -eax | grep "tail" # http://askubuntu.com/questions/157075/why-does-ps-aux-grep-x-give-better-results-than-pgrep-x end |
#stop ⇒ Object
172 173 174 175 176 177 178 179 180 181 |
# File 'lib/flaky/appium.rb', line 172 def stop # https://github.com/tmm1/pygments.rb/blob/master/lib/pygments/popen.rb begin Process.kill 'KILL', @pid rescue end unless @pid.nil? @pid = nil self.end_all_nodes self.end_all_instruments unless @android end |
#update_buffer(data) ⇒ Object
106 107 108 109 |
# File 'lib/flaky/appium.rb', line 106 def update_buffer data @buffer += data self.flush_buffer end |
#wait ⇒ Object
Internal methods
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/flaky/appium.rb', line 123 def wait out_err = [@out, @err] # https://github.com/rtomayko/posix-spawn/blob/1d498232660763ff0db6a2f0ab5c1c47fe593896/lib/posix/spawn/child.rb while out_err.any? io_array = IO.select out_err, [], out_err raise 'Appium never spawned' if io_array.nil? ready_for_reading = io_array[0] ready_for_reading.each do |stream| begin capture = stream.readpartial 999_999 update_buffer(capture) if capture @ready = true if !@ready && capture.include?('Appium REST http interface listener started') rescue EOFError out_err.delete stream stream.close end end end end |