From 6c970edfc2ac3d32b93ae8fab1fa3a3c9ade9a16 Mon Sep 17 00:00:00 2001 From: kviksilver Date: Wed, 8 Apr 2015 13:00:36 -0400 Subject: [PATCH 01/11] [PODS] basic podspec file --- Illuminator.podspec | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Illuminator.podspec diff --git a/Illuminator.podspec b/Illuminator.podspec new file mode 100644 index 0000000..298e1a8 --- /dev/null +++ b/Illuminator.podspec @@ -0,0 +1,19 @@ + +Pod::Spec.new do |s| + s.name = "Illuminator" + s.version = "0.0.1" + s.summary = "ILLUMINATOR - the iOS Automator" + + s.description = <<-DESC + Illuminator enables continuous integration for iOS apps. It makes it easy (well, easier) to write and debug sophisticated app tests. Additionally, it makes the entire UIAutomation apparatus more capable of handling high-volume automated testing -- providing features that are missing from Apple's "Instruments" application. + DESC + + s.homepage = "https://github.com/paypal/illuminator" + s.license = 'Apache License, Version 2.0' + s.author = "PayPal" + s.platform = :ios + s.source = { :git => "https://github.com/kviksilver/Illuminator.git", :tag => "0.0.1" } + s.source_files = "PPAutomationBridge", "PPAutomationBridge/*.{h,m}" + s.resources = "Illuminator/*" + +end From 123510909e5a09f0a8c030ed20cb6dfed712cd6b Mon Sep 17 00:00:00 2001 From: kviksilver Date: Wed, 8 Apr 2015 13:05:42 -0400 Subject: [PATCH 02/11] [REORGANIZE] rename Illuminator to src --- Illuminator.podspec | 2 +- SampleApp/smokeTests.rb | 8 ++++---- {Illuminator => src}/AppMap.js | 0 {Illuminator => src}/Automator.js | 0 {Illuminator => src}/Base64.js | 0 {Illuminator => src}/Bridge.js | 0 {Illuminator => src}/Config.js | 0 {Illuminator => src}/Extensions.js | 0 {Illuminator => src}/Illuminator.js | 0 {Illuminator => src}/Preferences.js | 0 {Illuminator => src}/scripts/UIAutomationBridge.rb | 0 {Illuminator => src}/scripts/automationTests.rb | 0 {Illuminator => src}/scripts/choose_sim_language.sh | 0 .../scripts/classes/AutomationBuilder.rb | 0 .../scripts/classes/AutomationRunner.rb | 0 .../scripts/classes/BuildArtifacts.rb | 0 .../scripts/classes/DeviceInstaller.rb | 0 {Illuminator => src}/scripts/classes/HostUtils.rb | 0 .../scripts/classes/IlluminatorArgumentParsing.rb | 0 .../scripts/classes/IlluminatorFramework.rb | 0 .../scripts/classes/IlluminatorOptions.rb | 0 .../scripts/classes/InstrumentsRunner.rb | 0 .../scripts/classes/JavascriptRunner.rb | 0 .../scripts/classes/TestDefinitions.rb | 0 {Illuminator => src}/scripts/classes/TestSuite.rb | 0 .../scripts/classes/XcodeBuilder.rb | 0 {Illuminator => src}/scripts/classes/XcodeUtils.rb | 0 .../scripts/classes/listeners/ConsoleLogger.rb | 0 .../scripts/classes/listeners/FullOutput.rb | 0 .../classes/listeners/InstrumentsListener.rb | 0 .../listeners/IntermittentFailureDetector.rb | 0 .../scripts/classes/listeners/PrettyOutput.rb | 0 .../scripts/classes/listeners/SaltinelAgent.rb | 0 .../scripts/classes/listeners/SaltinelListener.rb | 0 .../scripts/classes/listeners/StartDetector.rb | 0 .../scripts/classes/listeners/StopDetector.rb | 0 .../scripts/classes/listeners/TestListener.rb | 0 {Illuminator => src}/scripts/diff_png.sh | 0 .../scripts/kill_all_sim_processes.sh | 0 {Illuminator => src}/scripts/plist_to_json.sh | 0 {Illuminator => src}/scripts/rerunFailedTests.rb | 0 .../scripts/resources/BuildConfiguration.xcconfig | 0 .../resources/IlluminatorGeneratedEnvironment.erb | 0 .../IlluminatorGeneratedRunnerForInstruments.erb | 0 .../scripts/set_hardware_keyboard.applescript | Bin 45 files changed, 5 insertions(+), 5 deletions(-) rename {Illuminator => src}/AppMap.js (100%) rename {Illuminator => src}/Automator.js (100%) rename {Illuminator => src}/Base64.js (100%) rename {Illuminator => src}/Bridge.js (100%) rename {Illuminator => src}/Config.js (100%) rename {Illuminator => src}/Extensions.js (100%) rename {Illuminator => src}/Illuminator.js (100%) rename {Illuminator => src}/Preferences.js (100%) rename {Illuminator => src}/scripts/UIAutomationBridge.rb (100%) rename {Illuminator => src}/scripts/automationTests.rb (100%) rename {Illuminator => src}/scripts/choose_sim_language.sh (100%) rename {Illuminator => src}/scripts/classes/AutomationBuilder.rb (100%) rename {Illuminator => src}/scripts/classes/AutomationRunner.rb (100%) rename {Illuminator => src}/scripts/classes/BuildArtifacts.rb (100%) rename {Illuminator => src}/scripts/classes/DeviceInstaller.rb (100%) rename {Illuminator => src}/scripts/classes/HostUtils.rb (100%) rename {Illuminator => src}/scripts/classes/IlluminatorArgumentParsing.rb (100%) rename {Illuminator => src}/scripts/classes/IlluminatorFramework.rb (100%) rename {Illuminator => src}/scripts/classes/IlluminatorOptions.rb (100%) rename {Illuminator => src}/scripts/classes/InstrumentsRunner.rb (100%) rename {Illuminator => src}/scripts/classes/JavascriptRunner.rb (100%) rename {Illuminator => src}/scripts/classes/TestDefinitions.rb (100%) rename {Illuminator => src}/scripts/classes/TestSuite.rb (100%) rename {Illuminator => src}/scripts/classes/XcodeBuilder.rb (100%) rename {Illuminator => src}/scripts/classes/XcodeUtils.rb (100%) rename {Illuminator => src}/scripts/classes/listeners/ConsoleLogger.rb (100%) rename {Illuminator => src}/scripts/classes/listeners/FullOutput.rb (100%) rename {Illuminator => src}/scripts/classes/listeners/InstrumentsListener.rb (100%) rename {Illuminator => src}/scripts/classes/listeners/IntermittentFailureDetector.rb (100%) rename {Illuminator => src}/scripts/classes/listeners/PrettyOutput.rb (100%) rename {Illuminator => src}/scripts/classes/listeners/SaltinelAgent.rb (100%) rename {Illuminator => src}/scripts/classes/listeners/SaltinelListener.rb (100%) rename {Illuminator => src}/scripts/classes/listeners/StartDetector.rb (100%) rename {Illuminator => src}/scripts/classes/listeners/StopDetector.rb (100%) rename {Illuminator => src}/scripts/classes/listeners/TestListener.rb (100%) rename {Illuminator => src}/scripts/diff_png.sh (100%) rename {Illuminator => src}/scripts/kill_all_sim_processes.sh (100%) rename {Illuminator => src}/scripts/plist_to_json.sh (100%) rename {Illuminator => src}/scripts/rerunFailedTests.rb (100%) rename {Illuminator => src}/scripts/resources/BuildConfiguration.xcconfig (100%) rename {Illuminator => src}/scripts/resources/IlluminatorGeneratedEnvironment.erb (100%) rename {Illuminator => src}/scripts/resources/IlluminatorGeneratedRunnerForInstruments.erb (100%) rename {Illuminator => src}/scripts/set_hardware_keyboard.applescript (100%) diff --git a/Illuminator.podspec b/Illuminator.podspec index 298e1a8..eb8c6ab 100644 --- a/Illuminator.podspec +++ b/Illuminator.podspec @@ -14,6 +14,6 @@ Pod::Spec.new do |s| s.platform = :ios s.source = { :git => "https://github.com/kviksilver/Illuminator.git", :tag => "0.0.1" } s.source_files = "PPAutomationBridge", "PPAutomationBridge/*.{h,m}" - s.resources = "Illuminator/*" + s.resources = "src/*" end diff --git a/SampleApp/smokeTests.rb b/SampleApp/smokeTests.rb index ea5c200..787c783 100644 --- a/SampleApp/smokeTests.rb +++ b/SampleApp/smokeTests.rb @@ -1,7 +1,7 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), '../Illuminator/scripts/classes/IlluminatorFramework.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), '../Illuminator/scripts/classes/IlluminatorOptions.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), '../Illuminator/scripts/classes/XcodeUtils.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), '../Illuminator/scripts/classes/HostUtils.rb') +require File.join(File.expand_path(File.dirname(__FILE__)), '../src/scripts/classes/IlluminatorFramework.rb') +require File.join(File.expand_path(File.dirname(__FILE__)), '../src/scripts/classes/IlluminatorOptions.rb') +require File.join(File.expand_path(File.dirname(__FILE__)), '../src/scripts/classes/XcodeUtils.rb') +require File.join(File.expand_path(File.dirname(__FILE__)), '../src/scripts/classes/HostUtils.rb') # Change directory to sample app and use that for the workspace Dir.chdir File.join(File.expand_path(File.dirname(__FILE__)), '/AutomatorSampleApp') diff --git a/Illuminator/AppMap.js b/src/AppMap.js similarity index 100% rename from Illuminator/AppMap.js rename to src/AppMap.js diff --git a/Illuminator/Automator.js b/src/Automator.js similarity index 100% rename from Illuminator/Automator.js rename to src/Automator.js diff --git a/Illuminator/Base64.js b/src/Base64.js similarity index 100% rename from Illuminator/Base64.js rename to src/Base64.js diff --git a/Illuminator/Bridge.js b/src/Bridge.js similarity index 100% rename from Illuminator/Bridge.js rename to src/Bridge.js diff --git a/Illuminator/Config.js b/src/Config.js similarity index 100% rename from Illuminator/Config.js rename to src/Config.js diff --git a/Illuminator/Extensions.js b/src/Extensions.js similarity index 100% rename from Illuminator/Extensions.js rename to src/Extensions.js diff --git a/Illuminator/Illuminator.js b/src/Illuminator.js similarity index 100% rename from Illuminator/Illuminator.js rename to src/Illuminator.js diff --git a/Illuminator/Preferences.js b/src/Preferences.js similarity index 100% rename from Illuminator/Preferences.js rename to src/Preferences.js diff --git a/Illuminator/scripts/UIAutomationBridge.rb b/src/scripts/UIAutomationBridge.rb similarity index 100% rename from Illuminator/scripts/UIAutomationBridge.rb rename to src/scripts/UIAutomationBridge.rb diff --git a/Illuminator/scripts/automationTests.rb b/src/scripts/automationTests.rb similarity index 100% rename from Illuminator/scripts/automationTests.rb rename to src/scripts/automationTests.rb diff --git a/Illuminator/scripts/choose_sim_language.sh b/src/scripts/choose_sim_language.sh similarity index 100% rename from Illuminator/scripts/choose_sim_language.sh rename to src/scripts/choose_sim_language.sh diff --git a/Illuminator/scripts/classes/AutomationBuilder.rb b/src/scripts/classes/AutomationBuilder.rb similarity index 100% rename from Illuminator/scripts/classes/AutomationBuilder.rb rename to src/scripts/classes/AutomationBuilder.rb diff --git a/Illuminator/scripts/classes/AutomationRunner.rb b/src/scripts/classes/AutomationRunner.rb similarity index 100% rename from Illuminator/scripts/classes/AutomationRunner.rb rename to src/scripts/classes/AutomationRunner.rb diff --git a/Illuminator/scripts/classes/BuildArtifacts.rb b/src/scripts/classes/BuildArtifacts.rb similarity index 100% rename from Illuminator/scripts/classes/BuildArtifacts.rb rename to src/scripts/classes/BuildArtifacts.rb diff --git a/Illuminator/scripts/classes/DeviceInstaller.rb b/src/scripts/classes/DeviceInstaller.rb similarity index 100% rename from Illuminator/scripts/classes/DeviceInstaller.rb rename to src/scripts/classes/DeviceInstaller.rb diff --git a/Illuminator/scripts/classes/HostUtils.rb b/src/scripts/classes/HostUtils.rb similarity index 100% rename from Illuminator/scripts/classes/HostUtils.rb rename to src/scripts/classes/HostUtils.rb diff --git a/Illuminator/scripts/classes/IlluminatorArgumentParsing.rb b/src/scripts/classes/IlluminatorArgumentParsing.rb similarity index 100% rename from Illuminator/scripts/classes/IlluminatorArgumentParsing.rb rename to src/scripts/classes/IlluminatorArgumentParsing.rb diff --git a/Illuminator/scripts/classes/IlluminatorFramework.rb b/src/scripts/classes/IlluminatorFramework.rb similarity index 100% rename from Illuminator/scripts/classes/IlluminatorFramework.rb rename to src/scripts/classes/IlluminatorFramework.rb diff --git a/Illuminator/scripts/classes/IlluminatorOptions.rb b/src/scripts/classes/IlluminatorOptions.rb similarity index 100% rename from Illuminator/scripts/classes/IlluminatorOptions.rb rename to src/scripts/classes/IlluminatorOptions.rb diff --git a/Illuminator/scripts/classes/InstrumentsRunner.rb b/src/scripts/classes/InstrumentsRunner.rb similarity index 100% rename from Illuminator/scripts/classes/InstrumentsRunner.rb rename to src/scripts/classes/InstrumentsRunner.rb diff --git a/Illuminator/scripts/classes/JavascriptRunner.rb b/src/scripts/classes/JavascriptRunner.rb similarity index 100% rename from Illuminator/scripts/classes/JavascriptRunner.rb rename to src/scripts/classes/JavascriptRunner.rb diff --git a/Illuminator/scripts/classes/TestDefinitions.rb b/src/scripts/classes/TestDefinitions.rb similarity index 100% rename from Illuminator/scripts/classes/TestDefinitions.rb rename to src/scripts/classes/TestDefinitions.rb diff --git a/Illuminator/scripts/classes/TestSuite.rb b/src/scripts/classes/TestSuite.rb similarity index 100% rename from Illuminator/scripts/classes/TestSuite.rb rename to src/scripts/classes/TestSuite.rb diff --git a/Illuminator/scripts/classes/XcodeBuilder.rb b/src/scripts/classes/XcodeBuilder.rb similarity index 100% rename from Illuminator/scripts/classes/XcodeBuilder.rb rename to src/scripts/classes/XcodeBuilder.rb diff --git a/Illuminator/scripts/classes/XcodeUtils.rb b/src/scripts/classes/XcodeUtils.rb similarity index 100% rename from Illuminator/scripts/classes/XcodeUtils.rb rename to src/scripts/classes/XcodeUtils.rb diff --git a/Illuminator/scripts/classes/listeners/ConsoleLogger.rb b/src/scripts/classes/listeners/ConsoleLogger.rb similarity index 100% rename from Illuminator/scripts/classes/listeners/ConsoleLogger.rb rename to src/scripts/classes/listeners/ConsoleLogger.rb diff --git a/Illuminator/scripts/classes/listeners/FullOutput.rb b/src/scripts/classes/listeners/FullOutput.rb similarity index 100% rename from Illuminator/scripts/classes/listeners/FullOutput.rb rename to src/scripts/classes/listeners/FullOutput.rb diff --git a/Illuminator/scripts/classes/listeners/InstrumentsListener.rb b/src/scripts/classes/listeners/InstrumentsListener.rb similarity index 100% rename from Illuminator/scripts/classes/listeners/InstrumentsListener.rb rename to src/scripts/classes/listeners/InstrumentsListener.rb diff --git a/Illuminator/scripts/classes/listeners/IntermittentFailureDetector.rb b/src/scripts/classes/listeners/IntermittentFailureDetector.rb similarity index 100% rename from Illuminator/scripts/classes/listeners/IntermittentFailureDetector.rb rename to src/scripts/classes/listeners/IntermittentFailureDetector.rb diff --git a/Illuminator/scripts/classes/listeners/PrettyOutput.rb b/src/scripts/classes/listeners/PrettyOutput.rb similarity index 100% rename from Illuminator/scripts/classes/listeners/PrettyOutput.rb rename to src/scripts/classes/listeners/PrettyOutput.rb diff --git a/Illuminator/scripts/classes/listeners/SaltinelAgent.rb b/src/scripts/classes/listeners/SaltinelAgent.rb similarity index 100% rename from Illuminator/scripts/classes/listeners/SaltinelAgent.rb rename to src/scripts/classes/listeners/SaltinelAgent.rb diff --git a/Illuminator/scripts/classes/listeners/SaltinelListener.rb b/src/scripts/classes/listeners/SaltinelListener.rb similarity index 100% rename from Illuminator/scripts/classes/listeners/SaltinelListener.rb rename to src/scripts/classes/listeners/SaltinelListener.rb diff --git a/Illuminator/scripts/classes/listeners/StartDetector.rb b/src/scripts/classes/listeners/StartDetector.rb similarity index 100% rename from Illuminator/scripts/classes/listeners/StartDetector.rb rename to src/scripts/classes/listeners/StartDetector.rb diff --git a/Illuminator/scripts/classes/listeners/StopDetector.rb b/src/scripts/classes/listeners/StopDetector.rb similarity index 100% rename from Illuminator/scripts/classes/listeners/StopDetector.rb rename to src/scripts/classes/listeners/StopDetector.rb diff --git a/Illuminator/scripts/classes/listeners/TestListener.rb b/src/scripts/classes/listeners/TestListener.rb similarity index 100% rename from Illuminator/scripts/classes/listeners/TestListener.rb rename to src/scripts/classes/listeners/TestListener.rb diff --git a/Illuminator/scripts/diff_png.sh b/src/scripts/diff_png.sh similarity index 100% rename from Illuminator/scripts/diff_png.sh rename to src/scripts/diff_png.sh diff --git a/Illuminator/scripts/kill_all_sim_processes.sh b/src/scripts/kill_all_sim_processes.sh similarity index 100% rename from Illuminator/scripts/kill_all_sim_processes.sh rename to src/scripts/kill_all_sim_processes.sh diff --git a/Illuminator/scripts/plist_to_json.sh b/src/scripts/plist_to_json.sh similarity index 100% rename from Illuminator/scripts/plist_to_json.sh rename to src/scripts/plist_to_json.sh diff --git a/Illuminator/scripts/rerunFailedTests.rb b/src/scripts/rerunFailedTests.rb similarity index 100% rename from Illuminator/scripts/rerunFailedTests.rb rename to src/scripts/rerunFailedTests.rb diff --git a/Illuminator/scripts/resources/BuildConfiguration.xcconfig b/src/scripts/resources/BuildConfiguration.xcconfig similarity index 100% rename from Illuminator/scripts/resources/BuildConfiguration.xcconfig rename to src/scripts/resources/BuildConfiguration.xcconfig diff --git a/Illuminator/scripts/resources/IlluminatorGeneratedEnvironment.erb b/src/scripts/resources/IlluminatorGeneratedEnvironment.erb similarity index 100% rename from Illuminator/scripts/resources/IlluminatorGeneratedEnvironment.erb rename to src/scripts/resources/IlluminatorGeneratedEnvironment.erb diff --git a/Illuminator/scripts/resources/IlluminatorGeneratedRunnerForInstruments.erb b/src/scripts/resources/IlluminatorGeneratedRunnerForInstruments.erb similarity index 100% rename from Illuminator/scripts/resources/IlluminatorGeneratedRunnerForInstruments.erb rename to src/scripts/resources/IlluminatorGeneratedRunnerForInstruments.erb diff --git a/Illuminator/scripts/set_hardware_keyboard.applescript b/src/scripts/set_hardware_keyboard.applescript similarity index 100% rename from Illuminator/scripts/set_hardware_keyboard.applescript rename to src/scripts/set_hardware_keyboard.applescript From 081620fac42d1d4e515e00895b7c04bee24752fe Mon Sep 17 00:00:00 2001 From: kviksilver Date: Wed, 8 Apr 2015 13:09:20 -0400 Subject: [PATCH 03/11] [PODS] create local pod file --- SampleApp/AutomatorSampleApp/Podfile | 1 + 1 file changed, 1 insertion(+) create mode 100644 SampleApp/AutomatorSampleApp/Podfile diff --git a/SampleApp/AutomatorSampleApp/Podfile b/SampleApp/AutomatorSampleApp/Podfile new file mode 100644 index 0000000..4fc7e96 --- /dev/null +++ b/SampleApp/AutomatorSampleApp/Podfile @@ -0,0 +1 @@ +pod 'Illuminator', :local => "../../" From d407cd9f7fafa90a9c6513cb21228e09d2b6958b Mon Sep 17 00:00:00 2001 From: kviksilver Date: Wed, 8 Apr 2015 13:22:52 -0400 Subject: [PATCH 04/11] move automation sample to sample folder --- Illuminator.podspec | 2 +- {src/scripts => SampleApp}/automationTests.rb | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) rename {src/scripts => SampleApp}/automationTests.rb (64%) diff --git a/Illuminator.podspec b/Illuminator.podspec index eb8c6ab..b749844 100644 --- a/Illuminator.podspec +++ b/Illuminator.podspec @@ -13,7 +13,7 @@ Pod::Spec.new do |s| s.author = "PayPal" s.platform = :ios s.source = { :git => "https://github.com/kviksilver/Illuminator.git", :tag => "0.0.1" } - s.source_files = "PPAutomationBridge", "PPAutomationBridge/*.{h,m}" + s.source_files = "PPAutomationBridge/*.{h,m}" s.resources = "src/*" end diff --git a/src/scripts/automationTests.rb b/SampleApp/automationTests.rb similarity index 64% rename from src/scripts/automationTests.rb rename to SampleApp/automationTests.rb index 0150862..1c26dac 100644 --- a/src/scripts/automationTests.rb +++ b/SampleApp/automationTests.rb @@ -1,8 +1,8 @@ require 'pathname' -require File.join(File.expand_path(File.dirname(__FILE__)), '/classes/IlluminatorFramework.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), '/classes/IlluminatorArgumentParsing.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'classes/HostUtils.rb') +require File.join(File.expand_path(File.dirname(__FILE__)), '../src/scripts/classes/IlluminatorFramework.rb') +require File.join(File.expand_path(File.dirname(__FILE__)), '../src/scripts/classes/IlluminatorArgumentParsing.rb') +require File.join(File.expand_path(File.dirname(__FILE__)), '../src/scripts/classes/HostUtils.rb') options = {} @@ -19,7 +19,7 @@ optionStruct.xcode.appName = 'AutomatorSampleApp' optionStruct.xcode.scheme = 'AutomatorSampleApp' optionStruct.javascript.implementation = 'iPhone' -optionStruct.javascript.testPath = HostUtils.realpath('SampleApp/SampleTests/tests/AllTests.js') # must be full path +optionStruct.javascript.testPath = HostUtils.realpath('../SampleTests/tests/AllTests.js') # must be full path Dir.chdir 'SampleApp/AutomatorSampleApp' workspace = Dir.pwd From 702c51d18b7c90ea4863493477c9e2eca5ac643d Mon Sep 17 00:00:00 2001 From: kviksilver Date: Wed, 8 Apr 2015 13:30:45 -0400 Subject: [PATCH 05/11] [PODS] update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 1b2f5b5..9e50ece 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ vendor !default.xcworkspace xcuserdata SampleApp/AutomatorSampleApp/build +SampleApp/AutomatorSampleApp/Pods From 38d4a07ad12fc0f06d1a8881a5b1475870e3e61f Mon Sep 17 00:00:00 2001 From: kviksilver Date: Wed, 8 Apr 2015 13:37:19 -0400 Subject: [PATCH 06/11] [POD] add ios version and correct tag to podspec file --- Illuminator.podspec | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Illuminator.podspec b/Illuminator.podspec index b749844..60bfcb4 100644 --- a/Illuminator.podspec +++ b/Illuminator.podspec @@ -12,8 +12,10 @@ Pod::Spec.new do |s| s.license = 'Apache License, Version 2.0' s.author = "PayPal" s.platform = :ios - s.source = { :git => "https://github.com/kviksilver/Illuminator.git", :tag => "0.0.1" } + s.ios.deployment_target = "7.0" + s.source = { :git => "https://github.com/kviksilver/Illuminator.git", :tag => s.version.to_s } s.source_files = "PPAutomationBridge/*.{h,m}" + s.public_header_files = "PPAutomationBridge/*.h" s.resources = "src/*" - + #s.prepare_command = 'bundle install' #maybe do this? end From f7220257fc775553c79c6daf1a6bd161f8d8733b Mon Sep 17 00:00:00 2001 From: kviksilver Date: Wed, 8 Apr 2015 14:24:46 -0400 Subject: [PATCH 07/11] [PODS] added Podfile lock --- Illuminator.podspec | 3 - PPAutomationBridge/PPAutomationBridge.h | 3 - PPAutomationBridge/PPAutomationBridge.m | 3 - .../project.pbxproj | 68 +++++++++++++++---- .../AutomatorSampleApp/PPHAAppDelegate.m | 2 +- .../AutomatorSampleApp/PPHABridgeDelegate.h | 2 +- SampleApp/AutomatorSampleApp/Podfile.lock | 14 ++++ 7 files changed, 69 insertions(+), 26 deletions(-) create mode 100644 SampleApp/AutomatorSampleApp/Podfile.lock diff --git a/Illuminator.podspec b/Illuminator.podspec index 60bfcb4..e98a0de 100644 --- a/Illuminator.podspec +++ b/Illuminator.podspec @@ -1,13 +1,10 @@ - Pod::Spec.new do |s| s.name = "Illuminator" s.version = "0.0.1" s.summary = "ILLUMINATOR - the iOS Automator" - s.description = <<-DESC Illuminator enables continuous integration for iOS apps. It makes it easy (well, easier) to write and debug sophisticated app tests. Additionally, it makes the entire UIAutomation apparatus more capable of handling high-volume automated testing -- providing features that are missing from Apple's "Instruments" application. DESC - s.homepage = "https://github.com/paypal/illuminator" s.license = 'Apache License, Version 2.0' s.author = "PayPal" diff --git a/PPAutomationBridge/PPAutomationBridge.h b/PPAutomationBridge/PPAutomationBridge.h index eca29ad..e7958fd 100644 --- a/PPAutomationBridge/PPAutomationBridge.h +++ b/PPAutomationBridge/PPAutomationBridge.h @@ -10,8 +10,6 @@ #import -#ifdef UIAUTOMATION_BUILD - @class PPAutomationBridge; @class PPAutomationBridgeAction; @@ -147,4 +145,3 @@ @end -#endif diff --git a/PPAutomationBridge/PPAutomationBridge.m b/PPAutomationBridge/PPAutomationBridge.m index 499e00c..0021b06 100644 --- a/PPAutomationBridge/PPAutomationBridge.m +++ b/PPAutomationBridge/PPAutomationBridge.m @@ -6,8 +6,6 @@ // Copyright 2013 PayPal. All rights reserved. // -#ifdef UIAUTOMATION_BUILD - #import "PPAutomationBridge.h" #ifndef AUTOMATION_UDID @@ -427,4 +425,3 @@ - (NSDictionary *)resultFromTarget:(id)target { @end -#endif diff --git a/SampleApp/AutomatorSampleApp/AutomatorSampleApp.xcodeproj/project.pbxproj b/SampleApp/AutomatorSampleApp/AutomatorSampleApp.xcodeproj/project.pbxproj index eb1cea8..82279d3 100644 --- a/SampleApp/AutomatorSampleApp/AutomatorSampleApp.xcodeproj/project.pbxproj +++ b/SampleApp/AutomatorSampleApp/AutomatorSampleApp.xcodeproj/project.pbxproj @@ -20,12 +20,13 @@ 88945DE818F5AC4E00F02E4A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 88945DE618F5AC4E00F02E4A /* Main.storyboard */; }; 88945DEE18F5AC4E00F02E4A /* PPHAMainMenuViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 88945DED18F5AC4E00F02E4A /* PPHAMainMenuViewController.m */; }; 88945DF018F5AC4E00F02E4A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 88945DEF18F5AC4E00F02E4A /* Images.xcassets */; }; - 88945E1218F5ADC800F02E4A /* PPAutomationBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 88945E0E18F5ADC800F02E4A /* PPAutomationBridge.m */; }; 88945E1618F5AE3200F02E4A /* PPHABridgeDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 88945E1518F5AE3200F02E4A /* PPHABridgeDelegate.m */; }; 88A92B691A7BE76500D288A8 /* PPHAWaitViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 88A92B681A7BE76500D288A8 /* PPHAWaitViewController.m */; }; + DC2A4DC7D739A8C70CD8705C /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A98E8546B4575DC9C73C646A /* libPods.a */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 206AC460FBA2873F874C3043 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; 885ED8961A7A8CCB00E75280 /* PPHATableDataObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PPHATableDataObject.h; path = Misc/PPHATableDataObject.h; sourceTree = ""; }; 885ED8971A7A8CCB00E75280 /* PPHATableDataObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PPHATableDataObject.m; path = Misc/PPHATableDataObject.m; sourceTree = ""; }; 885ED8A41A7AD0C300E75280 /* PPHAInputView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PPHAInputView.h; path = Misc/PPHAInputView.h; sourceTree = ""; }; @@ -48,12 +49,12 @@ 88945DED18F5AC4E00F02E4A /* PPHAMainMenuViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = PPHAMainMenuViewController.m; path = ViewControllers/PPHAMainMenuViewController.m; sourceTree = ""; }; 88945DEF18F5AC4E00F02E4A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 88945DF618F5AC4E00F02E4A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; - 88945E0D18F5ADC800F02E4A /* PPAutomationBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPAutomationBridge.h; sourceTree = ""; }; - 88945E0E18F5ADC800F02E4A /* PPAutomationBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PPAutomationBridge.m; sourceTree = ""; }; 88945E1418F5AE3200F02E4A /* PPHABridgeDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPHABridgeDelegate.h; sourceTree = ""; }; 88945E1518F5AE3200F02E4A /* PPHABridgeDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PPHABridgeDelegate.m; sourceTree = ""; }; 88A92B671A7BE76500D288A8 /* PPHAWaitViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PPHAWaitViewController.h; path = ViewControllers/PPHAWaitViewController.h; sourceTree = ""; }; 88A92B681A7BE76500D288A8 /* PPHAWaitViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PPHAWaitViewController.m; path = ViewControllers/PPHAWaitViewController.m; sourceTree = ""; }; + A98E8546B4575DC9C73C646A /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; + D502EA7F001472B79F6D8739 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -64,12 +65,22 @@ 88945DD718F5AC4E00F02E4A /* CoreGraphics.framework in Frameworks */, 88945DD918F5AC4E00F02E4A /* UIKit.framework in Frameworks */, 88945DD518F5AC4E00F02E4A /* Foundation.framework in Frameworks */, + DC2A4DC7D739A8C70CD8705C /* libPods.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 7440427F2921BC74965F888D /* Pods */ = { + isa = PBXGroup; + children = ( + D502EA7F001472B79F6D8739 /* Pods.debug.xcconfig */, + 206AC460FBA2873F874C3043 /* Pods.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; 885ED89F1A7ACF2D00E75280 /* ViewControllers */ = { isa = PBXGroup; children = ( @@ -101,6 +112,7 @@ 88945DDA18F5AC4E00F02E4A /* AutomatorSampleApp */, 88945DD318F5AC4E00F02E4A /* Frameworks */, 88945DD218F5AC4E00F02E4A /* Products */, + 7440427F2921BC74965F888D /* Pods */, ); sourceTree = ""; }; @@ -119,6 +131,7 @@ 88945DD618F5AC4E00F02E4A /* CoreGraphics.framework */, 88945DD818F5AC4E00F02E4A /* UIKit.framework */, 88945DF618F5AC4E00F02E4A /* XCTest.framework */, + A98E8546B4575DC9C73C646A /* libPods.a */, ); name = Frameworks; sourceTree = ""; @@ -128,7 +141,6 @@ children = ( 885ED8A01A7ACFE600E75280 /* Misc */, 885ED89F1A7ACF2D00E75280 /* ViewControllers */, - 88945E0C18F5ADC800F02E4A /* PPAutomationBridge */, 88945DE318F5AC4E00F02E4A /* PPHAAppDelegate.h */, 88945DE418F5AC4E00F02E4A /* PPHAAppDelegate.m */, 88945DE618F5AC4E00F02E4A /* Main.storyboard */, @@ -151,16 +163,6 @@ name = "Supporting Files"; sourceTree = ""; }; - 88945E0C18F5ADC800F02E4A /* PPAutomationBridge */ = { - isa = PBXGroup; - children = ( - 88945E0D18F5ADC800F02E4A /* PPAutomationBridge.h */, - 88945E0E18F5ADC800F02E4A /* PPAutomationBridge.m */, - ); - name = PPAutomationBridge; - path = ../../../PPAutomationBridge; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -168,9 +170,11 @@ isa = PBXNativeTarget; buildConfigurationList = 88945E0618F5AC4F00F02E4A /* Build configuration list for PBXNativeTarget "AutomatorSampleApp" */; buildPhases = ( + 84609880B0BABF3F0DB485D8 /* Check Pods Manifest.lock */, 88945DCD18F5AC4E00F02E4A /* Sources */, 88945DCE18F5AC4E00F02E4A /* Frameworks */, 88945DCF18F5AC4E00F02E4A /* Resources */, + D8E3193F2185B9CF3BBDAF03 /* Copy Pods Resources */, ); buildRules = ( ); @@ -223,6 +227,39 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 84609880B0BABF3F0DB485D8 /* Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; + D8E3193F2185B9CF3BBDAF03 /* Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 88945DCD18F5AC4E00F02E4A /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -230,7 +267,6 @@ files = ( 885ED8981A7A8CCB00E75280 /* PPHATableDataObject.m in Sources */, 88945DE118F5AC4E00F02E4A /* main.m in Sources */, - 88945E1218F5ADC800F02E4A /* PPAutomationBridge.m in Sources */, 885ED8A61A7AD0C300E75280 /* PPHAInputView.m in Sources */, 88945DEE18F5AC4E00F02E4A /* PPHAMainMenuViewController.m in Sources */, 885ED8AB1A7AD3DF00E75280 /* PPHACustomKeyboardViewController.m in Sources */, @@ -336,6 +372,7 @@ }; 88945E0718F5AC4F00F02E4A /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = D502EA7F001472B79F6D8739 /* Pods.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; @@ -351,6 +388,7 @@ }; 88945E0818F5AC4F00F02E4A /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 206AC460FBA2873F874C3043 /* Pods.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; diff --git a/SampleApp/AutomatorSampleApp/AutomatorSampleApp/PPHAAppDelegate.m b/SampleApp/AutomatorSampleApp/AutomatorSampleApp/PPHAAppDelegate.m index 667ae02..6107a08 100644 --- a/SampleApp/AutomatorSampleApp/AutomatorSampleApp/PPHAAppDelegate.m +++ b/SampleApp/AutomatorSampleApp/AutomatorSampleApp/PPHAAppDelegate.m @@ -7,7 +7,7 @@ // #import "PPHAAppDelegate.h" -#import "PPAutomationBridge.h" +#import #import "PPHABridgeDelegate.h" //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/SampleApp/AutomatorSampleApp/AutomatorSampleApp/PPHABridgeDelegate.h b/SampleApp/AutomatorSampleApp/AutomatorSampleApp/PPHABridgeDelegate.h index fa9da91..894287f 100644 --- a/SampleApp/AutomatorSampleApp/AutomatorSampleApp/PPHABridgeDelegate.h +++ b/SampleApp/AutomatorSampleApp/AutomatorSampleApp/PPHABridgeDelegate.h @@ -12,7 +12,7 @@ #ifdef UIAUTOMATION_BUILD -#import "PPAutomationBridge.h" +#import //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/SampleApp/AutomatorSampleApp/Podfile.lock b/SampleApp/AutomatorSampleApp/Podfile.lock new file mode 100644 index 0000000..727531c --- /dev/null +++ b/SampleApp/AutomatorSampleApp/Podfile.lock @@ -0,0 +1,14 @@ +PODS: + - Illuminator (0.0.1) + +DEPENDENCIES: + - Illuminator (from `../../`) + +EXTERNAL SOURCES: + Illuminator: + :local: ../../ + +SPEC CHECKSUMS: + Illuminator: 6d22f2dc02bbcfc9b83b3443fce4cad6ad9daacb + +COCOAPODS: 0.36.0 From 3e95eb4ae32e89982381725e10f4c1126833bce1 Mon Sep 17 00:00:00 2001 From: kviksilver Date: Wed, 8 Apr 2015 15:00:28 -0400 Subject: [PATCH 08/11] [PODS] change local to path as local is deprecated in podspec --- SampleApp/AutomatorSampleApp/Podfile | 2 +- SampleApp/AutomatorSampleApp/Podfile.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SampleApp/AutomatorSampleApp/Podfile b/SampleApp/AutomatorSampleApp/Podfile index 4fc7e96..c1ab251 100644 --- a/SampleApp/AutomatorSampleApp/Podfile +++ b/SampleApp/AutomatorSampleApp/Podfile @@ -1 +1 @@ -pod 'Illuminator', :local => "../../" +pod 'Illuminator', :path => "../../" diff --git a/SampleApp/AutomatorSampleApp/Podfile.lock b/SampleApp/AutomatorSampleApp/Podfile.lock index 727531c..8b3c7ea 100644 --- a/SampleApp/AutomatorSampleApp/Podfile.lock +++ b/SampleApp/AutomatorSampleApp/Podfile.lock @@ -6,7 +6,7 @@ DEPENDENCIES: EXTERNAL SOURCES: Illuminator: - :local: ../../ + :path: ../../ SPEC CHECKSUMS: Illuminator: 6d22f2dc02bbcfc9b83b3443fce4cad6ad9daacb From 65eb08234aff4846cf890f219740d3e085656c98 Mon Sep 17 00:00:00 2001 From: Ian Katz Date: Wed, 8 Apr 2015 16:20:27 -0400 Subject: [PATCH 09/11] Convert to ruby gem --- .gitignore | 40 ++- .travis.yml | 1 + Gemfile | 4 + Gemfile.lock | 16 - Rakefile | 1 + SampleApp/Gemfile | 2 + SampleApp/Gemfile.lock | 22 ++ .../scripts => SampleApp}/rerunFailedTests.rb | 0 gem/README.md | 37 +++ gem/bin/console | 14 + gem/bin/setup | 7 + .../lib/illuminator.rb | 33 +- gem/lib/illuminator/argument-parsing.rb | 283 ++++++++++++++++++ .../lib/illuminator/automation-builder.rb | 5 +- .../lib/illuminator/automation-runner.rb | 30 +- .../lib/illuminator/build-artifacts.rb | 0 .../lib/illuminator/device-installer.rb | 2 +- gem/lib/illuminator/host-utils.rb | 42 +++ .../lib/illuminator/instruments-runner.rb | 10 +- .../lib/illuminator/javascript-runner.rb | 8 +- .../illuminator/listeners/console-logger.rb | 4 +- .../lib/illuminator/listeners/full-output.rb | 2 +- .../listeners/instruments-listener.rb | 0 .../intermittent-failure-detector.rb | 2 +- .../illuminator/listeners/pretty-output.rb | 2 +- .../illuminator/listeners/saltinel-agent.rb | 2 +- .../listeners/saltinel-listener.rb | 2 +- .../illuminator/listeners/start-detector.rb | 2 +- .../illuminator/listeners/stop-detector.rb | 2 +- .../illuminator/listeners/test-listener.rb | 2 +- gem/lib/illuminator/options.rb | 92 ++++++ .../IlluminatorGeneratedEnvironment.erb | 0 ...luminatorGeneratedRunnerForInstruments.erb | 0 .../lib/illuminator/test-definitions.rb | 1 - .../lib/illuminator/test-suite.rb | 0 gem/lib/illuminator/version.rb | 3 + .../lib/illuminator/xcode-builder.rb | 6 +- gem/lib/illuminator/xcode-utils.rb | 203 +++++++++++++ gemfile | 5 - illuminator.gemspec | 32 ++ src/scripts/classes/HostUtils.rb | 39 --- .../classes/IlluminatorArgumentParsing.rb | 280 ----------------- src/scripts/classes/IlluminatorOptions.rb | 90 ------ src/scripts/classes/XcodeUtils.rb | 199 ------------ 44 files changed, 836 insertions(+), 691 deletions(-) create mode 100644 Gemfile delete mode 100644 Gemfile.lock create mode 100644 Rakefile create mode 100644 SampleApp/Gemfile create mode 100644 SampleApp/Gemfile.lock rename {src/scripts => SampleApp}/rerunFailedTests.rb (100%) create mode 100644 gem/README.md create mode 100755 gem/bin/console create mode 100755 gem/bin/setup rename src/scripts/classes/IlluminatorFramework.rb => gem/lib/illuminator.rb (78%) create mode 100644 gem/lib/illuminator/argument-parsing.rb rename src/scripts/classes/AutomationBuilder.rb => gem/lib/illuminator/automation-builder.rb (86%) rename src/scripts/classes/AutomationRunner.rb => gem/lib/illuminator/automation-runner.rb (94%) rename src/scripts/classes/BuildArtifacts.rb => gem/lib/illuminator/build-artifacts.rb (100%) rename src/scripts/classes/DeviceInstaller.rb => gem/lib/illuminator/device-installer.rb (94%) create mode 100644 gem/lib/illuminator/host-utils.rb rename src/scripts/classes/InstrumentsRunner.rb => gem/lib/illuminator/instruments-runner.rb (94%) rename src/scripts/classes/JavascriptRunner.rb => gem/lib/illuminator/javascript-runner.rb (92%) rename src/scripts/classes/listeners/ConsoleLogger.rb => gem/lib/illuminator/listeners/console-logger.rb (77%) rename src/scripts/classes/listeners/FullOutput.rb => gem/lib/illuminator/listeners/full-output.rb (61%) rename src/scripts/classes/listeners/InstrumentsListener.rb => gem/lib/illuminator/listeners/instruments-listener.rb (100%) rename src/scripts/classes/listeners/IntermittentFailureDetector.rb => gem/lib/illuminator/listeners/intermittent-failure-detector.rb (92%) rename src/scripts/classes/listeners/PrettyOutput.rb => gem/lib/illuminator/listeners/pretty-output.rb (84%) rename src/scripts/classes/listeners/SaltinelAgent.rb => gem/lib/illuminator/listeners/saltinel-agent.rb (95%) rename src/scripts/classes/listeners/SaltinelListener.rb => gem/lib/illuminator/listeners/saltinel-listener.rb (86%) rename src/scripts/classes/listeners/StartDetector.rb => gem/lib/illuminator/listeners/start-detector.rb (93%) rename src/scripts/classes/listeners/StopDetector.rb => gem/lib/illuminator/listeners/stop-detector.rb (89%) rename src/scripts/classes/listeners/TestListener.rb => gem/lib/illuminator/listeners/test-listener.rb (94%) create mode 100644 gem/lib/illuminator/options.rb rename {src/scripts => gem/lib/illuminator}/resources/IlluminatorGeneratedEnvironment.erb (100%) rename {src/scripts => gem/lib/illuminator}/resources/IlluminatorGeneratedRunnerForInstruments.erb (100%) rename src/scripts/classes/TestDefinitions.rb => gem/lib/illuminator/test-definitions.rb (95%) rename src/scripts/classes/TestSuite.rb => gem/lib/illuminator/test-suite.rb (100%) create mode 100644 gem/lib/illuminator/version.rb rename src/scripts/classes/XcodeBuilder.rb => gem/lib/illuminator/xcode-builder.rb (93%) create mode 100644 gem/lib/illuminator/xcode-utils.rb delete mode 100644 gemfile create mode 100644 illuminator.gemspec delete mode 100644 src/scripts/classes/HostUtils.rb delete mode 100644 src/scripts/classes/IlluminatorArgumentParsing.rb delete mode 100644 src/scripts/classes/IlluminatorOptions.rb delete mode 100644 src/scripts/classes/XcodeUtils.rb diff --git a/.gitignore b/.gitignore index 9e50ece..633dc85 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,47 @@ buildArtifacts/ **/.DS_Store .DS_Store -.bundle -vendor .idea *.xcworkspace !default.xcworkspace xcuserdata SampleApp/AutomatorSampleApp/build SampleApp/AutomatorSampleApp/Pods + +## For gem + +*.gem +*.rbc +/.config +/coverage/ +/InstalledFiles +/pkg/ +/spec/reports/ +/test/tmp/ +/test/version_tmp/ +/tmp/ + +## Specific to RubyMotion: +.dat* +.repl_history +build/ + +## Documentation cache and generated files: +/.yardoc/ +/_yardoc/ +/doc/ +/rdoc/ + +## Environment normalisation: +/.bundle/ +/vendor/bundle +/lib/bundler/man/ + +# for a library or gem, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +Gemfile.lock +# .ruby-version +# .ruby-gemset + +# unless supporting rvm < 1.11.0 or doing something fancy, ignore this: +.rvmrc diff --git a/.travis.yml b/.travis.yml index 98c2d27..f000ddd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,2 +1,3 @@ language: objective-c +install: bundle install --jobs=3 --retry=3 --gemfile SampleApp/Gemfile script: ruby SampleApp/smokeTests.rb \ No newline at end of file diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..d8a5010 --- /dev/null +++ b/Gemfile @@ -0,0 +1,4 @@ +source 'https://rubygems.org' + +# Specify your gem's dependencies in illuminator.gemspec +gemspec diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index 29d7289..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,16 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - colorize (0.7.2) - dnssd (2.0) - json (1.8.1) - xcpretty (0.1.2) - -PLATFORMS - ruby - -DEPENDENCIES - colorize - dnssd - json - xcpretty diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..2995527 --- /dev/null +++ b/Rakefile @@ -0,0 +1 @@ +require "bundler/gem_tasks" diff --git a/SampleApp/Gemfile b/SampleApp/Gemfile new file mode 100644 index 0000000..170d653 --- /dev/null +++ b/SampleApp/Gemfile @@ -0,0 +1,2 @@ +source 'https://rubygems.org' +gem 'illuminator', :path => '../' diff --git a/SampleApp/Gemfile.lock b/SampleApp/Gemfile.lock new file mode 100644 index 0000000..e00bc5f --- /dev/null +++ b/SampleApp/Gemfile.lock @@ -0,0 +1,22 @@ +PATH + remote: ../ + specs: + illuminator (0.1.0) + colorize + dnssd + json + xcpretty + +GEM + remote: https://rubygems.org/ + specs: + colorize (0.7.5) + dnssd (3.0.1) + json (1.8.2) + xcpretty (0.1.8) + +PLATFORMS + ruby + +DEPENDENCIES + illuminator! diff --git a/src/scripts/rerunFailedTests.rb b/SampleApp/rerunFailedTests.rb similarity index 100% rename from src/scripts/rerunFailedTests.rb rename to SampleApp/rerunFailedTests.rb diff --git a/gem/README.md b/gem/README.md new file mode 100644 index 0000000..3c50172 --- /dev/null +++ b/gem/README.md @@ -0,0 +1,37 @@ +# Illuminator gem + +This gem contains ruby modules necessary to run tests using the [Illuminator framework](http://github.com/paypal/Illuminator). + +## Installation + +Add this line to your application's Gemfile: + +```ruby +gem 'illuminator' +``` + +And then execute: + + $ bundle + +Or install it yourself as: + + $ gem install illuminator + +## Usage + +TODO: Write usage instructions here + +## Development + +After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment. + +To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). + +## Contributing + +1. Fork it ( https://github.com/paypal/illuminator/fork ) +2. Create your feature branch (`git checkout -b my-new-feature`) +3. Commit your changes (`git commit -am 'Add some feature'`) +4. Push to the branch (`git push origin my-new-feature`) +5. Create a new Pull Request diff --git a/gem/bin/console b/gem/bin/console new file mode 100755 index 0000000..0b5d20d --- /dev/null +++ b/gem/bin/console @@ -0,0 +1,14 @@ +#!/usr/bin/env ruby + +require "bundler/setup" +require "illuminator" + +# You can add fixtures and/or initialization code here to make experimenting +# with your gem easier. You can also use a different console, if you like. + +# (If you use this, don't forget to add pry to your Gemfile!) +# require "pry" +# Pry.start + +require "irb" +IRB.start diff --git a/gem/bin/setup b/gem/bin/setup new file mode 100755 index 0000000..b65ed50 --- /dev/null +++ b/gem/bin/setup @@ -0,0 +1,7 @@ +#!/bin/bash +set -euo pipefail +IFS=$'\n\t' + +bundle install + +# Do any other automated setup that you need to do here diff --git a/src/scripts/classes/IlluminatorFramework.rb b/gem/lib/illuminator.rb similarity index 78% rename from src/scripts/classes/IlluminatorFramework.rb rename to gem/lib/illuminator.rb index 3ed0181..5164354 100644 --- a/src/scripts/classes/IlluminatorFramework.rb +++ b/gem/lib/illuminator.rb @@ -1,12 +1,12 @@ -require 'ostruct' - -require File.join(File.expand_path(File.dirname(__FILE__)), 'AutomationBuilder.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'AutomationRunner.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'DeviceInstaller.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'BuildArtifacts.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'HostUtils.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'XcodeUtils.rb') +require "illuminator/version" +require "illuminator/automation-builder" +require "illuminator/automation-runner" +require "illuminator/device-installer" +require "illuminator/build-artifacts" +require "illuminator/host-utils" +require "illuminator/xcode-utils" +require "illuminator/options" class IlluminatorFramework @@ -52,25 +52,27 @@ def self.validateOptions(options) return noproblems end - ################################################################################################ - # MAIN ENTRY POINT - ################################################################################################ +end + + +module Illuminator + def self.runWithOptions(originalOptions, workspace) - options = IlluminatorOptions.new(originalOptions.to_h) # immediately create a copy of the options, because we may mangle them + options = Options.new(originalOptions.to_h) # immediately create a copy of the options, because we may mangle them hardwareID = options.illuminator.hardwareID appName = options.xcode.appName # validate some inputs - return false unless self.validateOptions(options) + return false unless IlluminatorFramework.validateOptions(options) # do any initial cleaning cleanDirs = { HostUtils.realpath("~/Library/Developer/Xcode/DerivedData") => options.illuminator.clean.derived, BuildArtifacts.instance.root(true) => options.illuminator.clean.artifacts, } - self.cleanCountdown if self.willClean(options) and (not options.illuminator.clean.noDelay) + IlluminatorFramework.cleanCountdown if IlluminatorFramework.willClean(options) and (not options.illuminator.clean.noDelay) cleanDirs.each do |d, doClean| dir = HostUtils.realpath d if doClean @@ -130,7 +132,8 @@ def self.reRun(configPath, workspace, overrideOptions = nil) # process any overrides options = overrideOptions.(IlluminatorOptions.new(JSON.parse(jsonConfig))) unless overrideOptions.nil? - return self.runWithOptions options, workspace + return runWithOptions options, workspace end + end diff --git a/gem/lib/illuminator/argument-parsing.rb b/gem/lib/illuminator/argument-parsing.rb new file mode 100644 index 0000000..ef9fcf5 --- /dev/null +++ b/gem/lib/illuminator/argument-parsing.rb @@ -0,0 +1,283 @@ +require 'optparse' +require 'ostruct' + +require_relative './options' +require_relative './host-utils' + + +class IlluminatorParser < OptionParser + def initialize options + super + @_options = options + end + + + def checkRetestArgs + knownRetests = ["solo"] + + @_options["retest"] = [] if @_options["retest"].nil? + + @_options["retest"].each do |r| + if knownRetests.include? r + # ok + elsif /^\d+x$/.match(r) + # ok (1x, 2x, 3x...) + else + puts "Got unknown --retest specifier '#{r}'".yellow + end + end + end + + def getMaxRetests + ret = 0 + @_options["retest"].each do |r| + matches = /^(\d+)x$/.match(r) + unless matches.nil? + ret = [ret, matches[1].to_i].max + end + end + ret + end + + def checkCleanArgs + knownCleans = ["xcode", "buildArtifacts", "derivedData", "noDelay"] + + @_options["clean"] = [] if @_options["clean"].nil? + + @_options["clean"].each do |c| + unless knownCleans.include? c + puts "Got unknown --clean specifier '#{c}'".yellow + end + end + end + + # copy internal options storage into a options object + def copyParsedOptionsInto(illuminatorOptions) + self.checkCleanArgs + self.checkRetestArgs + + # load up known illuminatorOptions + # we only load non-nil options, just in case there was already something in the illuminatorOptions obj + illuminatorOptions.xcode.appName = @_options["appName"] unless @_options["appName"].nil? + illuminatorOptions.xcode.sdk = @_options["sdk"] unless @_options["sdk"].nil? + illuminatorOptions.xcode.scheme = @_options["scheme"] unless @_options["scheme"].nil? + + illuminatorOptions.illuminator.entryPoint = @_options["entryPoint"] unless @_options["entryPoint"].nil? + illuminatorOptions.illuminator.test.randomSeed = @_options["randomSeed"].to_i unless @_options["randomSeed"].nil? + illuminatorOptions.illuminator.test.tags.any = @_options["tagsAny"] unless @_options["tagsAny"].nil? + illuminatorOptions.illuminator.test.tags.all = @_options["tagsAll"] unless @_options["tagsAll"].nil? + illuminatorOptions.illuminator.test.tags.none = @_options["tagsNone"] unless @_options["tagsNone"].nil? + + illuminatorOptions.illuminator.test.retest.attempts = getMaxRetests + illuminatorOptions.illuminator.test.retest.solo = @_options["retest"].include? "solo" + + illuminatorOptions.illuminator.clean.xcode = @_options["clean"].include? "xcode" + illuminatorOptions.illuminator.clean.derived = @_options["clean"].include? "derivedData" + illuminatorOptions.illuminator.clean.artifacts = @_options["clean"].include? "buildArtifacts" + illuminatorOptions.illuminator.clean.noDelay = @_options["clean"].include? "noDelay" + + illuminatorOptions.illuminator.task.build = (not @_options["skipBuild"]) unless @_options["skipBuild"].nil? + illuminatorOptions.illuminator.task.automate = (not @_options["skipAutomate"]) unless @_options["skipAutomate"].nil? + illuminatorOptions.illuminator.task.setSim = (not @_options["skipSetSim"]) unless @_options["skipSetSim"].nil? + illuminatorOptions.illuminator.task.coverage = @_options["coverage"] unless @_options["coverage"].nil? + illuminatorOptions.illuminator.hardwareID = @_options["hardwareID"] unless @_options["hardwareID"].nil? + + illuminatorOptions.simulator.device = @_options["simDevice"] unless @_options["simDevice"].nil? + illuminatorOptions.simulator.version = @_options["simVersion"] unless @_options["simVersion"].nil? + illuminatorOptions.simulator.language = @_options["simLanguage"] unless @_options["simLanguage"].nil? + illuminatorOptions.simulator.killAfter = (not @_options["skipKillAfter"]) unless @_options["skipKillAfter"].nil? + + illuminatorOptions.instruments.appLocation = @_options["appLocation"] unless @_options["appLocation"].nil? + illuminatorOptions.instruments.doVerbose = @_options["verbose"] unless @_options["verbose"].nil? + illuminatorOptions.instruments.timeout = @_options["timeout"].to_i unless @_options["timeout"].nil? + + illuminatorOptions.javascript.testPath = @_options["testPath"] unless @_options["testPath"].nil? + illuminatorOptions.javascript.implementation = @_options["implementation"] unless @_options["implementation"].nil? + + knownKeys = IlluminatorParserFactory.new.letterMap.values # get option keynames from a plain vanilla factory + + # load up unknown illuminatorOptions + illuminatorOptions.appSpecific = @_options.select { |keyname, _| not (knownKeys.include? keyname) } + + return illuminatorOptions + end + + def parse args + leftovers = super(args) + return self.copyParsedOptionsInto(IlluminatorOptions.new) + end + +end + +module Illuminator + class ParserFactory + + attr_reader :letterMap + + # the currency of this parser factory is the "short" single-letter argument switch + def initialize() + @options = nil + @switches = {} + + # build the list of how each parameter will be saved in the output + @letterMap = { + 'x' => 'entryPoint', + 'p' => 'testPath', + 'a' => 'appName', + 'P' => 'xcodeProject', + 't' => 'tagsAny', + 'o' => 'tagsAll', + 'n' => 'tagsNone', + 'q' => 'sdk', + 's' => 'scheme', + 'd' => 'hardwareID', + 'i' => 'implementation', + 'E' => 'appLocation', + 'b' => 'simDevice', + 'z' => 'simVersion', + 'l' => 'simLanguage', + 'f' => 'skipBuild', + 'B' => 'skipAutomate', + 'e' => 'skipSetSim', + 'k' => 'skipKillAfter', + 'c' => 'coverage', + 'r' => 'retest', + 'v' => 'verbose', + 'm' => 'timeout', + 'w' => 'randomSeed', + 'y' => 'clean', + } + + @letterProcessing = { + 'p' => lambda {|p| HostUtils.realpath(p) }, # get real path to tests file + 'E' => lambda {|p| HostUtils.realpath(p) }, # get real path to app + 'y' => lambda {|p| p.split(',')}, # split comma-separated string into array + 'r' => lambda {|p| p.split(',')}, # split comma-separated string into array + 't' => lambda {|p| p.split(',')}, # split comma-separated string into array + 'o' => lambda {|p| p.split(',')}, # split comma-separated string into array + 'n' => lambda {|p| p.split(',')}, # split comma-separated string into array + } + + @defaultValues = { + 'b' => 'iPhone 5', + 'z' => '8.2', + 'q' => 'iphonesimulator', + 'l' => 'en', + 'x' => 'runTestsByTag', + 'm' => 30, + 'f' => false, + 'B' => false, + 'e' => false, + 'k' => false, + 'c' => false, + } + end + + # you must custom prepare before you can add custom switches... otherwise things get all stupid + def prepare(defaultValues = nil, letterMapUpdates = nil, letterProcessingUpdates = nil) + @letterMap = @letterMap.merge(letterMapUpdates) unless letterMapUpdates.nil? + @letterProcessing = @letterProcessing.merge(letterProcessingUpdates) unless letterProcessingUpdates.nil? + @defaultValues = @defaultValues.merge defaultValues unless defaultValues.nil? + + self.addSwitch('x', ['-x', '--entryPoint LABEL', 'The execution entry point {runTestsByTag, runTestsByName, describe}']) + self.addSwitch('p', ['-p', '--testPath PATH', 'Path to js file with all tests imported']) + self.addSwitch('a', ['-a', '--appName APPNAME', "Name of the app to build / run"]) + self.addSwitch('P', ['-P', '--xcodeProject PROJECTNAME', "Project to build -- required if there are 2 in the same directory"]) + self.addSwitch('t', ['-t', '--tags-any TAGSANY', 'Run tests with any of the given tags']) + self.addSwitch('o', ['-o', '--tags-all TAGSALL', 'Run tests with all of the given tags']) + self.addSwitch('n', ['-n', '--tags-none TAGSNONE', 'Run tests with none of the given tags']) + self.addSwitch('q', ['-q', '--sdk SDK', 'SDK to build against']) + self.addSwitch('s', ['-s', '--scheme SCHEME', 'Build and run specific tests on given workspace scheme']) + self.addSwitch('d', ['-d', '--hardwareID ID', 'hardware id of device to run on instead of simulator']) + self.addSwitch('i', ['-i', '--implementation IMPL', 'Device tests implementation']) + self.addSwitch('E', ['-E', '--appLocation LOCATION', 'Location of app executable, if pre-built']) + self.addSwitch('b', ['-b', '--simDevice DEVICE', 'Run on given simulated device']) + self.addSwitch('z', ['-z', '--simVersion VERSION', 'Run on given simulated iOS version']) + self.addSwitch('l', ['-l', '--simLanguage LANGUAGE', 'Run on given simulated iOS language']) + self.addSwitch('f', ['-f', '--skip-build', 'Just automate; assume already built']) + self.addSwitch('B', ['-B', '--skip-automate', "Don't automate; build only"]) + self.addSwitch('e', ['-e', '--skip-set-sim', 'Assume that simulator has already been chosen and properly reset']) + self.addSwitch('k', ['-k', '--skip-kill-after', 'Leave the simulator open after the run']) + self.addSwitch('y', ['-y', '--clean PLACES', 'Comma-separated list of places to clean {xcode, buildArtifacts, derivedData}']) + self.addSwitch('c', ['-c', '--coverage', 'Generate coverage files']) + self.addSwitch('r', ['-r', '--retest OPTIONS', 'Immediately retest failed tests with comma-separated options {1x, solo}']) + self.addSwitch('v', ['-v', '--verbose', 'Show verbose output from instruments']) + self.addSwitch('m', ['-m', '--timeout TIMEOUT', 'Seconds to wait for instruments tool to start tests']) + self.addSwitch('w', ['-w', '--random-seed SEED', 'Randomize test order based on given integer seed']) + end + + # add a parse switch for the given letter key, using the given options. + # the parse action is defined by the existence of letterProcessing for the letter key, + # which by default is simple assignment + def addSwitch(letter, opts) + dest = self.getLetterDestination(letter) + + # alter opts to include the default values + altered = false + if @defaultValues[letter].nil? + opts_with_default = opts + else + opts_with_default = opts.map do |item| + if (!altered and item.chars.first != '-') + item += " :: Defaults to \"#{@defaultValues[letter]}\"" + altered = true + end + item + end + end + + @switches[letter] = OpenStruct.new(:opts => opts_with_default, + :block => lambda do |newval| + # assign the parsed value to the output, processing it if necessary + if @letterProcessing[letter] + @options[dest] = @letterProcessing[letter].call(newval) + else + @options[dest] = newval + end + end) + end + + + # letter destination defaults to the letter itself, but can be overwritten by letterMap + def getLetterDestination(letter) + return @letterMap[letter]? @letterMap[letter] : letter + end + + + # factory function + def buildParser(options, letters = nil) + @options = options + + if letters.nil? + letters = switches.keys.join('') + end + + # helpful error message for bad chars + bad_chars = letters.chars.to_a.select{|c| c != "#" and @switches[c].nil?} + raise ArgumentError, "buildParser got letters (" + letters + ") containing unknown option characters: " + bad_chars.to_s unless bad_chars.empty? + + retval = IlluminatorParser.new options + + # build a parser as specified by the user + letters.each_char do |c| + options[self.getLetterDestination(c)] = @defaultValues[c] unless @defaultValues[c].nil? + + if c == '#' + retval.separator(' ---------------------------------------------------------------------------------') + else + retval.on(*(@switches[c].send(:opts))) {|foo| @switches[c].send(:block).call(foo)} + end + end + + # help message is hard coded! + retval.on_tail('-h', '--help', 'Show this help message') {|foo| puts retval.help(); exit } + + retval.banner = "Usage: #{File.basename($PROGRAM_NAME)} [options]" + + #puts retval + return retval + end + + end + +end diff --git a/src/scripts/classes/AutomationBuilder.rb b/gem/lib/illuminator/automation-builder.rb similarity index 86% rename from src/scripts/classes/AutomationBuilder.rb rename to gem/lib/illuminator/automation-builder.rb index 6ba3005..188b686 100644 --- a/src/scripts/classes/AutomationBuilder.rb +++ b/gem/lib/illuminator/automation-builder.rb @@ -1,8 +1,7 @@ -require 'rubygems' require 'fileutils' -require File.join(File.expand_path(File.dirname(__FILE__)), 'XcodeBuilder.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'BuildArtifacts.rb') +require_relative './xcode-builder' +require_relative './build-artifacts' #################################################################################################### # Builder diff --git a/src/scripts/classes/AutomationRunner.rb b/gem/lib/illuminator/automation-runner.rb similarity index 94% rename from src/scripts/classes/AutomationRunner.rb rename to gem/lib/illuminator/automation-runner.rb index c577cc0..7bc8883 100644 --- a/src/scripts/classes/AutomationRunner.rb +++ b/gem/lib/illuminator/automation-runner.rb @@ -1,24 +1,22 @@ -require 'bundler/setup' -require 'rubygems' require 'fileutils' require 'find' require 'pathname' require 'json' -require File.join(File.expand_path(File.dirname(__FILE__)), 'InstrumentsRunner.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'JavascriptRunner.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'HostUtils.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'XcodeUtils.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'BuildArtifacts.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'TestSuite.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'TestDefinitions.rb') - -require File.join(File.expand_path(File.dirname(__FILE__)), 'listeners/PrettyOutput.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'listeners/FullOutput.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'listeners/ConsoleLogger.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'listeners/TestListener.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'listeners/SaltinelAgent.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'listeners/StopDetector.rb') +require_relative './instruments-runner' +require_relative './javascript-runner' +require_relative './host-utils' +require_relative './xcode-utils' +require_relative './build-artifacts' +require_relative './test-suite' +require_relative './test-definitions' + +require_relative 'listeners/pretty-output' +require_relative 'listeners/full-output' +require_relative 'listeners/console-logger' +require_relative 'listeners/test-listener' +require_relative 'listeners/saltinel-agent' +require_relative 'listeners/stop-detector' #################################################################################################### # runner diff --git a/src/scripts/classes/BuildArtifacts.rb b/gem/lib/illuminator/build-artifacts.rb similarity index 100% rename from src/scripts/classes/BuildArtifacts.rb rename to gem/lib/illuminator/build-artifacts.rb diff --git a/src/scripts/classes/DeviceInstaller.rb b/gem/lib/illuminator/device-installer.rb similarity index 94% rename from src/scripts/classes/DeviceInstaller.rb rename to gem/lib/illuminator/device-installer.rb index 0fcd743..81c5453 100644 --- a/src/scripts/classes/DeviceInstaller.rb +++ b/gem/lib/illuminator/device-installer.rb @@ -1,6 +1,6 @@ require 'singleton' -require File.join(File.expand_path(File.dirname(__FILE__)), 'HostUtils.rb') +require_relative './host-utils' # Wrapper for possible methods of installing an app on physical hardware class DeviceInstaller diff --git a/gem/lib/illuminator/host-utils.rb b/gem/lib/illuminator/host-utils.rb new file mode 100644 index 0000000..e39092f --- /dev/null +++ b/gem/lib/illuminator/host-utils.rb @@ -0,0 +1,42 @@ +require 'pathname' + +module Illuminator + class HostUtils + + # Cross-platform way of finding an executable in the $PATH. + # based on http://stackoverflow.com/a/5471032/2063546 + # + # which('ruby') #=> /usr/bin/ruby + def self.which program + exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : [''] + ENV['PATH'].split(File::PATH_SEPARATOR).each do |path| + exts.each do |ext| + exe = File.join(path, "#{program}#{ext}") + return exe if File.executable?(exe) unless File.directory?(exe) + end + end + return nil + end + + def self.saveJSON(hashObject, path) + f = File.open(path, 'w') + f << JSON.pretty_generate(hashObject) + f.close + end + + # try to simplify the path, if it exists + def self.realpath(path) + epath = File.expand_path path + + # use expanded path if regular one fails + path = epath unless (File.exists? path) or (File.directory? path) + + # use given path if it doesn't exist (can't take a real path of a nonexistent path) + return path unless (File.exists? path) or (File.directory? path) + + Pathname.new(path).realpath.to_s + end + + end + +end diff --git a/src/scripts/classes/InstrumentsRunner.rb b/gem/lib/illuminator/instruments-runner.rb similarity index 94% rename from src/scripts/classes/InstrumentsRunner.rb rename to gem/lib/illuminator/instruments-runner.rb index 330a941..8f8a2d2 100644 --- a/src/scripts/classes/InstrumentsRunner.rb +++ b/gem/lib/illuminator/instruments-runner.rb @@ -1,13 +1,11 @@ -require 'bundler/setup' -require 'rubygems' require 'fileutils' require 'colorize' require 'pty' -require File.join(File.expand_path(File.dirname(__FILE__)), 'XcodeUtils.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'BuildArtifacts.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'listeners/StartDetector.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'listeners/IntermittentFailureDetector.rb') +require_relative './xcode-utils' +require_relative './build-artifacts' +require_relative 'listeners/start-detector' +require_relative 'listeners/intermittent-failure-detector' #################################################################################################### # status diff --git a/src/scripts/classes/JavascriptRunner.rb b/gem/lib/illuminator/javascript-runner.rb similarity index 92% rename from src/scripts/classes/JavascriptRunner.rb rename to gem/lib/illuminator/javascript-runner.rb index 502fd17..48949c3 100644 --- a/src/scripts/classes/JavascriptRunner.rb +++ b/gem/lib/illuminator/javascript-runner.rb @@ -1,12 +1,12 @@ -require 'bundler/setup' require 'erb' require 'pathname' require 'json' require 'socket' require 'digest/sha1' -require File.join(File.expand_path(File.dirname(__FILE__)), '/BuildArtifacts.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), '/HostUtils.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), '/XcodeUtils.rb') + +require_relative './build-artifacts' +require_relative './host-utils' +require_relative './xcode-utils' # Class to handle all configuration relating to the javascript environment # "runner" is a bit of a misnomer (this runs as part of instruments) but without this code, nothing runs diff --git a/src/scripts/classes/listeners/ConsoleLogger.rb b/gem/lib/illuminator/listeners/console-logger.rb similarity index 77% rename from src/scripts/classes/listeners/ConsoleLogger.rb rename to gem/lib/illuminator/listeners/console-logger.rb index 1b50bff..53be244 100644 --- a/src/scripts/classes/listeners/ConsoleLogger.rb +++ b/gem/lib/illuminator/listeners/console-logger.rb @@ -1,7 +1,7 @@ require 'logger' -require File.join(File.expand_path(File.dirname(__FILE__)), '../BuildArtifacts.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'InstrumentsListener.rb') +require_relative '../build-artifacts' +require_relative './instruments-listener' class ConsoleLogger < InstrumentsListener diff --git a/src/scripts/classes/listeners/FullOutput.rb b/gem/lib/illuminator/listeners/full-output.rb similarity index 61% rename from src/scripts/classes/listeners/FullOutput.rb rename to gem/lib/illuminator/listeners/full-output.rb index f874090..6afc8ee 100644 --- a/src/scripts/classes/listeners/FullOutput.rb +++ b/gem/lib/illuminator/listeners/full-output.rb @@ -1,5 +1,5 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'InstrumentsListener.rb') +require_relative './instruments-listener' class FullOutput < InstrumentsListener diff --git a/src/scripts/classes/listeners/InstrumentsListener.rb b/gem/lib/illuminator/listeners/instruments-listener.rb similarity index 100% rename from src/scripts/classes/listeners/InstrumentsListener.rb rename to gem/lib/illuminator/listeners/instruments-listener.rb diff --git a/src/scripts/classes/listeners/IntermittentFailureDetector.rb b/gem/lib/illuminator/listeners/intermittent-failure-detector.rb similarity index 92% rename from src/scripts/classes/listeners/IntermittentFailureDetector.rb rename to gem/lib/illuminator/listeners/intermittent-failure-detector.rb index b2d8d58..fffdac1 100644 --- a/src/scripts/classes/listeners/IntermittentFailureDetector.rb +++ b/gem/lib/illuminator/listeners/intermittent-failure-detector.rb @@ -1,5 +1,5 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'SaltinelListener.rb') +require_relative './saltinel-listener' module IntermittentFailureDetectorEventSink diff --git a/src/scripts/classes/listeners/PrettyOutput.rb b/gem/lib/illuminator/listeners/pretty-output.rb similarity index 84% rename from src/scripts/classes/listeners/PrettyOutput.rb rename to gem/lib/illuminator/listeners/pretty-output.rb index 78022d4..5d3386c 100644 --- a/src/scripts/classes/listeners/PrettyOutput.rb +++ b/gem/lib/illuminator/listeners/pretty-output.rb @@ -1,5 +1,5 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'InstrumentsListener.rb') +require_relative './instruments-listener' class PrettyOutput < InstrumentsListener diff --git a/src/scripts/classes/listeners/SaltinelAgent.rb b/gem/lib/illuminator/listeners/saltinel-agent.rb similarity index 95% rename from src/scripts/classes/listeners/SaltinelAgent.rb rename to gem/lib/illuminator/listeners/saltinel-agent.rb index 3f997fc..d0272b0 100644 --- a/src/scripts/classes/listeners/SaltinelAgent.rb +++ b/gem/lib/illuminator/listeners/saltinel-agent.rb @@ -1,5 +1,5 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'SaltinelListener.rb') +require_relative './saltinel-listener' module SaltinelAgentEventSink diff --git a/src/scripts/classes/listeners/SaltinelListener.rb b/gem/lib/illuminator/listeners/saltinel-listener.rb similarity index 86% rename from src/scripts/classes/listeners/SaltinelListener.rb rename to gem/lib/illuminator/listeners/saltinel-listener.rb index 6d9b7bd..58ebd47 100644 --- a/src/scripts/classes/listeners/SaltinelListener.rb +++ b/gem/lib/illuminator/listeners/saltinel-listener.rb @@ -1,5 +1,5 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'InstrumentsListener.rb') +require_relative './instruments-listener' # A listener class that just looks for saltinel messages and parses them, # sending them off to a subclassable handler diff --git a/src/scripts/classes/listeners/StartDetector.rb b/gem/lib/illuminator/listeners/start-detector.rb similarity index 93% rename from src/scripts/classes/listeners/StartDetector.rb rename to gem/lib/illuminator/listeners/start-detector.rb index 6b8540f..0189148 100644 --- a/src/scripts/classes/listeners/StartDetector.rb +++ b/gem/lib/illuminator/listeners/start-detector.rb @@ -1,5 +1,5 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'SaltinelListener.rb') +require_relative './saltinel-listener' module StartDetectorEventSink diff --git a/src/scripts/classes/listeners/StopDetector.rb b/gem/lib/illuminator/listeners/stop-detector.rb similarity index 89% rename from src/scripts/classes/listeners/StopDetector.rb rename to gem/lib/illuminator/listeners/stop-detector.rb index 0c603b4..ee857f7 100644 --- a/src/scripts/classes/listeners/StopDetector.rb +++ b/gem/lib/illuminator/listeners/stop-detector.rb @@ -1,5 +1,5 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), 'InstrumentsListener.rb') +require_relative 'instruments-listener' module StopDetectorEventSink diff --git a/src/scripts/classes/listeners/TestListener.rb b/gem/lib/illuminator/listeners/test-listener.rb similarity index 94% rename from src/scripts/classes/listeners/TestListener.rb rename to gem/lib/illuminator/listeners/test-listener.rb index 6a44e59..73b5dfe 100644 --- a/src/scripts/classes/listeners/TestListener.rb +++ b/gem/lib/illuminator/listeners/test-listener.rb @@ -1,6 +1,6 @@ require 'date' -require File.join(File.expand_path(File.dirname(__FILE__)), 'InstrumentsListener.rb') +require_relative './instruments-listener' module TestListenerEventSink diff --git a/gem/lib/illuminator/options.rb b/gem/lib/illuminator/options.rb new file mode 100644 index 0000000..7400873 --- /dev/null +++ b/gem/lib/illuminator/options.rb @@ -0,0 +1,92 @@ + +require 'ostruct' + +class RecursiveOpenStruct < OpenStruct + + def initialize(hash=nil) + # preprocess hash objects into openstruct objects + unless hash.nil? + hash.each do |k, v| + hash[k] = RecursiveOpenStruct.new(v) if v.is_a? Hash + end + end + + super + end + + # recursively translate the openstruct hierarchy to a hash hierarchy + def to_h + ret = super + + ret.each do |k, v| + ret[k] = v.to_h if v.is_a? RecursiveOpenStruct + end + + return ret + end +end + +module Illuminator + class Options < RecursiveOpenStruct + + def initialize(hash=nil) + super + return unless hash.nil? + + # stub out all the branches + self.xcode = RecursiveOpenStruct.new + self.instruments = RecursiveOpenStruct.new + self.simulator = RecursiveOpenStruct.new + self.javascript = RecursiveOpenStruct.new + self.illuminator = RecursiveOpenStruct.new + self.appSpecific = nil # all unknown options will go here + + self.illuminator.clean = RecursiveOpenStruct.new + self.illuminator.task = RecursiveOpenStruct.new + self.illuminator.test = RecursiveOpenStruct.new + + self.illuminator.test.tags = RecursiveOpenStruct.new + self.illuminator.test.retest = RecursiveOpenStruct.new + + # name all the keys (just for visibiilty) + self.xcode.project = nil + self.xcode.appName = nil + self.xcode.sdk = nil + self.xcode.scheme = nil + self.xcode.environmentVars = nil + + self.illuminator.entryPoint = nil + self.illuminator.test.randomSeed = nil + self.illuminator.test.tags.any = nil + self.illuminator.test.tags.all = nil + self.illuminator.test.tags.none = nil + self.illuminator.test.names = nil + self.illuminator.test.retest.attempts = nil + self.illuminator.test.retest.solo = nil + self.illuminator.clean.xcode = nil + self.illuminator.clean.derived = nil + self.illuminator.clean.artifacts = nil + self.illuminator.clean.noDelay = nil + self.illuminator.task.build = nil + self.illuminator.task.automate = nil + self.illuminator.task.setSim = nil + self.illuminator.task.coverage = nil + self.illuminator.hardwareID = nil + + self.simulator.device = nil + self.simulator.version = nil + self.simulator.language = nil + self.simulator.killAfter = nil + + self.instruments.doVerbose = nil + self.instruments.timeout = nil + self.instruments.attempts = nil + self.instruments.appLocation = nil # normally, this is where we build to + + self.javascript.testPath = nil + self.javascript.implementation = nil + self.javascript.appSpecificConfig = nil + end + + end +end diff --git a/src/scripts/resources/IlluminatorGeneratedEnvironment.erb b/gem/lib/illuminator/resources/IlluminatorGeneratedEnvironment.erb similarity index 100% rename from src/scripts/resources/IlluminatorGeneratedEnvironment.erb rename to gem/lib/illuminator/resources/IlluminatorGeneratedEnvironment.erb diff --git a/src/scripts/resources/IlluminatorGeneratedRunnerForInstruments.erb b/gem/lib/illuminator/resources/IlluminatorGeneratedRunnerForInstruments.erb similarity index 100% rename from src/scripts/resources/IlluminatorGeneratedRunnerForInstruments.erb rename to gem/lib/illuminator/resources/IlluminatorGeneratedRunnerForInstruments.erb diff --git a/src/scripts/classes/TestDefinitions.rb b/gem/lib/illuminator/test-definitions.rb similarity index 95% rename from src/scripts/classes/TestDefinitions.rb rename to gem/lib/illuminator/test-definitions.rb index 2f4ff40..bc8f92d 100644 --- a/src/scripts/classes/TestDefinitions.rb +++ b/gem/lib/illuminator/test-definitions.rb @@ -1,4 +1,3 @@ -require 'bundler/setup' require 'json' # A class to hold the defintions of all automator tests, as defined in the (generated) automatorScenarios.json diff --git a/src/scripts/classes/TestSuite.rb b/gem/lib/illuminator/test-suite.rb similarity index 100% rename from src/scripts/classes/TestSuite.rb rename to gem/lib/illuminator/test-suite.rb diff --git a/gem/lib/illuminator/version.rb b/gem/lib/illuminator/version.rb new file mode 100644 index 0000000..dce050e --- /dev/null +++ b/gem/lib/illuminator/version.rb @@ -0,0 +1,3 @@ +module Illuminator + VERSION = "0.1.0" +end diff --git a/src/scripts/classes/XcodeBuilder.rb b/gem/lib/illuminator/xcode-builder.rb similarity index 93% rename from src/scripts/classes/XcodeBuilder.rb rename to gem/lib/illuminator/xcode-builder.rb index 3710eb8..98a90ad 100644 --- a/src/scripts/classes/XcodeBuilder.rb +++ b/gem/lib/illuminator/xcode-builder.rb @@ -1,9 +1,7 @@ -require 'bundler/setup' -require 'rubygems' require 'colorize' -require File.join(File.expand_path(File.dirname(__FILE__)), 'BuildArtifacts.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'HostUtils.rb') +require_relative './build-artifacts' +require_relative './host-utils' class XcodeBuilder attr_accessor :project diff --git a/gem/lib/illuminator/xcode-utils.rb b/gem/lib/illuminator/xcode-utils.rb new file mode 100644 index 0000000..06d73ff --- /dev/null +++ b/gem/lib/illuminator/xcode-utils.rb @@ -0,0 +1,203 @@ +require 'singleton' +require 'fileutils' + +module Illuminator + + # Convenience functions for command-line actions done in Xcode + class XcodeUtils + include Singleton + + def initialize + @xcodePath = `/usr/bin/xcode-select -print-path`.chomp.sub(/^\s+/, '') + @xcodeVersion = nil + @sdkPath = nil + @instrumentsPath = nil + @_simulatorDevicesText = nil + @simulatorDeviceTypes = nil + @simulatorRuntims = nil + end + + def getXcodePath + @xcodePath + end + + def getXcodeAppPath + HostUtils.realpath(File.join(@xcodePath, "../../")) + end + + def getXcodeSimctlPath + HostUtils.realpath(File.join(@xcodePath, "/usr/bin/simctl")) + end + + def getXcodeVersion + if @xcodeVersion.nil? + xcodeVersion = `xcodebuild -version` + needle = 'Xcode (.*)' + match = xcodeVersion.match(needle) + @xcodeVersion = match.captures[0] + end + @xcodeVersion + end + + def isXcodeMajorVersion ver + # should update this with 'version' gem + needle = '(\d+)\.?(\d+)?' + match = self.getXcodeVersion.match(needle) + return match.captures[0].to_i == ver + end + + # Get the path to the SDK + def getSdkPath + @sdkPath ||= `/usr/bin/xcodebuild -version -sdk iphoneos | grep PlatformPath`.split(':')[1].chomp.sub(/^\s+/, '') + end + + # Get the path to the instruments bundle + def getInstrumentsPath + if @instrumentsPath.nil? + if File.directory? "#{@xcodePath}/../Applications/Instruments.app/Contents/PlugIns/AutomationInstrument.xrplugin/" + @instrumentsPath = "AutomationInstrument.xrplugin"; + else + #fallback to old instruments bundle (pre Xcode6) + @instrumentsPath = "AutomationInstrument.bundle"; + end + end + @instrumentsPath + end + + # Get the path to the instruments template + def getInstrumentsTemplatePath + instrumentsFolder = self.getInstrumentsPath + "#{@xcodePath}/../Applications/Instruments.app/Contents/PlugIns/#{instrumentsFolder}/Contents/Resources/Automation.tracetemplate" + end + + def _getAllSimulatorInfo + info = `#{self.getXcodeSimctlPath} list`.split("\n") + + output = {"devices" => [], "runtimes" => []} + pointer = nil + needle = nil + + info.each do |line| + case line + when "== Device Types ==" + # all data we want is followed by " (" e.g. "iPhone 5 (com.apple.C......." + pointer = "devices" + needle = '([^(]*) ' + when "== Runtimes ==" + # all data we want is in the form "iOS 7.0 (7.0.3 - ........." and we want the 7.0 + pointer = "runtimes" + needle = 'iOS ([^(]*) ' + when "== Devices ==" + pointer = nil + needle = nil + else + unless pointer.nil? + match = line.match(needle) + if match + output[pointer] << match.captures[0] + end + end + end + end + + @simulatorDeviceTypes = output["devices"] + @simulatorRuntimes = output["runtimes"] + end + + def getSimulatorDeviceTypes + if @simulatorDeviceTypes.nil? + self._getAllSimulatorInfo + end + @simulatorDeviceTypes + end + + def getSimulatorRuntimes + if @simulatorRuntimes.nil? + self._getAllSimulatorInfo + end + @simulatorRuntimes + end + + def getSimulatorDevices + if @_simulatorDevicesText.nil? + @_simulatorDevicesText = `instruments -s devices` + end + @_simulatorDevicesText + end + + # Based on the desired device and version, get the ID of the simulator that will be passed to instruments + def getSimulatorID (simDevice, simVersion) + devices = self.getSimulatorDevices + needle = simDevice + ' \(' + simVersion + ' Simulator\) \[(.*)\]' + match = devices.match(needle) + if match + puts "Found device match: #{match}".green + return match.captures[0] + elsif + puts "Did not find UDID of device '#{simDevice}' for version '#{simVersion}'".green + if XcodeUtils.instance.isXcodeMajorVersion 5 + fallbackName = "#{simDevice} - Simulator - iOS #{simVersion}" + puts "Falling back to Xcode5 name #{fallbackName}".green + return fallbackName + end + end + + return nil + end + + def getCrashDirectory + return "#{ENV['HOME']}/Library/Logs/DiagnosticReports" + end + + # Create a crash report + def createSymbolicatedCrashReport (appPath, crashPath, crashReportPath) + # find symbolicatecrash file, which is different depending on the Xcode version (we assume either 5 or 6) + frameworksPath = "#{@xcodePath}/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks" + symbolicatorPath = "#{frameworksPath}/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash" + if not File.exist?(symbolicatorPath) + symbolicatorPath = "#{frameworksPath}/DTDeviceKit.framework/Versions/A/Resources/symbolicatecrash" + end + if not File.exist?(symbolicatorPath) + symbolicatorPath = File.join(self.getXcodeAppPath, "Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash") + end + + command = "DEVELOPER_DIR='#{@xcodePath}' " + command << "'#{symbolicatorPath}' " + command << "-o '#{crashReportPath}' '#{crashPath}' '#{appPath}.dSYM' 2>&1" + + output = `#{command}` + + # log the output of the crash reporting if the file didn't appear + unless File.exist?(crashReportPath) + puts command.green + puts output + return false + end + return true + end + + # use the provided applescript to reset the content and settings of the simulator + def resetSimulator deviceID + command = "#{self.getXcodeSimctlPath} erase #{deviceID}" + puts command.green + puts `#{command}` + + end + + # remove any apps in the specified directory + def self.removeExistingApps xcodeOutputDir + Dir["#{xcodeOutputDir}/*.app"].each do |app| + puts "XcodeUtils: removing #{app}" + FileUtils.rm_rf app + end + end + + def self.killAllSimulatorProcesses + command = HostUtils.realpath(File.join(File.dirname(__FILE__), "../kill_all_sim_processes.sh")) + puts "Running #{command}" + puts `'#{command}'` + end + + end + +end diff --git a/gemfile b/gemfile deleted file mode 100644 index 37bfb69..0000000 --- a/gemfile +++ /dev/null @@ -1,5 +0,0 @@ -source 'https://rubygems.org' -gem 'dnssd' -gem 'colorize' -gem 'json' -gem 'xcpretty' diff --git a/illuminator.gemspec b/illuminator.gemspec new file mode 100644 index 0000000..30bdf7c --- /dev/null +++ b/illuminator.gemspec @@ -0,0 +1,32 @@ +# coding: utf-8 +lib = File.expand_path('../gem/lib', __FILE__) +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) +require 'illuminator/version' + +Gem::Specification.new do |spec| + spec.name = "illuminator" + spec.version = Illuminator::VERSION + spec.licenses = ['Apache 2.0'] + spec.authors = ["Ian Katz", "Boris Erceg"] + spec.email = ["iakatz@paypal.com"] + + spec.summary = %q{iOS CI test runner for Illuminator} + spec.homepage = "http://github.com/paypal/illuminator" + + spec.files = `git ls-files -z gem`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } + spec.bindir = "exe" + spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } + spec.require_paths = ["gem/lib"] + + if spec.respond_to?(:metadata) + # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com' to prevent pushes to rubygems.org, or delete to allow pushes to any server." + end + + spec.add_development_dependency "bundler", "~> 1.9" + spec.add_development_dependency "rake", "~> 10.0" + + spec.add_runtime_dependency "json" + spec.add_runtime_dependency "colorize" + spec.add_runtime_dependency "xcpretty" + spec.add_runtime_dependency "dnssd" +end diff --git a/src/scripts/classes/HostUtils.rb b/src/scripts/classes/HostUtils.rb deleted file mode 100644 index a5ff8d1..0000000 --- a/src/scripts/classes/HostUtils.rb +++ /dev/null @@ -1,39 +0,0 @@ -require 'pathname' - -class HostUtils - - # Cross-platform way of finding an executable in the $PATH. - # based on http://stackoverflow.com/a/5471032/2063546 - # - # which('ruby') #=> /usr/bin/ruby - def self.which program - exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : [''] - ENV['PATH'].split(File::PATH_SEPARATOR).each do |path| - exts.each do |ext| - exe = File.join(path, "#{program}#{ext}") - return exe if File.executable?(exe) unless File.directory?(exe) - end - end - return nil - end - - def self.saveJSON(hashObject, path) - f = File.open(path, 'w') - f << JSON.pretty_generate(hashObject) - f.close - end - - # try to simplify the path, if it exists - def self.realpath(path) - epath = File.expand_path path - - # use expanded path if regular one fails - path = epath unless (File.exists? path) or (File.directory? path) - - # use given path if it doesn't exist (can't take a real path of a nonexistent path) - return path unless (File.exists? path) or (File.directory? path) - - Pathname.new(path).realpath.to_s - end - -end diff --git a/src/scripts/classes/IlluminatorArgumentParsing.rb b/src/scripts/classes/IlluminatorArgumentParsing.rb deleted file mode 100644 index c1dc727..0000000 --- a/src/scripts/classes/IlluminatorArgumentParsing.rb +++ /dev/null @@ -1,280 +0,0 @@ -require 'optparse' -require 'ostruct' - -require File.join(File.expand_path(File.dirname(__FILE__)), 'IlluminatorOptions.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), 'HostUtils.rb') - - -class IlluminatorParser < OptionParser - def initialize options - super - @_options = options - end - - - def checkRetestArgs - knownRetests = ["solo"] - - @_options["retest"] = [] if @_options["retest"].nil? - - @_options["retest"].each do |r| - if knownRetests.include? r - # ok - elsif /^\d+x$/.match(r) - # ok (1x, 2x, 3x...) - else - puts "Got unknown --retest specifier '#{r}'".yellow - end - end - end - - def getMaxRetests - ret = 0 - @_options["retest"].each do |r| - matches = /^(\d+)x$/.match(r) - unless matches.nil? - ret = [ret, matches[1].to_i].max - end - end - ret - end - - def checkCleanArgs - knownCleans = ["xcode", "buildArtifacts", "derivedData", "noDelay"] - - @_options["clean"] = [] if @_options["clean"].nil? - - @_options["clean"].each do |c| - unless knownCleans.include? c - puts "Got unknown --clean specifier '#{c}'".yellow - end - end - end - - # copy internal options storage into a options object - def copyParsedOptionsInto(illuminatorOptions) - self.checkCleanArgs - self.checkRetestArgs - - # load up known illuminatorOptions - # we only load non-nil options, just in case there was already something in the illuminatorOptions obj - illuminatorOptions.xcode.appName = @_options["appName"] unless @_options["appName"].nil? - illuminatorOptions.xcode.sdk = @_options["sdk"] unless @_options["sdk"].nil? - illuminatorOptions.xcode.scheme = @_options["scheme"] unless @_options["scheme"].nil? - - illuminatorOptions.illuminator.entryPoint = @_options["entryPoint"] unless @_options["entryPoint"].nil? - illuminatorOptions.illuminator.test.randomSeed = @_options["randomSeed"].to_i unless @_options["randomSeed"].nil? - illuminatorOptions.illuminator.test.tags.any = @_options["tagsAny"] unless @_options["tagsAny"].nil? - illuminatorOptions.illuminator.test.tags.all = @_options["tagsAll"] unless @_options["tagsAll"].nil? - illuminatorOptions.illuminator.test.tags.none = @_options["tagsNone"] unless @_options["tagsNone"].nil? - - illuminatorOptions.illuminator.test.retest.attempts = getMaxRetests - illuminatorOptions.illuminator.test.retest.solo = @_options["retest"].include? "solo" - - illuminatorOptions.illuminator.clean.xcode = @_options["clean"].include? "xcode" - illuminatorOptions.illuminator.clean.derived = @_options["clean"].include? "derivedData" - illuminatorOptions.illuminator.clean.artifacts = @_options["clean"].include? "buildArtifacts" - illuminatorOptions.illuminator.clean.noDelay = @_options["clean"].include? "noDelay" - - illuminatorOptions.illuminator.task.build = (not @_options["skipBuild"]) unless @_options["skipBuild"].nil? - illuminatorOptions.illuminator.task.automate = (not @_options["skipAutomate"]) unless @_options["skipAutomate"].nil? - illuminatorOptions.illuminator.task.setSim = (not @_options["skipSetSim"]) unless @_options["skipSetSim"].nil? - illuminatorOptions.illuminator.task.coverage = @_options["coverage"] unless @_options["coverage"].nil? - illuminatorOptions.illuminator.hardwareID = @_options["hardwareID"] unless @_options["hardwareID"].nil? - - illuminatorOptions.simulator.device = @_options["simDevice"] unless @_options["simDevice"].nil? - illuminatorOptions.simulator.version = @_options["simVersion"] unless @_options["simVersion"].nil? - illuminatorOptions.simulator.language = @_options["simLanguage"] unless @_options["simLanguage"].nil? - illuminatorOptions.simulator.killAfter = (not @_options["skipKillAfter"]) unless @_options["skipKillAfter"].nil? - - illuminatorOptions.instruments.appLocation = @_options["appLocation"] unless @_options["appLocation"].nil? - illuminatorOptions.instruments.doVerbose = @_options["verbose"] unless @_options["verbose"].nil? - illuminatorOptions.instruments.timeout = @_options["timeout"].to_i unless @_options["timeout"].nil? - - illuminatorOptions.javascript.testPath = @_options["testPath"] unless @_options["testPath"].nil? - illuminatorOptions.javascript.implementation = @_options["implementation"] unless @_options["implementation"].nil? - - knownKeys = IlluminatorParserFactory.new.letterMap.values # get option keynames from a plain vanilla factory - - # load up unknown illuminatorOptions - illuminatorOptions.appSpecific = @_options.select { |keyname, _| not (knownKeys.include? keyname) } - - return illuminatorOptions - end - - def parse args - leftovers = super(args) - return self.copyParsedOptionsInto(IlluminatorOptions.new) - end - -end - -class IlluminatorParserFactory - - attr_reader :letterMap - - # the currency of this parser factory is the "short" single-letter argument switch - def initialize() - @options = nil - @switches = {} - - # build the list of how each parameter will be saved in the output - @letterMap = { - 'x' => 'entryPoint', - 'p' => 'testPath', - 'a' => 'appName', - 'P' => 'xcodeProject', - 't' => 'tagsAny', - 'o' => 'tagsAll', - 'n' => 'tagsNone', - 'q' => 'sdk', - 's' => 'scheme', - 'd' => 'hardwareID', - 'i' => 'implementation', - 'E' => 'appLocation', - 'b' => 'simDevice', - 'z' => 'simVersion', - 'l' => 'simLanguage', - 'f' => 'skipBuild', - 'B' => 'skipAutomate', - 'e' => 'skipSetSim', - 'k' => 'skipKillAfter', - 'c' => 'coverage', - 'r' => 'retest', - 'v' => 'verbose', - 'm' => 'timeout', - 'w' => 'randomSeed', - 'y' => 'clean', - } - - @letterProcessing = { - 'p' => lambda {|p| HostUtils.realpath(p) }, # get real path to tests file - 'E' => lambda {|p| HostUtils.realpath(p) }, # get real path to app - 'y' => lambda {|p| p.split(',')}, # split comma-separated string into array - 'r' => lambda {|p| p.split(',')}, # split comma-separated string into array - 't' => lambda {|p| p.split(',')}, # split comma-separated string into array - 'o' => lambda {|p| p.split(',')}, # split comma-separated string into array - 'n' => lambda {|p| p.split(',')}, # split comma-separated string into array - } - - @defaultValues = { - 'b' => 'iPhone 5', - 'z' => '8.2', - 'q' => 'iphonesimulator', - 'l' => 'en', - 'x' => 'runTestsByTag', - 'm' => 30, - 'f' => false, - 'B' => false, - 'e' => false, - 'k' => false, - 'c' => false, - } - end - - # you must custom prepare before you can add custom switches... otherwise things get all stupid - def prepare(defaultValues = nil, letterMapUpdates = nil, letterProcessingUpdates = nil) - @letterMap = @letterMap.merge(letterMapUpdates) unless letterMapUpdates.nil? - @letterProcessing = @letterProcessing.merge(letterProcessingUpdates) unless letterProcessingUpdates.nil? - @defaultValues = @defaultValues.merge defaultValues unless defaultValues.nil? - - self.addSwitch('x', ['-x', '--entryPoint LABEL', 'The execution entry point {runTestsByTag, runTestsByName, describe}']) - self.addSwitch('p', ['-p', '--testPath PATH', 'Path to js file with all tests imported']) - self.addSwitch('a', ['-a', '--appName APPNAME', "Name of the app to build / run"]) - self.addSwitch('P', ['-P', '--xcodeProject PROJECTNAME', "Project to build -- required if there are 2 in the same directory"]) - self.addSwitch('t', ['-t', '--tags-any TAGSANY', 'Run tests with any of the given tags']) - self.addSwitch('o', ['-o', '--tags-all TAGSALL', 'Run tests with all of the given tags']) - self.addSwitch('n', ['-n', '--tags-none TAGSNONE', 'Run tests with none of the given tags']) - self.addSwitch('q', ['-q', '--sdk SDK', 'SDK to build against']) - self.addSwitch('s', ['-s', '--scheme SCHEME', 'Build and run specific tests on given workspace scheme']) - self.addSwitch('d', ['-d', '--hardwareID ID', 'hardware id of device to run on instead of simulator']) - self.addSwitch('i', ['-i', '--implementation IMPL', 'Device tests implementation']) - self.addSwitch('E', ['-E', '--appLocation LOCATION', 'Location of app executable, if pre-built']) - self.addSwitch('b', ['-b', '--simDevice DEVICE', 'Run on given simulated device']) - self.addSwitch('z', ['-z', '--simVersion VERSION', 'Run on given simulated iOS version']) - self.addSwitch('l', ['-l', '--simLanguage LANGUAGE', 'Run on given simulated iOS language']) - self.addSwitch('f', ['-f', '--skip-build', 'Just automate; assume already built']) - self.addSwitch('B', ['-B', '--skip-automate', "Don't automate; build only"]) - self.addSwitch('e', ['-e', '--skip-set-sim', 'Assume that simulator has already been chosen and properly reset']) - self.addSwitch('k', ['-k', '--skip-kill-after', 'Leave the simulator open after the run']) - self.addSwitch('y', ['-y', '--clean PLACES', 'Comma-separated list of places to clean {xcode, buildArtifacts, derivedData}']) - self.addSwitch('c', ['-c', '--coverage', 'Generate coverage files']) - self.addSwitch('r', ['-r', '--retest OPTIONS', 'Immediately retest failed tests with comma-separated options {1x, solo}']) - self.addSwitch('v', ['-v', '--verbose', 'Show verbose output from instruments']) - self.addSwitch('m', ['-m', '--timeout TIMEOUT', 'Seconds to wait for instruments tool to start tests']) - self.addSwitch('w', ['-w', '--random-seed SEED', 'Randomize test order based on given integer seed']) - end - - # add a parse switch for the given letter key, using the given options. - # the parse action is defined by the existence of letterProcessing for the letter key, - # which by default is simple assignment - def addSwitch(letter, opts) - dest = self.getLetterDestination(letter) - - # alter opts to include the default values - altered = false - if @defaultValues[letter].nil? - opts_with_default = opts - else - opts_with_default = opts.map do |item| - if (!altered and item.chars.first != '-') - item += " :: Defaults to \"#{@defaultValues[letter]}\"" - altered = true - end - item - end - end - - @switches[letter] = OpenStruct.new(:opts => opts_with_default, - :block => lambda do |newval| - # assign the parsed value to the output, processing it if necessary - if @letterProcessing[letter] - @options[dest] = @letterProcessing[letter].call(newval) - else - @options[dest] = newval - end - end) - end - - - # letter destination defaults to the letter itself, but can be overwritten by letterMap - def getLetterDestination(letter) - return @letterMap[letter]? @letterMap[letter] : letter - end - - - # factory function - def buildParser(options, letters = nil) - @options = options - - if letters.nil? - letters = switches.keys.join('') - end - - # helpful error message for bad chars - bad_chars = letters.chars.to_a.select{|c| c != "#" and @switches[c].nil?} - raise ArgumentError, "buildParser got letters (" + letters + ") containing unknown option characters: " + bad_chars.to_s unless bad_chars.empty? - - retval = IlluminatorParser.new options - - # build a parser as specified by the user - letters.each_char do |c| - options[self.getLetterDestination(c)] = @defaultValues[c] unless @defaultValues[c].nil? - - if c == '#' - retval.separator(' ---------------------------------------------------------------------------------') - else - retval.on(*(@switches[c].send(:opts))) {|foo| @switches[c].send(:block).call(foo)} - end - end - - # help message is hard coded! - retval.on_tail('-h', '--help', 'Show this help message') {|foo| puts retval.help(); exit } - - retval.banner = "Usage: #{File.basename($PROGRAM_NAME)} [options]" - - #puts retval - return retval - end - -end diff --git a/src/scripts/classes/IlluminatorOptions.rb b/src/scripts/classes/IlluminatorOptions.rb deleted file mode 100644 index 2c5944e..0000000 --- a/src/scripts/classes/IlluminatorOptions.rb +++ /dev/null @@ -1,90 +0,0 @@ - -require 'ostruct' - -class RecursiveOpenStruct < OpenStruct - - def initialize(hash=nil) - # preprocess hash objects into openstruct objects - unless hash.nil? - hash.each do |k, v| - hash[k] = RecursiveOpenStruct.new(v) if v.is_a? Hash - end - end - - super - end - - # recursively translate the openstruct hierarchy to a hash hierarchy - def to_h - ret = super - - ret.each do |k, v| - ret[k] = v.to_h if v.is_a? RecursiveOpenStruct - end - - return ret - end -end - -class IlluminatorOptions < RecursiveOpenStruct - - def initialize(hash=nil) - super - return unless hash.nil? - - # stub out all the branches - self.xcode = RecursiveOpenStruct.new - self.instruments = RecursiveOpenStruct.new - self.simulator = RecursiveOpenStruct.new - self.javascript = RecursiveOpenStruct.new - self.illuminator = RecursiveOpenStruct.new - self.appSpecific = nil # all unknown options will go here - - self.illuminator.clean = RecursiveOpenStruct.new - self.illuminator.task = RecursiveOpenStruct.new - self.illuminator.test = RecursiveOpenStruct.new - - self.illuminator.test.tags = RecursiveOpenStruct.new - self.illuminator.test.retest = RecursiveOpenStruct.new - - # name all the keys (just for visibiilty) - self.xcode.project = nil - self.xcode.appName = nil - self.xcode.sdk = nil - self.xcode.scheme = nil - self.xcode.environmentVars = nil - - self.illuminator.entryPoint = nil - self.illuminator.test.randomSeed = nil - self.illuminator.test.tags.any = nil - self.illuminator.test.tags.all = nil - self.illuminator.test.tags.none = nil - self.illuminator.test.names = nil - self.illuminator.test.retest.attempts = nil - self.illuminator.test.retest.solo = nil - self.illuminator.clean.xcode = nil - self.illuminator.clean.derived = nil - self.illuminator.clean.artifacts = nil - self.illuminator.clean.noDelay = nil - self.illuminator.task.build = nil - self.illuminator.task.automate = nil - self.illuminator.task.setSim = nil - self.illuminator.task.coverage = nil - self.illuminator.hardwareID = nil - - self.simulator.device = nil - self.simulator.version = nil - self.simulator.language = nil - self.simulator.killAfter = nil - - self.instruments.doVerbose = nil - self.instruments.timeout = nil - self.instruments.attempts = nil - self.instruments.appLocation = nil # normally, this is where we build to - - self.javascript.testPath = nil - self.javascript.implementation = nil - self.javascript.appSpecificConfig = nil - end - -end diff --git a/src/scripts/classes/XcodeUtils.rb b/src/scripts/classes/XcodeUtils.rb deleted file mode 100644 index b42351f..0000000 --- a/src/scripts/classes/XcodeUtils.rb +++ /dev/null @@ -1,199 +0,0 @@ -require 'singleton' -require 'fileutils' - -# Convenience functions for command-line actions done in Xcode -class XcodeUtils - include Singleton - - def initialize - @xcodePath = `/usr/bin/xcode-select -print-path`.chomp.sub(/^\s+/, '') - @xcodeVersion = nil - @sdkPath = nil - @instrumentsPath = nil - @_simulatorDevicesText = nil - @simulatorDeviceTypes = nil - @simulatorRuntims = nil - end - - def getXcodePath - @xcodePath - end - - def getXcodeAppPath - HostUtils.realpath(File.join(@xcodePath, "../../")) - end - - def getXcodeSimctlPath - HostUtils.realpath(File.join(@xcodePath, "/usr/bin/simctl")) - end - - def getXcodeVersion - if @xcodeVersion.nil? - xcodeVersion = `xcodebuild -version` - needle = 'Xcode (.*)' - match = xcodeVersion.match(needle) - @xcodeVersion = match.captures[0] - end - @xcodeVersion - end - - def isXcodeMajorVersion ver - # should update this with 'version' gem - needle = '(\d+)\.?(\d+)?' - match = self.getXcodeVersion.match(needle) - return match.captures[0].to_i == ver - end - - # Get the path to the SDK - def getSdkPath - @sdkPath ||= `/usr/bin/xcodebuild -version -sdk iphoneos | grep PlatformPath`.split(':')[1].chomp.sub(/^\s+/, '') - end - - # Get the path to the instruments bundle - def getInstrumentsPath - if @instrumentsPath.nil? - if File.directory? "#{@xcodePath}/../Applications/Instruments.app/Contents/PlugIns/AutomationInstrument.xrplugin/" - @instrumentsPath = "AutomationInstrument.xrplugin"; - else - #fallback to old instruments bundle (pre Xcode6) - @instrumentsPath = "AutomationInstrument.bundle"; - end - end - @instrumentsPath - end - - # Get the path to the instruments template - def getInstrumentsTemplatePath - instrumentsFolder = self.getInstrumentsPath - "#{@xcodePath}/../Applications/Instruments.app/Contents/PlugIns/#{instrumentsFolder}/Contents/Resources/Automation.tracetemplate" - end - - def _getAllSimulatorInfo - info = `#{self.getXcodeSimctlPath} list`.split("\n") - - output = {"devices" => [], "runtimes" => []} - pointer = nil - needle = nil - - info.each do |line| - case line - when "== Device Types ==" - # all data we want is followed by " (" e.g. "iPhone 5 (com.apple.C......." - pointer = "devices" - needle = '([^(]*) ' - when "== Runtimes ==" - # all data we want is in the form "iOS 7.0 (7.0.3 - ........." and we want the 7.0 - pointer = "runtimes" - needle = 'iOS ([^(]*) ' - when "== Devices ==" - pointer = nil - needle = nil - else - unless pointer.nil? - match = line.match(needle) - if match - output[pointer] << match.captures[0] - end - end - end - end - - @simulatorDeviceTypes = output["devices"] - @simulatorRuntimes = output["runtimes"] - end - - def getSimulatorDeviceTypes - if @simulatorDeviceTypes.nil? - self._getAllSimulatorInfo - end - @simulatorDeviceTypes - end - - def getSimulatorRuntimes - if @simulatorRuntimes.nil? - self._getAllSimulatorInfo - end - @simulatorRuntimes - end - - def getSimulatorDevices - if @_simulatorDevicesText.nil? - @_simulatorDevicesText = `instruments -s devices` - end - @_simulatorDevicesText - end - - # Based on the desired device and version, get the ID of the simulator that will be passed to instruments - def getSimulatorID (simDevice, simVersion) - devices = self.getSimulatorDevices - needle = simDevice + ' \(' + simVersion + ' Simulator\) \[(.*)\]' - match = devices.match(needle) - if match - puts "Found device match: #{match}".green - return match.captures[0] - elsif - puts "Did not find UDID of device '#{simDevice}' for version '#{simVersion}'".green - if XcodeUtils.instance.isXcodeMajorVersion 5 - fallbackName = "#{simDevice} - Simulator - iOS #{simVersion}" - puts "Falling back to Xcode5 name #{fallbackName}".green - return fallbackName - end - end - - return nil - end - - def getCrashDirectory - return "#{ENV['HOME']}/Library/Logs/DiagnosticReports" - end - - # Create a crash report - def createSymbolicatedCrashReport (appPath, crashPath, crashReportPath) - # find symbolicatecrash file, which is different depending on the Xcode version (we assume either 5 or 6) - frameworksPath = "#{@xcodePath}/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks" - symbolicatorPath = "#{frameworksPath}/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash" - if not File.exist?(symbolicatorPath) - symbolicatorPath = "#{frameworksPath}/DTDeviceKit.framework/Versions/A/Resources/symbolicatecrash" - end - if not File.exist?(symbolicatorPath) - symbolicatorPath = File.join(self.getXcodeAppPath, "Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash") - end - - command = "DEVELOPER_DIR='#{@xcodePath}' " - command << "'#{symbolicatorPath}' " - command << "-o '#{crashReportPath}' '#{crashPath}' '#{appPath}.dSYM' 2>&1" - - output = `#{command}` - - # log the output of the crash reporting if the file didn't appear - unless File.exist?(crashReportPath) - puts command.green - puts output - return false - end - return true - end - - # use the provided applescript to reset the content and settings of the simulator - def resetSimulator deviceID - command = "#{self.getXcodeSimctlPath} erase #{deviceID}" - puts command.green - puts `#{command}` - - end - - # remove any apps in the specified directory - def self.removeExistingApps xcodeOutputDir - Dir["#{xcodeOutputDir}/*.app"].each do |app| - puts "XcodeUtils: removing #{app}" - FileUtils.rm_rf app - end - end - - def self.killAllSimulatorProcesses - command = HostUtils.realpath(File.join(File.dirname(__FILE__), "../kill_all_sim_processes.sh")) - puts "Running #{command}" - puts `'#{command}'` - end - -end From fdb5ef906f40210c973d49e285270b70ca03ec02 Mon Sep 17 00:00:00 2001 From: Ian Katz Date: Wed, 8 Apr 2015 16:35:16 -0400 Subject: [PATCH 10/11] Fix sample app scripts --- .travis.yml | 4 +- SampleApp/automationTests.rb | 14 +- SampleApp/rerunFailedTests.rb | 6 +- SampleApp/smokeTests.rb | 16 +-- gem/lib/illuminator.rb | 75 ++++++----- gem/lib/illuminator/argument-parsing.rb | 168 ++++++++++++------------ gem/lib/illuminator/xcode-builder.rb | 2 +- 7 files changed, 143 insertions(+), 142 deletions(-) diff --git a/.travis.yml b/.travis.yml index f000ddd..47a993a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,5 @@ language: objective-c install: bundle install --jobs=3 --retry=3 --gemfile SampleApp/Gemfile -script: ruby SampleApp/smokeTests.rb \ No newline at end of file +script: + - cd SampleApp + - ruby smokeTests.rb \ No newline at end of file diff --git a/SampleApp/automationTests.rb b/SampleApp/automationTests.rb index 1c26dac..79b1128 100644 --- a/SampleApp/automationTests.rb +++ b/SampleApp/automationTests.rb @@ -1,12 +1,9 @@ +require 'bundler/setup' +require 'illuminator' require 'pathname' -require File.join(File.expand_path(File.dirname(__FILE__)), '../src/scripts/classes/IlluminatorFramework.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), '../src/scripts/classes/IlluminatorArgumentParsing.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), '../src/scripts/classes/HostUtils.rb') - - options = {} -parserFactory = IlluminatorParserFactory.new +parserFactory = Illuminator::ParserFactory.new parserFactory.prepare({"b" => 'iPhone 5'}, # the default sim devie is iPhone 5 {}, # no extra parse flags are being defined @@ -19,11 +16,10 @@ optionStruct.xcode.appName = 'AutomatorSampleApp' optionStruct.xcode.scheme = 'AutomatorSampleApp' optionStruct.javascript.implementation = 'iPhone' -optionStruct.javascript.testPath = HostUtils.realpath('../SampleTests/tests/AllTests.js') # must be full path +optionStruct.javascript.testPath = Illuminator::HostUtils.realpath('../SampleTests/tests/AllTests.js') # must be full path -Dir.chdir 'SampleApp/AutomatorSampleApp' workspace = Dir.pwd -success = IlluminatorFramework.runWithOptions optionStruct, workspace +success = Illuminator::runWithOptions optionStruct, workspace exit 1 unless success diff --git a/SampleApp/rerunFailedTests.rb b/SampleApp/rerunFailedTests.rb index c6cc985..529c06b 100644 --- a/SampleApp/rerunFailedTests.rb +++ b/SampleApp/rerunFailedTests.rb @@ -1,13 +1,13 @@ +require 'bundler/setup' +require 'illuminator' require 'pathname' -require File.join(File.expand_path(File.dirname(__FILE__)), '/classes/IlluminatorFramework.rb') - workspace = Dir.pwd # TODO: helpful message if file isn't supplied overrideOptions = lambda {|opts| opts} -success = IlluminatorFramework.reRun(ARGV[0], workspace, overrideOptions) +success = Illuminator::.reRun(ARGV[0], workspace, overrideOptions) exit 1 unless success diff --git a/SampleApp/smokeTests.rb b/SampleApp/smokeTests.rb index 787c783..38e2451 100644 --- a/SampleApp/smokeTests.rb +++ b/SampleApp/smokeTests.rb @@ -1,18 +1,16 @@ -require File.join(File.expand_path(File.dirname(__FILE__)), '../src/scripts/classes/IlluminatorFramework.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), '../src/scripts/classes/IlluminatorOptions.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), '../src/scripts/classes/XcodeUtils.rb') -require File.join(File.expand_path(File.dirname(__FILE__)), '../src/scripts/classes/HostUtils.rb') +require 'bundler/setup' +require 'illuminator' # Change directory to sample app and use that for the workspace Dir.chdir File.join(File.expand_path(File.dirname(__FILE__)), '/AutomatorSampleApp') workspace = Dir.pwd allTestPath = '../SampleTests/tests/AllTests.js' -allTestPath = HostUtils.realpath(allTestPath) +allTestPath = Illuminator::HostUtils.realpath(allTestPath) # Hard-coded options -options = IlluminatorOptions.new +options = Illuminator::Options.new options.xcode.appName = 'AutomatorSampleApp' options.xcode.scheme = 'AutomatorSampleApp' @@ -34,17 +32,17 @@ options.javascript.testPath = allTestPath options.javascript.implementation = 'iPhone' -if XcodeUtils.instance.isXcodeMajorVersion 5 +if Illuminator::XcodeUtils.instance.isXcodeMajorVersion 5 options.simulator.device = 'iPhone Retina (4-inch)' end options.simulator.version = '8.1' -success8 = IlluminatorFramework.runWithOptions options, workspace +success8 = Illuminator::runWithOptions options, workspace options.illuminator.clean.xcode = false options.illuminator.clean.artifacts = false options.illuminator.task.build = false options.simulator.version = '7.1' -success7 = IlluminatorFramework.runWithOptions options, workspace +success7 = Illuminator::runWithOptions options, workspace exit 1 unless success7 and success8 diff --git a/gem/lib/illuminator.rb b/gem/lib/illuminator.rb index 5164354..be23faa 100644 --- a/gem/lib/illuminator.rb +++ b/gem/lib/illuminator.rb @@ -2,60 +2,63 @@ require "illuminator/automation-builder" require "illuminator/automation-runner" +require "illuminator/argument-parsing" require "illuminator/device-installer" require "illuminator/build-artifacts" require "illuminator/host-utils" require "illuminator/xcode-utils" require "illuminator/options" -class IlluminatorFramework - def self.willClean options - return true if options.illuminator.clean.derived - return true if options.illuminator.clean.artifacts - return true if options.illuminator.clean.xcode - return false - end +module Illuminator + + class Framework - def self.cleanCountdown - countdown = "3....2....1...." - print "Cleaning in ".yellow - countdown.split("").each do |c| - print c.yellow - sleep(0.2) + def self.willClean options + return true if options.illuminator.clean.derived + return true if options.illuminator.clean.artifacts + return true if options.illuminator.clean.xcode + return false + end + + def self.cleanCountdown + countdown = "3....2....1...." + print "Cleaning in ".yellow + countdown.split("").each do |c| + print c.yellow + sleep(0.2) + end + print "\n" end - print "\n" - end - def self.validateOptions(options) + def self.validateOptions(options) - # fail quickly if simulator device and/or version are wrong - if options.illuminator.hardwareID.nil? - device = options.simulator.device - version = options.simulator.version - devices = XcodeUtils.instance.getSimulatorDeviceTypes() - versions = XcodeUtils.instance.getSimulatorRuntimes() + # fail quickly if simulator device and/or version are wrong + if options.illuminator.hardwareID.nil? + device = options.simulator.device + version = options.simulator.version + devices = XcodeUtils.instance.getSimulatorDeviceTypes() + versions = XcodeUtils.instance.getSimulatorRuntimes() - noproblems = true + noproblems = true - unless devices.include? device - puts "Specified simulator device '#{device}' does not appear to be installed - options are #{devices}".red - noproblems = false - end + unless devices.include? device + puts "Specified simulator device '#{device}' does not appear to be installed - options are #{devices}".red + noproblems = false + end - unless versions.include? version - puts "Specified simulator iOS version '#{version}' does not appear to be installed - options are #{versions}".red - noproblems = false + unless versions.include? version + puts "Specified simulator iOS version '#{version}' does not appear to be installed - options are #{versions}".red + noproblems = false + end end + + return noproblems end - return noproblems end -end - -module Illuminator def self.runWithOptions(originalOptions, workspace) @@ -65,14 +68,14 @@ def self.runWithOptions(originalOptions, workspace) appName = options.xcode.appName # validate some inputs - return false unless IlluminatorFramework.validateOptions(options) + return false unless Framework.validateOptions(options) # do any initial cleaning cleanDirs = { HostUtils.realpath("~/Library/Developer/Xcode/DerivedData") => options.illuminator.clean.derived, BuildArtifacts.instance.root(true) => options.illuminator.clean.artifacts, } - IlluminatorFramework.cleanCountdown if IlluminatorFramework.willClean(options) and (not options.illuminator.clean.noDelay) + Framework.cleanCountdown if Framework.willClean(options) and (not options.illuminator.clean.noDelay) cleanDirs.each do |d, doClean| dir = HostUtils.realpath d if doClean diff --git a/gem/lib/illuminator/argument-parsing.rb b/gem/lib/illuminator/argument-parsing.rb index ef9fcf5..7ce3cd8 100644 --- a/gem/lib/illuminator/argument-parsing.rb +++ b/gem/lib/illuminator/argument-parsing.rb @@ -4,112 +4,114 @@ require_relative './options' require_relative './host-utils' +module Illuminator -class IlluminatorParser < OptionParser - def initialize options - super - @_options = options - end + class Parser < OptionParser + def initialize options + super + @_options = options + end - def checkRetestArgs - knownRetests = ["solo"] + def checkRetestArgs + knownRetests = ["solo"] - @_options["retest"] = [] if @_options["retest"].nil? + @_options["retest"] = [] if @_options["retest"].nil? - @_options["retest"].each do |r| - if knownRetests.include? r - # ok - elsif /^\d+x$/.match(r) - # ok (1x, 2x, 3x...) - else - puts "Got unknown --retest specifier '#{r}'".yellow + @_options["retest"].each do |r| + if knownRetests.include? r + # ok + elsif /^\d+x$/.match(r) + # ok (1x, 2x, 3x...) + else + puts "Got unknown --retest specifier '#{r}'".yellow + end end end - end - def getMaxRetests - ret = 0 - @_options["retest"].each do |r| - matches = /^(\d+)x$/.match(r) - unless matches.nil? - ret = [ret, matches[1].to_i].max + def getMaxRetests + ret = 0 + @_options["retest"].each do |r| + matches = /^(\d+)x$/.match(r) + unless matches.nil? + ret = [ret, matches[1].to_i].max + end end + ret end - ret - end - def checkCleanArgs - knownCleans = ["xcode", "buildArtifacts", "derivedData", "noDelay"] + def checkCleanArgs + knownCleans = ["xcode", "buildArtifacts", "derivedData", "noDelay"] - @_options["clean"] = [] if @_options["clean"].nil? + @_options["clean"] = [] if @_options["clean"].nil? - @_options["clean"].each do |c| - unless knownCleans.include? c - puts "Got unknown --clean specifier '#{c}'".yellow + @_options["clean"].each do |c| + unless knownCleans.include? c + puts "Got unknown --clean specifier '#{c}'".yellow + end end end - end - # copy internal options storage into a options object - def copyParsedOptionsInto(illuminatorOptions) - self.checkCleanArgs - self.checkRetestArgs + # copy internal options storage into a options object + def copyParsedOptionsInto(illuminatorOptions) + self.checkCleanArgs + self.checkRetestArgs - # load up known illuminatorOptions - # we only load non-nil options, just in case there was already something in the illuminatorOptions obj - illuminatorOptions.xcode.appName = @_options["appName"] unless @_options["appName"].nil? - illuminatorOptions.xcode.sdk = @_options["sdk"] unless @_options["sdk"].nil? - illuminatorOptions.xcode.scheme = @_options["scheme"] unless @_options["scheme"].nil? + # load up known illuminatorOptions + # we only load non-nil options, just in case there was already something in the illuminatorOptions obj + illuminatorOptions.xcode.appName = @_options["appName"] unless @_options["appName"].nil? + illuminatorOptions.xcode.sdk = @_options["sdk"] unless @_options["sdk"].nil? + illuminatorOptions.xcode.scheme = @_options["scheme"] unless @_options["scheme"].nil? - illuminatorOptions.illuminator.entryPoint = @_options["entryPoint"] unless @_options["entryPoint"].nil? - illuminatorOptions.illuminator.test.randomSeed = @_options["randomSeed"].to_i unless @_options["randomSeed"].nil? - illuminatorOptions.illuminator.test.tags.any = @_options["tagsAny"] unless @_options["tagsAny"].nil? - illuminatorOptions.illuminator.test.tags.all = @_options["tagsAll"] unless @_options["tagsAll"].nil? - illuminatorOptions.illuminator.test.tags.none = @_options["tagsNone"] unless @_options["tagsNone"].nil? + illuminatorOptions.illuminator.entryPoint = @_options["entryPoint"] unless @_options["entryPoint"].nil? + illuminatorOptions.illuminator.test.randomSeed = @_options["randomSeed"].to_i unless @_options["randomSeed"].nil? + illuminatorOptions.illuminator.test.tags.any = @_options["tagsAny"] unless @_options["tagsAny"].nil? + illuminatorOptions.illuminator.test.tags.all = @_options["tagsAll"] unless @_options["tagsAll"].nil? + illuminatorOptions.illuminator.test.tags.none = @_options["tagsNone"] unless @_options["tagsNone"].nil? - illuminatorOptions.illuminator.test.retest.attempts = getMaxRetests - illuminatorOptions.illuminator.test.retest.solo = @_options["retest"].include? "solo" + illuminatorOptions.illuminator.test.retest.attempts = getMaxRetests + illuminatorOptions.illuminator.test.retest.solo = @_options["retest"].include? "solo" - illuminatorOptions.illuminator.clean.xcode = @_options["clean"].include? "xcode" - illuminatorOptions.illuminator.clean.derived = @_options["clean"].include? "derivedData" - illuminatorOptions.illuminator.clean.artifacts = @_options["clean"].include? "buildArtifacts" - illuminatorOptions.illuminator.clean.noDelay = @_options["clean"].include? "noDelay" + illuminatorOptions.illuminator.clean.xcode = @_options["clean"].include? "xcode" + illuminatorOptions.illuminator.clean.derived = @_options["clean"].include? "derivedData" + illuminatorOptions.illuminator.clean.artifacts = @_options["clean"].include? "buildArtifacts" + illuminatorOptions.illuminator.clean.noDelay = @_options["clean"].include? "noDelay" - illuminatorOptions.illuminator.task.build = (not @_options["skipBuild"]) unless @_options["skipBuild"].nil? - illuminatorOptions.illuminator.task.automate = (not @_options["skipAutomate"]) unless @_options["skipAutomate"].nil? - illuminatorOptions.illuminator.task.setSim = (not @_options["skipSetSim"]) unless @_options["skipSetSim"].nil? - illuminatorOptions.illuminator.task.coverage = @_options["coverage"] unless @_options["coverage"].nil? - illuminatorOptions.illuminator.hardwareID = @_options["hardwareID"] unless @_options["hardwareID"].nil? + illuminatorOptions.illuminator.task.build = (not @_options["skipBuild"]) unless @_options["skipBuild"].nil? + illuminatorOptions.illuminator.task.automate = (not @_options["skipAutomate"]) unless @_options["skipAutomate"].nil? + illuminatorOptions.illuminator.task.setSim = (not @_options["skipSetSim"]) unless @_options["skipSetSim"].nil? + illuminatorOptions.illuminator.task.coverage = @_options["coverage"] unless @_options["coverage"].nil? + illuminatorOptions.illuminator.hardwareID = @_options["hardwareID"] unless @_options["hardwareID"].nil? - illuminatorOptions.simulator.device = @_options["simDevice"] unless @_options["simDevice"].nil? - illuminatorOptions.simulator.version = @_options["simVersion"] unless @_options["simVersion"].nil? - illuminatorOptions.simulator.language = @_options["simLanguage"] unless @_options["simLanguage"].nil? - illuminatorOptions.simulator.killAfter = (not @_options["skipKillAfter"]) unless @_options["skipKillAfter"].nil? + illuminatorOptions.simulator.device = @_options["simDevice"] unless @_options["simDevice"].nil? + illuminatorOptions.simulator.version = @_options["simVersion"] unless @_options["simVersion"].nil? + illuminatorOptions.simulator.language = @_options["simLanguage"] unless @_options["simLanguage"].nil? + illuminatorOptions.simulator.killAfter = (not @_options["skipKillAfter"]) unless @_options["skipKillAfter"].nil? - illuminatorOptions.instruments.appLocation = @_options["appLocation"] unless @_options["appLocation"].nil? - illuminatorOptions.instruments.doVerbose = @_options["verbose"] unless @_options["verbose"].nil? - illuminatorOptions.instruments.timeout = @_options["timeout"].to_i unless @_options["timeout"].nil? + illuminatorOptions.instruments.appLocation = @_options["appLocation"] unless @_options["appLocation"].nil? + illuminatorOptions.instruments.doVerbose = @_options["verbose"] unless @_options["verbose"].nil? + illuminatorOptions.instruments.timeout = @_options["timeout"].to_i unless @_options["timeout"].nil? - illuminatorOptions.javascript.testPath = @_options["testPath"] unless @_options["testPath"].nil? - illuminatorOptions.javascript.implementation = @_options["implementation"] unless @_options["implementation"].nil? + illuminatorOptions.javascript.testPath = @_options["testPath"] unless @_options["testPath"].nil? + illuminatorOptions.javascript.implementation = @_options["implementation"] unless @_options["implementation"].nil? - knownKeys = IlluminatorParserFactory.new.letterMap.values # get option keynames from a plain vanilla factory + knownKeys = Illuminator::ParserFactory.new.letterMap.values # get option keynames from a plain vanilla factory - # load up unknown illuminatorOptions - illuminatorOptions.appSpecific = @_options.select { |keyname, _| not (knownKeys.include? keyname) } + # load up unknown illuminatorOptions + illuminatorOptions.appSpecific = @_options.select { |keyname, _| not (knownKeys.include? keyname) } - return illuminatorOptions - end + return illuminatorOptions + end + + def parse args + leftovers = super(args) + return self.copyParsedOptionsInto(Illuminator::Options.new) + end - def parse args - leftovers = super(args) - return self.copyParsedOptionsInto(IlluminatorOptions.new) end -end -module Illuminator + class ParserFactory attr_reader :letterMap @@ -149,13 +151,13 @@ def initialize() } @letterProcessing = { - 'p' => lambda {|p| HostUtils.realpath(p) }, # get real path to tests file - 'E' => lambda {|p| HostUtils.realpath(p) }, # get real path to app - 'y' => lambda {|p| p.split(',')}, # split comma-separated string into array - 'r' => lambda {|p| p.split(',')}, # split comma-separated string into array - 't' => lambda {|p| p.split(',')}, # split comma-separated string into array - 'o' => lambda {|p| p.split(',')}, # split comma-separated string into array - 'n' => lambda {|p| p.split(',')}, # split comma-separated string into array + 'p' => lambda {|p| Illuminator::HostUtils.realpath(p) }, # get real path to tests file + 'E' => lambda {|p| Illuminator::HostUtils.realpath(p) }, # get real path to app + 'y' => lambda {|p| p.split(',')}, # split comma-separated string into array + 'r' => lambda {|p| p.split(',')}, # split comma-separated string into array + 't' => lambda {|p| p.split(',')}, # split comma-separated string into array + 'o' => lambda {|p| p.split(',')}, # split comma-separated string into array + 'n' => lambda {|p| p.split(',')}, # split comma-separated string into array } @defaultValues = { @@ -256,7 +258,7 @@ def buildParser(options, letters = nil) bad_chars = letters.chars.to_a.select{|c| c != "#" and @switches[c].nil?} raise ArgumentError, "buildParser got letters (" + letters + ") containing unknown option characters: " + bad_chars.to_s unless bad_chars.empty? - retval = IlluminatorParser.new options + retval = Illuminator::Parser.new options # build a parser as specified by the user letters.each_char do |c| diff --git a/gem/lib/illuminator/xcode-builder.rb b/gem/lib/illuminator/xcode-builder.rb index 98a90ad..0890dea 100644 --- a/gem/lib/illuminator/xcode-builder.rb +++ b/gem/lib/illuminator/xcode-builder.rb @@ -77,7 +77,7 @@ def _buildCommand command << 'xcodebuild' command << parameters << environmentVars << tasks command << " | tee '#{self.logfilePath}'" - command << " | xcpretty -c -r junit" unless HostUtils.which("xcpretty").nil? # use xcpretty if available + command << " | xcpretty -c -r junit" unless Illuminator::HostUtils.which("xcpretty").nil? # use xcpretty if available command << ' && exit ${PIPESTATUS[0]}' unless usePipefail command From 7899c41b884d9d95bcd6111abcb06566725aef9f Mon Sep 17 00:00:00 2001 From: Ian Katz Date: Wed, 8 Apr 2015 16:49:21 -0400 Subject: [PATCH 11/11] Try lower bundler version for Travis --- illuminator.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/illuminator.gemspec b/illuminator.gemspec index 30bdf7c..2d11d0b 100644 --- a/illuminator.gemspec +++ b/illuminator.gemspec @@ -22,7 +22,7 @@ Gem::Specification.new do |spec| # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com' to prevent pushes to rubygems.org, or delete to allow pushes to any server." end - spec.add_development_dependency "bundler", "~> 1.9" + spec.add_development_dependency "bundler", ">= 1.3.6" spec.add_development_dependency "rake", "~> 10.0" spec.add_runtime_dependency "json"