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