snapshot/lib/snapshot/test_command_generator.rb in fastlane-2.54.0.beta.20170822010003 vs snapshot/lib/snapshot/test_command_generator.rb in fastlane-2.54.0
- old
+ new
@@ -1,134 +1,66 @@
+require 'snapshot/test_command_generator_base'
+
module Snapshot
# Responsible for building the fully working xcodebuild command
- class TestCommandGenerator
+ # Xcode 9 introduced the ability to run tests in parallel on multiple simulators
+ # This TestCommandGenerator constructs the appropriate `xcodebuild` command
+ # to be used for executing simultaneous tests
+ class TestCommandGenerator < TestCommandGeneratorBase
class << self
- def generate(device_type: nil, language: nil, locale: nil)
+ def generate(devices: nil, language: nil, locale: nil, log_path: nil)
parts = prefix
parts << "xcodebuild"
parts += options
- parts += destination(device_type)
+ parts += destination(devices)
parts += build_settings
parts += actions
parts += suffix
- parts += pipe(device_type, language, locale)
+ parts += pipe(language: language, locale: locale, log_path: log_path)
- parts
+ return parts
end
- def prefix
- ["set -o pipefail &&"]
+ def pipe(language: nil, locale: nil, log_path: nil)
+ tee_command = ['tee']
+ tee_command << '-a' if log_path && File.exist?(log_path)
+ tee_command << log_path.shellescape if log_path
+ return ["| #{tee_command.join(' ')} | xcpretty #{Snapshot.config[:xcpretty_args]}"]
end
- # Path to the project or workspace as parameter
- # This will also include the scheme (if given)
- # @return [Array] The array with all the components to join
- def project_path_array
- proj = Snapshot.project.xcodebuild_parameters
- return proj if proj.count > 0
- UI.user_error!("No project/workspace found")
- end
-
- def options
- config = Snapshot.config
-
- options = []
- options += project_path_array
- options << "-sdk '#{config[:sdk]}'" if config[:sdk]
- options << "-derivedDataPath '#{derived_data_path}'"
- options << config[:xcargs] if config[:xcargs]
- options
- end
-
- def build_settings
- config = Snapshot.config
-
- build_settings = []
- build_settings << "FASTLANE_SNAPSHOT=YES"
- build_settings << "TEST_TARGET_NAME=#{config[:test_target_name].shellescape}" if config[:test_target_name]
-
- build_settings
- end
-
- def actions
- actions = []
- actions << :clean if Snapshot.config[:clean]
- actions << :build # https://github.com/fastlane/snapshot/issues/246
- actions << :test
-
- actions
- end
-
- def suffix
- []
- end
-
- def pipe(device_type, language, locale)
- log_path = xcodebuild_log_path(device_type: device_type, language: language, locale: locale)
- ["| tee #{log_path.shellescape} | xcpretty #{Snapshot.config[:xcpretty_args]}"]
- end
-
- def find_device(device_name, os_version = Snapshot.config[:ios_version])
- # We might get this error message
- # > The requested device could not be found because multiple devices matched the request.
- #
- # This happens when you have multiple simulators for a given device type / iOS combination
- # { platform:iOS Simulator, id:1685B071-AFB2-4DC1-BE29-8370BA4A6EBD, OS:9.0, name:iPhone 5 }
- # { platform:iOS Simulator, id:A141F23B-96B3-491A-8949-813B376C28A7, OS:9.0, name:iPhone 5 }
- #
- simulators = FastlaneCore::DeviceManager.simulators
- # Sort devices with matching names by OS version, largest first, so that we can
- # pick the device with the newest OS in case an exact OS match is not available
- name_matches = simulators.find_all { |sim| sim.name.strip == device_name.strip }
- .sort_by { |sim| Gem::Version.new(sim.os_version) }
- .reverse
- name_matches.find { |sim| sim.os_version == os_version } || name_matches.first
- end
-
- def device_udid(device_name, os_version = Snapshot.config[:ios_version])
- device = find_device(device_name, os_version)
-
- device ? device.udid : nil
- end
-
- def destination(device_name)
+ def destination(devices)
+ unless verify_devices_share_os(devices)
+ UI.user_error!('All devices provided to snapshot should run the same operating system')
+ end
# on Mac we will always run on host machine, so should specify only platform
- return ["-destination 'platform=macOS'"] if device_name =~ /^Mac/
+ return ["-destination 'platform=macOS'"] if devices.first.to_s =~ /^Mac/
- os = device_name =~ /^Apple TV/ ? "tvOS" : "iOS"
+ os = devices.first.to_s =~ /^Apple TV/ ? "tvOS" : "iOS"
+
os_version = Snapshot.config[:ios_version] || Snapshot::LatestOsVersion.version(os)
- device = find_device(device_name, os_version)
- if device.nil?
- UI.user_error!("No device found named '#{device_name}' for version '#{os_version}'")
- return
- elsif device.os_version != os_version
- UI.important("Using device named '#{device_name}' with version '#{device.os_version}' because no match was found for version '#{os_version}'")
+ destinations = devices.map do |d|
+ device = find_device(d, os_version)
+ UI.user_error!("No device found named '#{d}' for version '#{os_version}'") if device.nil?
+ "-destination 'platform=#{os} Simulator,name=#{device.name},OS=#{os_version}'"
end
- value = "platform=#{os} Simulator,id=#{device.udid},OS=#{os_version}"
- return ["-destination '#{value}'"]
+ return [destinations.join(' ')]
end
- def xcodebuild_log_path(device_type: nil, language: nil, locale: nil)
- name_components = [Snapshot.project.app_name, Snapshot.config[:scheme]]
-
- if Snapshot.config[:namespace_log_files]
- name_components << device_type if device_type
- name_components << language if language
- name_components << locale if locale
+ def verify_devices_share_os(devices)
+ # Check each device to see if it is an iOS device
+ all_ios = devices.map do |device|
+ device = device.downcase
+ device.start_with?('iphone', 'ipad')
end
-
- file_name = "#{name_components.join('-')}.log"
-
- containing = File.expand_path(Snapshot.config[:buildlog_path])
- FileUtils.mkdir_p(containing)
-
- return File.join(containing, file_name)
- end
-
- def derived_data_path
- Snapshot.cache[:derived_data_path] ||= (Snapshot.config[:derived_data_path] || Dir.mktmpdir("snapshot_derived"))
+ # Return true if all devices are iOS devices
+ return true unless all_ios.include?(false)
+ # There should only be more than 1 device type if
+ # it is iOS, therefore, if there is more than 1
+ # device in the array, and they are not all iOS
+ # as checked above, that would imply that this is a mixed bag
+ return devices.count == 1
end
end
end
end