lib/slather/project.rb in slather-2.0.2 vs lib/slather/project.rb in slather-2.1.0

- old
+ new

@@ -49,29 +49,43 @@ module Slather class Project < Xcodeproj::Project attr_accessor :build_directory, :ignore_list, :ci_service, :coverage_service, :coverage_access_token, :source_directory, - :output_directory, :xcodeproj, :show_html, :verbose_mode, :input_format, :scheme, :binary_file, :binary_basename + :output_directory, :xcodeproj, :show_html, :verbose_mode, :input_format, :scheme, :workspace, :binary_file, :binary_basename alias_method :setup_for_coverage, :slather_setup_for_coverage def self.open(xcodeproj) proj = super proj.xcodeproj = xcodeproj proj end + def failure_help_string + "\n\tAre you sure your project is generating coverage? Make sure you enable code coverage in the Test section of your Xcode scheme.\n\tDid you specify your Xcode scheme? (--scheme or 'scheme' in .slather.yml)\n\tIf you're using a workspace, did you specify it? (--workspace or 'workspace' in .slather.yml)" + end + def derived_data_path # Get the derived data path from xcodebuild # Use OBJROOT when possible, as it provides regardless of whether or not the Derived Data location is customized + if self.workspace + projectOrWorkspaceArgument = "-workspace \"#{self.workspace}\"" + else + projectOrWorkspaceArgument = "-project \"#{self.path}\"" + end + if self.scheme - build_settings = `xcodebuild -project "#{self.path}" -scheme "#{self.scheme}" -showBuildSettings` + schemeArgument = "-scheme \"#{self.scheme}\"" + buildAction = "test" else - build_settings = `xcodebuild -project "#{self.path}" -showBuildSettings` + schemeArgument = nil + buildAction = nil end + build_settings = `xcodebuild #{projectOrWorkspaceArgument} #{schemeArgument} -showBuildSettings #{buildAction}` + if build_settings derived_data_path = build_settings.match(/ OBJROOT = (.+)/)[1] end if derived_data_path == nil @@ -97,11 +111,11 @@ # If there's no source file for this gcno, it probably belongs to another project. coverage_file.source_file_pathname && !coverage_file.ignored? ? coverage_file : nil end.compact if coverage_files.empty? - raise StandardError, "No coverage files found. Are you sure your project is setup for generating coverage files? Try `slather setup your/project.xcodeproj`" + raise StandardError, "No coverage files found." else dedupe(coverage_files) end end private :gcov_coverage_files @@ -139,11 +153,11 @@ if dir == nil # Xcode 7.3 moved the location of Coverage.profdata dir = Dir[File.join("#{build_directory}","/**/CodeCoverage")].first end - raise StandardError, "No coverage directory found. Are you sure your project is setup for generating coverage files? Try `slather setup your/project.xcodeproj`" unless dir != nil + raise StandardError, "No coverage directory found." unless dir != nil dir end def profdata_file profdata_coverage_dir = self.profdata_coverage_dir @@ -191,20 +205,28 @@ def self.yml @yml ||= File.exist?(yml_filename) ? YAML.load_file(yml_filename) : {} end def configure - configure_build_directory - configure_ignore_list - configure_ci_service - configure_coverage_access_token - configure_coverage_service - configure_source_directory - configure_output_directory - configure_input_format - configure_scheme - configure_binary_file + begin + configure_scheme + configure_workspace + configure_build_directory + configure_ignore_list + configure_ci_service + configure_coverage_access_token + configure_coverage_service + configure_source_directory + configure_output_directory + configure_input_format + configure_binary_file + rescue => e + puts e.message + puts failure_help_string + puts "\n" + raise + end if self.verbose_mode puts "\nProcessing coverage file: #{profdata_file}" puts "Against binary file: #{self.binary_file}\n\n" end @@ -248,10 +270,14 @@ def configure_scheme self.scheme ||= self.class.yml["scheme"] if self.class.yml["scheme"] end + def configure_workspace + self.workspace ||= self.class.yml["workspace"] if self.class.yml["workspace"] + end + def ci_service=(service) @ci_service = service && service.to_sym end def configure_coverage_service @@ -299,13 +325,26 @@ # Get scheme info out of the xcodeproj if self.scheme schemes_path = Xcodeproj::XCScheme.shared_data_dir(self.path) xcscheme_path = "#{schemes_path + self.scheme}.xcscheme" + + raise StandardError, "No shared scheme named '#{self.scheme}' found in #{self.path}" unless File.exists? xcscheme_path + xcscheme = Xcodeproj::XCScheme.new(xcscheme_path) - buildable_name = xcscheme.build_action.entries[0].buildable_references[0].buildable_name + begin + buildable_name = xcscheme.build_action.entries[0].buildable_references[0].buildable_name + rescue + # xcodeproj will raise an exception if there are no entries in the build action + end + + if buildable_name == nil or buildable_name.end_with? ".a" + # Can't run code coverage on static libraries, look for an associated test bundle + buildable_name = xcscheme.test_action.testables[0].buildable_references[0].buildable_name + end + configuration = xcscheme.test_action.build_configuration search_for = binary_basename || buildable_name found_product = Dir["#{profdata_coverage_dir}/Products/#{configuration}*/#{search_for}*"].sort { |x, y| # Sort the matches without the file extension to ensure better matches when there are multiple candidates @@ -342,12 +381,11 @@ else found_binary = find_binary_file_in_bundle(xctest_bundle) end end - raise StandardError, "No product binary found in #{profdata_coverage_dir}. Are you sure your project is setup for generating coverage files? Try `slather setup your/project.xcodeproj`" unless found_binary != nil + raise StandardError, "No product binary found in #{profdata_coverage_dir}." unless found_binary != nil found_binary end - end end