module Flaky
Flaky.trace_specs
trace: Dir.glob(File.join(__dir__, ‘**’, ‘*.rb’)) # verbose logging
Constants
- DATE
- VERSION
Attributes
no_video[RW]
Public Class Methods
capture_ios_app_log(app_name)
click to toggle source
app_name for example MyApp.app
# File lib/screen_recording.rb, line 12 def capture_ios_app_log app_name # nop -- this feature has moved into the appium server end
run_all_tests(opts={})
click to toggle source
# File lib/flaky/run/all_tests.rb, line 3 def self.run_all_tests opts={} raise 'Must pass :count and :os' unless opts && opts[:count] && opts[:os] count = opts[:count].to_i os = opts[:os] raise ':count must be an int' unless count.kind_of?(Integer) raise ':os must be a string' unless os.kind_of?(String) running_on_sauce = ENV['SAUCE_USERNAME'] ? true : false flaky = Flaky::Run.new is_android = os.strip.downcase == 'android' appium = Appium.new(android: is_android) unless running_on_sauce current_dir = Dir.pwd rakefile = File.expand_path(File.join(current_dir, 'Rakefile')) raise "Rakefile doesn't exist in #{current_dir}" unless File.exists? rakefile flaky_txt = File.expand_path(File.join(current_dir, 'flaky.txt')) parsed = TOML.load File.read flaky_txt puts "flaky.txt: #{parsed}" android_dir = parsed['android'] ios_dir = parsed['ios'] glob = parsed.fetch 'glob', '**/*.rb' active_dir = is_android ? android_dir : ios_dir final_path = File.expand_path File.join current_dir, active_dir, glob puts "Globbing: #{final_path}" Dir.glob(final_path) do |test_file| raise "#{test_file} does not exist." unless File.exist?(test_file) test_file = File.expand_path test_file test_name = test_file.sub(File.expand_path(File.join(current_dir, active_dir)), '') # remove leading / test_name.sub!(test_name.match(/^\//).to_s, '') test_name = File.join(File.dirname(test_name), File.basename(test_name, '.*')) count.times do File.open('/tmp/flaky/current.txt', 'a') { |f| f.puts "Running: #{test_name} on #{os}" } appium.start unless running_on_sauce run_cmd = "cd #{current_dir}; rake #{os.downcase}['#{test_file}',#{Flaky.no_video}]" passed = flaky.execute run_cmd: run_cmd, test_name: test_name, appium: appium, sauce: running_on_sauce break if passed # move onto the next test after one successful run end end appium.stop unless running_on_sauce flaky.report end
run_from_file(opts={})
click to toggle source
# File lib/flaky/run/from_file.rb, line 3 def self.run_from_file opts={} raise 'Must pass :count, :os, and :file' unless opts && opts[:count] && opts[:os] && opts[:file] count = opts[:count].to_i os = opts[:os] file = opts[:file] raise ':count must be an int' unless count.kind_of?(Integer) raise ':os must be a string' unless os.kind_of?(String) raise ':file must be a string' unless file.kind_of?(String) raise "#{file} doesn't exist" unless File.exists? file tests = File.readlines(file).map { |line| File.basename(line.chomp, '.*') } resolved_paths = [] # Convert file names into full paths current_dir = Dir.pwd Dir.glob(File.join current_dir, 'appium', os, 'specs', '**/*.rb') do |test_file| if tests.include? File.basename(test_file, '.*') resolved_paths << File.expand_path(test_file) end end if tests.length != resolved_paths.length missing_tests = [] tests.each do |test| missing_tests << test unless File.exists? test end raise "Missing tests #{missing_tests}" end raise "Rakefile doesn't exist in #{current_dir}" unless File.exists?(File.join(current_dir, 'Rakefile')) running_on_sauce = ENV['SAUCE_USERNAME'] ? true : false flaky = Flaky::Run.new is_android = os.strip.downcase == 'android' appium = Appium.new(android: is_android) unless running_on_sauce resolved_paths.each do |test_file| file = test_file name = File.basename file, '.*' raise "#{test_file} does not exist." if file.empty? test_name = file.sub(current_dir + '/appium/', '') test_name = File.join(File.dirname(test_name), File.basename(test_name, '.*')) count.times do appium.start unless running_on_sauce run_cmd = "cd #{current_dir}; rake #{os.downcase}['#{name}',#{Flaky.no_video}]" passed = flaky.execute run_cmd: run_cmd, test_name: test_name, appium: appium, sauce: running_on_sauce break if passed # move onto the next test after one successful run end end appium.stop unless running_on_sauce flaky.report end
run_one_test(opts={})
click to toggle source
# File lib/flaky/run/one_test.rb, line 3 def self.run_one_test opts={} raise 'Must pass :count and :name' unless opts && opts[:count] && opts[:os] && opts[:name] count = opts[:count].to_i os = opts[:os] name = opts[:name] raise ':count must be an int' unless count.kind_of?(Integer) raise ':os must be a string' unless os.kind_of?(String) raise ':name must be a string' unless name.kind_of?(String) # ensure file name does not contain an extension # don't expand the path because it's joined and expanded in final_path. name = File.join(File.dirname(name), File.basename(name, '.*')) running_on_sauce = ENV['SAUCE_USERNAME'] ? true : false flaky = Flaky::Run.new is_android = os.strip.downcase == 'android' appium = Appium.new(android: is_android) unless running_on_sauce current_dir = Dir.pwd raise "Rakefile doesn't exist in #{current_dir}" unless File.exists?(File.join(current_dir, 'Rakefile')) flaky_txt = File.expand_path(File.join(current_dir, 'flaky.txt')) parsed = TOML.load File.read flaky_txt puts "flaky.txt: #{parsed}" android_dir = parsed['android'] ios_dir = parsed['ios'] active_dir = is_android ? android_dir : ios_dir final_path = File.expand_path File.join current_dir, active_dir, name + '.rb' test_file = '' Dir.glob(final_path) do |file| test_file = file end raise "#{test_file} does not exist." unless File.exists?(test_file) test_name = test_file.sub(File.expand_path(File.join(current_dir, active_dir)), '') # remove leading / test_name.sub!(test_name.match(/^\//).to_s, '') test_name = File.join(File.dirname(test_name), File.basename(test_name, '.*')) count.times do appium.start unless running_on_sauce run_cmd = "cd #{current_dir}; rake #{os.downcase}['#{test_file}',#{Flaky.no_video}]" flaky.execute run_cmd: run_cmd, test_name: test_name, appium: appium, sauce: running_on_sauce end appium.stop unless running_on_sauce flaky.report end
screen_recording_binary()
click to toggle source
# File lib/screen_recording.rb, line 16 def screen_recording_binary @screen_recording_binary ||= File.expand_path('../screen-recording', __FILE__) end
screen_recording_start(opts={})
click to toggle source
# File lib/screen_recording.rb, line 20 def screen_recording_start opts={} return if Flaky.no_video os = opts[:os] path = opts[:path] raise ':os is required' unless os raise ':path is required' unless path raise 'Invalid os. Must be ios or android' unless %w[ios android].include? os raise 'Invalid path. Must end with .mov' unless File.extname(path) == '.mov' raise 'Invalid path. Must not be a dir' if File.exists?(path) && File.directory?(path) # ensure we have exactly one screen-recording process # wait for killall to complete Process::waitpid(spawn('killall', '-9', 'screen-recording', :in => '/dev/null', :out => '/dev/null', :err => '/dev/null')) File.delete(path) if File.exists? path pid = spawn(screen_recording_binary, os, path, :in => '/dev/null', :out => '/dev/null', :err => '/dev/null') pid end
screen_recording_stop(pid)
click to toggle source
# File lib/screen_recording.rb, line 43 def screen_recording_stop pid Process.kill(:SIGINT, pid) # Must wait 5 seconds for the video to end. # If we don't wait, the movie will be corrupt. # See: https://github.com/bootstraponline/screen_recording/blob/master/screen-recording/main.m#L137 sleep 5 end
trace_specs(spec_opts)
click to toggle source
Trace file source to :io (default $stdout)
spec_opts = {}
@param :trace [Array<String>] the files to trace @param :io [IO] io to print to
# File lib/trace.rb, line 10 def self.trace_specs spec_opts targets = [] files = {} last_file = '' last_line = -1 files_to_trace = spec_opts.fetch(:trace, []); io = spec_opts.fetch(:io, $stdout) color = spec_opts.fetch(:color, "\e[32m") # ANSI.green default # target only existing readable files files_to_trace.each do |f| if File.exists?(f) && File.readable?(f) targets.push File.expand_path f targets.push File.basename f # sometimes the file is relative end end return if targets.empty? set_trace_func(lambda do |event, file, line, id, binding, classname| return unless targets.include?(file) # never repeat a line return if file == last_file && line == last_line file_sym = file.intern files[file_sym] = IO.readlines(file) if files[file_sym].nil? lines = files[file_sym] # arrays are 0 indexed and line numbers start at one. io.print color if color # ANSI code io.puts lines[line - 1] io.print "\e[0m" if color # ANSI.clear last_file = file last_line = line end) end
two_pass(opts={})
click to toggle source
# File lib/flaky/run/two_pass.rb, line 3 def self.two_pass opts={} raise 'Must pass :count and :os' unless opts && opts[:count] && opts[:os] count = opts[:count].to_i os = opts[:os] raise ':count must be an int' unless count.kind_of?(Integer) raise ':os must be a string' unless os.kind_of?(String) count1 = 1 count2 = count running_on_sauce = ENV['SAUCE_USERNAME'] ? true : false FileUtils.rm_rf '/tmp/flaky' result_dir_postfix = '1' # /tmp/flaky/1 flaky = Flaky::Run.new(result_dir_postfix) is_android = os.strip.downcase == 'android' appium = Appium.new(android: is_android) unless running_on_sauce current_dir = Dir.pwd raise "Rakefile doesn't exist in #{current_dir}" unless File.exists?(File.join(current_dir, 'Rakefile')) # run all tests once Dir.glob(File.join current_dir, 'appium', os, 'specs', '**/*.rb') do |test_file| file = test_file name = File.basename file, '.*' raise "#{test_file} does not exist." if file.empty? test_name = file.sub(current_dir + '/appium/', '') test_name = File.join(File.dirname(test_name), File.basename(test_name, '.*')) count1.times do File.open('/tmp/flaky/current.txt', 'a') { |f| f.puts "Running: #{test_name} on #{os}" } appium.start unless running_on_sauce run_cmd = "cd #{current_dir}; rake #{os.downcase}['#{name}',#{Flaky.no_video}]" passed = flaky.execute(run_cmd: run_cmd, test_name: test_name, appium: appium, sauce: running_on_sauce) break if passed # move onto the next test after one successful run end end appium.stop unless running_on_sauce flaky.report # --- # now run only the failures count2 times fails = File.read(File.join('/tmp/flaky/', result_dir_postfix, 'fail.txt')) result_dir_postfix = '2' # /tmp/flaky/1 flaky = Flaky::Run.new(result_dir_postfix) appium = Appium.new(android: is_android) unless running_on_sauce fails.split("\n").each do |test_file| file = test_file name = File.basename file, '.*' raise "#{test_file} does not exist." if file.empty? test_name = file.sub(current_dir + '/appium/', '') test_name = File.join(File.dirname(test_name), File.basename(test_name, '.*')) count2.times do File.open('/tmp/flaky/current.txt', 'a') { |f| f.puts "Running: #{test_name} on #{os}" } appium.start unless running_on_sauce run_cmd = "cd #{current_dir}; rake #{os.downcase}['#{name}',#{Flaky.no_video}]" passed = flaky.execute run_cmd: run_cmd, test_name: test_name, appium: appium, sauce: running_on_sauce break if passed # move onto the next test after one successful run end end appium.stop unless running_on_sauce flaky.report end