uiauto 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ed1dc6ce64fc2949895916755c61d112f34cf5c0
4
+ data.tar.gz: 020fca7e5018461aa99f95f24447ffefb6db9dfe
5
+ SHA512:
6
+ metadata.gz: 805e4f7309178911232396a1ff6c01c318a3754b1adfaac1886828b203161be761406295d5d932062d20dce61fc7946cbe615a7193a36cf168a844e5bc27cd3d
7
+ data.tar.gz: 013447062aa6df1bffc1502a15ef42bbf42dcddf0f5e76e2d42fa9c09df0c7774c0c5379f05ed3b4dc67a45db2d71926866dee9a8538edee4bdd437d23178147
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in uiauto.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Mike Enriquez
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,125 @@
1
+ # UIAuto
2
+
3
+ UIAuto is a command line tool for running UI Automation scripts. It improves Apple's `instruments` command by assuming reasonable defaults specific to UI Automation.
4
+
5
+ UIAuto also facilitates the setup of simulator data for running scripts in a repeatable and known state.
6
+
7
+ Note: UIAuto only works with the simulator for now.
8
+
9
+ ## Prerequisites
10
+
11
+ * Xcode command line tools
12
+
13
+ ## Installation
14
+
15
+ $ gem install uiauto
16
+
17
+ ## Usage
18
+
19
+ First, you need to build your app to run on the simulator. By default, `uiauto` will look for the most recently built app bundle in derived data based on your current working directory. UIAuto also provides commands and can read speical comment headers to setup simulator data. More details below.
20
+
21
+ ### Build your project
22
+
23
+ UIAuto does not build your app. You can use Xcode or `xcodebuild`.
24
+
25
+ #### With Xcode
26
+
27
+ The easiest way to build your app for UIAuto is to use Xcode. Open your app in Xcode, select the simulator, then build your project (command+b). This builds your app and places the resulting bundle in derived data.
28
+
29
+ #### With xcodebuild
30
+
31
+ You can build from the command line using `xcodebuild`. The following examples show how to build your iOS 6.1 app for the simulator.
32
+
33
+ # Example using xcodebuild to build a workspace
34
+ $ xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -sdk iphonesimulator6.1
35
+
36
+ # Example using xcodebuild to build a project
37
+ $ xcodebuild -project MyApp.xcodeproj -sdk iphonesimulator6.1
38
+
39
+ By building with the commands above, the resulting bundle is placed in derived data.
40
+
41
+ ### Run UI Automation scripts
42
+
43
+ The command to run automation scripts is simplified if the built app is in derived data and the defaults are used. For special use cases, these defaults may be overridden.
44
+
45
+ #### Default options
46
+
47
+ In the same directory as your project's .xcworkspace or .xcodeproj run the following.
48
+
49
+ $ uiauto exec path_to_your_script.js
50
+
51
+ This will run `path_to_your_script.js` using the app bundle located in derivated data that you just built. The results and trace file are placed in `./uiauto/results` and `./uiauto/results/trace`.
52
+
53
+ #### Advanced options
54
+
55
+ Running `uiauto help exec` prints the following message.
56
+
57
+ Usage:
58
+ uiauto exec [FILE_OR_DIRECTORY]
59
+
60
+ Options:
61
+ [--results=RESULTS]
62
+
63
+ [--trace=TRACE]
64
+
65
+ [--app=APP]
66
+
67
+ If you build your app outside of derived data, then you can specify the `--app` flag to tell uiauto where to find the `*.app`. You can also override the default locations for the trace file and results. For example, if your build your app in a build directory you can run the following
68
+
69
+ uiauto exec uiauto/scripts/script_to_run.js --app=build/MyApp.app
70
+
71
+ ### Simulator data
72
+
73
+ UIAuto's `simulator` subcommand allows you to setup the simulator's applications, settings, and data. This is done by taking a "snapshot" of the simulator's current data by saving the `~/Library/Application Support/iPhone Simulator/(SDK VERSION)/` directory somewhere, then loading it back in when needed.
74
+
75
+ This is useful for getting the simulator into a known state before running automation scripts.
76
+
77
+ #### uiauto simulator command
78
+
79
+ Running `uiauto simulator` prints the following message
80
+
81
+ Commands:
82
+ uiauto simulator close # Closes the simulator
83
+ uiauto simulator help [COMMAND] # Describe subcommands or one specific subcommand
84
+ uiauto simulator load DATA # Loads previously saved simulator data
85
+ uiauto simulator open # Opens the simulator
86
+ uiauto simulator reset # Deletes all applications and settings
87
+ uiauto simulator save DATA # Saves simulator data
88
+
89
+ #### Script comment headers
90
+
91
+ By placing a special comment header at the top of your script, `uiauto exec` will automatically load in a previously saved simulator data dump before running the script.
92
+
93
+ Let's say you have a TODO list application. You want to script the delete feature, but the problem is that you need tasks to delete first. With UIAuto, you can add a comment header that loads the simulator with your app with its tasks already there. Therefore, your script can safely make this assumption every time that it is ran.
94
+
95
+ The steps below explain how to do this.
96
+
97
+ ##### 1. Manually add tasks to your app in the simulator
98
+
99
+ Get data into your app up to the point where you want your script to start. In this case, you want to add some tasks so that your script can delete them later.
100
+
101
+ ##### 2. Save the simulator's current state
102
+
103
+ $ uiauto simulator save uiauto/simulator_data/with_tasks
104
+
105
+ This command will save ALL of the data in the simulator including your application's data (and therefore, it'll save the tasks you just created). It is stored in the directory you specified.
106
+
107
+ ##### 3. Add the comment header
108
+
109
+ Add the following to the top of `uiauto/scripts/delete_tasks.js`
110
+
111
+ // setup_simulator_data "../simulator_data/with_tasks"
112
+
113
+ Inside the quotes is where you specify the location of the simulator data you want loaded in before running the script. It may be a path relative to the script.
114
+
115
+ ##### 4. Run the script
116
+
117
+ Build if needed, then run:
118
+
119
+ $ uiauto exec uiauto/scripts/delete_tasks.js
120
+
121
+ This will load in the simulator data that was saved in step 2 before running the script.
122
+
123
+ ## License
124
+
125
+ MIT License. See LICENSE.txt
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/uiauto ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'uiauto/cli'
4
+ UIAuto::CLI.start
data/lib/uiauto.rb ADDED
@@ -0,0 +1,4 @@
1
+ require "uiauto/version"
2
+
3
+ module UIAuto
4
+ end
data/lib/uiauto/cli.rb ADDED
@@ -0,0 +1,53 @@
1
+ require 'thor'
2
+ require 'uiauto/simulator'
3
+ require 'uiauto/runner'
4
+
5
+ module UIAuto
6
+ class SimulatorCLI < Thor
7
+ namespace :simulator
8
+
9
+ desc "reset", "Deletes all applications and settings"
10
+ method_option :sdk, :default => Simulator::CURRENT_IOS_SDK_VERSION
11
+ def reset
12
+ simulator = Simulator.new(options[:sdk])
13
+ simulator.reset
14
+ end
15
+
16
+ desc "load DATA", "Loads previously saved simulator data"
17
+ method_option :sdk, :default => Simulator::CURRENT_IOS_SDK_VERSION
18
+ def load(data_path)
19
+ simulator = Simulator.new(options[:sdk])
20
+ simulator.load(data_path)
21
+ end
22
+
23
+ desc "save DATA", "Saves simulator data"
24
+ method_option :sdk, :default => Simulator::CURRENT_IOS_SDK_VERSION
25
+ def save(data_path)
26
+ simulator = Simulator.new(options[:sdk])
27
+ simulator.save(data_path)
28
+ end
29
+
30
+ desc "open", "Opens the simulator"
31
+ def open
32
+ Simulator.open
33
+ end
34
+
35
+ desc "close", "Closes the simulator"
36
+ def close
37
+ Simulator.close
38
+ end
39
+ end
40
+
41
+ class CLI < Thor
42
+ desc "exec FILE_OR_DIRECTORY", "Runs the given script or directory of scripts through UI Automation"
43
+ method_option :results, :default => File.expand_path("./uiauto/results")
44
+ method_option :trace, :default => File.expand_path("./uiauto/results/trace")
45
+ method_option :app
46
+ def exec(file_or_dir = "./uiauto/scripts/")
47
+ Runner.run(file_or_dir, options)
48
+ end
49
+
50
+ desc "simulator SUBCOMMAND ...ARGS", "manage simulator data"
51
+ subcommand "simulator", SimulatorCLI
52
+ end
53
+ end
@@ -0,0 +1,91 @@
1
+ require 'pty'
2
+ require 'fileutils'
3
+ require 'cfpropertylist'
4
+
5
+ module UIAuto
6
+ class Instruments
7
+ attr_accessor :trace, :app, :results, :script
8
+
9
+ def initialize(script, opts = {})
10
+ @script = script
11
+ @trace = opts[:trace]
12
+ @results = opts[:results]
13
+ @app = opts[:app] || default_application
14
+
15
+ FileUtils.mkdir_p(@results) unless File.exists?(@results)
16
+ end
17
+
18
+ def command
19
+ command = ["xcrun instruments"]
20
+ command << "-D #{@trace}"
21
+ command << "-t #{automation_template_location}"
22
+ command << @app
23
+ command << "-e UIASCRIPT #{@script}"
24
+ command << "-e UIARESULTSPATH #{@results}"
25
+
26
+ command.join(" ")
27
+ end
28
+
29
+ def execute
30
+ exit_status = 0
31
+ read, write = PTY.open
32
+ pid = spawn(command, :in => STDIN, :out => write, :err => write)
33
+ write.close
34
+
35
+ begin
36
+ loop do
37
+ buffer = read.readpartial(8192)
38
+ lines = buffer.split("\n")
39
+ lines.each do |line|
40
+ puts line
41
+ exit_status = 1 if line =~ /Fail:/ && exit_status != 2
42
+ exit_status = 2 if line =~ /Instruments Usage Error|Instruments Trace Error|^\d+-\d+-\d+ \d+:\d+:\d+ [-+]\d+ (Error:|None: Script threw an uncaught JavaScript error)/
43
+ end
44
+ end
45
+ rescue EOFError
46
+ ensure
47
+ read.close
48
+ end
49
+
50
+ exit_status
51
+ end
52
+
53
+ protected
54
+
55
+ def default_application
56
+ current_dir = Dir.pwd
57
+ product_directories = Dir.glob(File.join(derived_data_location, "*"))
58
+
59
+ matching_directories = product_directories.select do |product_dir|
60
+ info_plist_file = File.join(product_dir, "info.plist")
61
+ if File.exists?(info_plist_file)
62
+ info_plist = CFPropertyList::List.new(:file => info_plist_file)
63
+ data = CFPropertyList.native_types(info_plist.value)
64
+ current_dir == File.dirname(data["WorkspacePath"])
65
+ else
66
+ false
67
+ end
68
+ end
69
+
70
+ # TODO: Add support for running on a device
71
+ sorted_matches = matching_directories.sort_by { |dir| File.mtime(dir) }
72
+ Dir.glob(File.join(sorted_matches.last, "Build/Products/*-iphonesimulator/*.app")).sort_by { |dir| File.mtime(dir) }.last
73
+ end
74
+
75
+ def automation_template_location
76
+ template = nil
77
+ `xcrun instruments -s 2>&1 | grep Automation.tracetemplate`.split("\n").each do |path|
78
+ path = path.gsub(/^\s*"|",\s*$/, "")
79
+ template = path if File.exists?(path)
80
+ break if template
81
+ end
82
+ template
83
+ end
84
+
85
+ def derived_data_location
86
+ # TODO: Parse ~/Library/Preferences/com.apple.dt.Xcode.plist to find customized location
87
+ File.expand_path("~/Library/Developer/Xcode/DerivedData/")
88
+ end
89
+
90
+ end
91
+ end
@@ -0,0 +1,58 @@
1
+ require 'uiauto/instruments'
2
+ require 'uiauto/simulator'
3
+
4
+ module UIAuto
5
+ class Runner
6
+ def self.run(file_or_dir, options = {})
7
+ exit_status = 0
8
+ if file_or_dir.nil?
9
+ exit_status = self.run_one options
10
+ elsif File.directory?(file_or_dir)
11
+ exit_status = self.run_all(file_or_dir, options)
12
+ else
13
+ exit_status = self.run_one(file_or_dir, options)
14
+ end
15
+
16
+ exit exit_status
17
+ end
18
+
19
+ private
20
+
21
+ def self.run_one(script, options)
22
+ self.process_comment_header script
23
+ instruments = Instruments.new(script, options)
24
+ exit_status = instruments.execute
25
+
26
+ exit_status
27
+ end
28
+
29
+ def self.run_all(dir, options)
30
+ exit_status = 0
31
+ scripts = Dir.glob(File.join(dir, "*.js"))
32
+ scripts.each do |script|
33
+ script_exit_status = self.run_one(script, options)
34
+ if script_exit_status > exit_status
35
+ exit_status = script_exit_status
36
+ end
37
+ end
38
+
39
+ exit_status
40
+ end
41
+
42
+ def self.process_comment_header(script)
43
+ File.open(script) do |file|
44
+ if file.readline =~ /\s*\/\/ setup_simulator_data "(.+)"/
45
+ path = $1
46
+ full_path = path
47
+ if !path.start_with?("/")
48
+ full_path = File.expand_path(File.join(File.dirname(script), path))
49
+ end
50
+
51
+ simulator = Simulator.new
52
+ simulator.load full_path
53
+ end
54
+ end
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,51 @@
1
+ require 'fileutils'
2
+
3
+ module UIAuto
4
+ class Simulator
5
+ CURRENT_IOS_SDK_VERSION = "6.1"
6
+
7
+ def initialize(sdk_version = CURRENT_IOS_SDK_VERSION)
8
+ @sdk_version = sdk_version
9
+ @simulator_environment_path = File.expand_path("~/Library/Application Support/iPhone Simulator")
10
+ end
11
+
12
+ def reset
13
+ self.class.close
14
+ FileUtils.rm_rf(simulator_data_path)
15
+ end
16
+
17
+ def load(data_path)
18
+ source_directory = Dir.glob("#{File.expand_path(data_path)}/*")
19
+ destination_directory = simulator_data_path
20
+
21
+ reset
22
+ FileUtils.mkdir_p(destination_directory)
23
+ FileUtils.cp_r(source_directory, destination_directory)
24
+ end
25
+
26
+ def save(data_path)
27
+ source_directory = Dir.glob("#{simulator_data_path}/*")
28
+ destination_directory = File.expand_path(data_path)
29
+
30
+ FileUtils.mkdir_p(destination_directory)
31
+ FileUtils.cp_r(source_directory, destination_directory)
32
+ end
33
+
34
+ def self.close
35
+ `killall "iPhone Simulator" &> /dev/null || true`
36
+ end
37
+
38
+ def self.open
39
+ xcode_path = `xcode-select -p`.strip
40
+ simulator_path = File.join(xcode_path, "/Platforms/iPhoneSimulator.platform/Developer/Applications/iPhone Simulator.app")
41
+
42
+ `open "#{simulator_path}"`
43
+ end
44
+
45
+ private
46
+
47
+ def simulator_data_path
48
+ File.join(@simulator_environment_path, @sdk_version)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,3 @@
1
+ module UIAuto
2
+ VERSION = "0.0.1"
3
+ end
data/uiauto.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'uiauto/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "uiauto"
8
+ spec.version = UIAuto::VERSION
9
+ spec.authors = ["Mike Enriquez"]
10
+ spec.email = ["mike@enriquez.me"]
11
+ spec.description = %q{UI Automation script runner.}
12
+ spec.summary = %q{UI Automation script runner. Provides a user friendly command line tool for executing automation scripts. Facilitates simulator data setup for executing scripts in repeatable and known states.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+
24
+ spec.add_dependency "CFPropertyList"
25
+ spec.add_dependency "thor"
26
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: uiauto
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Mike Enriquez
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-08-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
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: CFPropertyList
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
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: thor
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: UI Automation script runner.
70
+ email:
71
+ - mike@enriquez.me
72
+ executables:
73
+ - uiauto
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - .gitignore
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - bin/uiauto
83
+ - lib/uiauto.rb
84
+ - lib/uiauto/cli.rb
85
+ - lib/uiauto/instruments.rb
86
+ - lib/uiauto/runner.rb
87
+ - lib/uiauto/simulator.rb
88
+ - lib/uiauto/version.rb
89
+ - uiauto.gemspec
90
+ homepage: ''
91
+ licenses:
92
+ - MIT
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 2.0.3
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: UI Automation script runner. Provides a user friendly command line tool for
114
+ executing automation scripts. Facilitates simulator data setup for executing scripts
115
+ in repeatable and known states.
116
+ test_files: []