slather 2.0.1 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5346e7ae5cba9037d3f9386b52acbdf4a4b40c91
4
- data.tar.gz: c6c6736662bc1f1f2730cf4fc351e131687b6d92
3
+ metadata.gz: c3091b591850a4c53ba0f5d19fea4f62b01f833e
4
+ data.tar.gz: dc3b6ed662c319e4d3cb7f0abd463ab80047ad8d
5
5
  SHA512:
6
- metadata.gz: ecd69108753a0d5bc1fd1cb0b89a6d1a98b970a26f29d1af4e7cef63a1b19c9b197212e01828da90a03f85c5a5ae5856c73dbef9959f5b5eaf448caf3c38b1e3
7
- data.tar.gz: bf38de9f006be3f6ec9ad966435ecb45ace99bc716a483a7eba1b6c0b69294b7f5409aeaa0a88f57a6bfda45846357e15ebbbecebcd7f4cda12128df59f84704
6
+ metadata.gz: b9abc7f87812d4f98fff3bbc4f90fa04c68516885b187fe5d6a60066b3084e814059de68d418b7c971af219d16aedc7acdc24f8526e0ce56a98070872ea32000
7
+ data.tar.gz: b3eac9e758b90f7b74e3cc3280ec4d9b21c668f1b6249d2568d89d411815054d4210e644ed7a0619c52f767af601f354e682ca059d898bee7e233257564faf48
data/.gitignore CHANGED
@@ -44,3 +44,6 @@ cobertura.xml
44
44
  html
45
45
  *.gcda
46
46
  *.gcno
47
+
48
+ # JetBrains IDE
49
+ .idea/
@@ -1,6 +1,6 @@
1
1
  language: objective-c
2
2
  script: bundle exec rake
3
- osx_image: xcode7
3
+ osx_image: xcode7.3
4
4
 
5
5
  # Sets Travis to run the Ruby specs on OS X machines which are required to
6
6
  # build the native extensions of Xcodeproj.
@@ -2,9 +2,37 @@
2
2
 
3
3
  ## master
4
4
 
5
+
6
+
7
+ ## v2.0.2
8
+
9
+ * Escape the link to file names properly
10
+ [Thomas Mellenthin](https://github.com/melle)
11
+ [#158](https://github.com/SlatherOrg/slather/pull/158)
12
+
13
+ * Product info is now read from schemes. Specify a scheme in `.slather.yml` or with the `--scheme` argument to ensure consistent results. Automatically detect the derived data directory from `xcodebuild`
14
+ [Kent Sutherland](https://github.com/ksuther)
15
+ [#174](https://github.com/SlatherOrg/slather/pull/174)
16
+
17
+ * Xcode 7.3 compatibility (updated path returned by `profdata_coverage_dir`)
18
+ [Kent Sutherland](https://github.com/ksuther)
19
+ [#125](https://github.com/SlatherOrg/slather/issues/125), [#169](https://github.com/SlatherOrg/slather/pull/169)
20
+
21
+ * Improve matching of xctest bundles when using `--binary-basename`
22
+ [Kent Sutherland](https://github.com/ksuther)
23
+ [#167](https://github.com/SlatherOrg/slather/pull/167)
24
+
25
+ * Build Statistic Reporting for TeamCity
26
+ [Michael Myers](https://github.com/michaelmyers)
27
+ [#150](https://github.com/SlatherOrg/slather/pull/150)
28
+
29
+ * Use named classes for subcommands in bin/slather
30
+ [bootstraponline](https://github.com/bootstraponline)
31
+ [#170](https://github.com/SlatherOrg/slather/pull/170)
32
+
5
33
  ## v2.0.1
6
34
 
7
- * Fixes how `profdata_coverage_dir` is created.
35
+ * Fixes how `profdata_coverage_dir` is created.
8
36
  [guidomb](https://github.com/guidomb)
9
37
  [#145](https://github.com/SlatherOrg/slather/pull/145)
10
38
 
data/README.md CHANGED
@@ -174,6 +174,14 @@ $ slather coverage --html path/to/project.xcodeproj
174
174
 
175
175
  This will make a directory named `html` in your root directory (unless `--output-directory` is specified) and will generate all the reports as static html pages inside the directory. It will print out the report's path by default, but you can also specify `--show` flag to open it in your browser automatically.
176
176
 
177
+ ### TeamCity Reporting
178
+
179
+ To report the coverage statistics to TeamCity:
180
+
181
+ ```sh
182
+ $ slather coverage --teamcity -s
183
+ ```
184
+
177
185
  ### Coverage for code included via CocoaPods
178
186
 
179
187
  If you're trying to compute the coverage of code that has been included via
@@ -1,156 +1,15 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'clamp'
3
3
  require 'yaml'
4
- require File.join(File.dirname(__FILE__), '../lib/slather')
5
-
6
- Clamp do
4
+ require_relative '../lib/slather'
5
+ require_relative '../lib/slather/command/coverage_command'
6
+ require_relative '../lib/slather/command/setup_command'
7
7
 
8
+ class MainCommand < Clamp::Command
8
9
  self.default_subcommand = "coverage"
9
10
 
10
- subcommand "coverage", "Computes coverage for the supplied project" do
11
-
12
- parameter "[PROJECT]", "Path to the xcodeproj", :attribute_name => :xcodeproj_path
13
-
14
- option ["--travis", "-t"], :flag, "Indicate that the builds are running on Travis CI"
15
- option ["--circleci"], :flag, "Indicate that the builds are running on CircleCI"
16
- option ["--jenkins"], :flag, "Indicate that the builds are running on Jenkins"
17
- option ["--buildkite"], :flag, "Indicate that the builds are running on Buildkite"
18
-
19
- option ["--coveralls", "-c"], :flag, "Post coverage results to coveralls"
20
- option ["--simple-output", "-s"], :flag, "Output coverage results to the terminal"
21
- option ["--gutter-json", "-g"], :flag, "Output coverage results as Gutter JSON format"
22
- option ["--cobertura-xml", "-x"], :flag, "Output coverage results as Cobertura XML format"
23
- option ["--html"], :flag, "Output coverage results as static html pages"
24
- option ["--show"], :flag, "Indicate that the static html pages will open automatically"
25
-
26
- option ["--build-directory", "-b"], "BUILD_DIRECTORY", "The directory where gcno files will be written to. Defaults to derived data."
27
- option ["--source-directory"], "SOURCE_DIRECTORY", "The directory where your source files are located."
28
- option ["--output-directory"], "OUTPUT_DIRECTORY", "The directory where your Cobertura XML report will be written to."
29
- option ["--ignore", "-i"], "IGNORE", "ignore files conforming to a path", :multivalued => true
30
- option ["--verbose", "-v"], :flag, "Enable verbose mode"
31
-
32
- option ["--input-format"], "INPUT_FORMAT", "Input format (gcov, profdata)"
33
- option ["--scheme"], "SCHEME", "The scheme for which the coverage was generated"
34
- option ["--binary-file"], "BINARY_FILE", "The binary file against the which the coverage will be run"
35
- option ["--binary-basename"], "BINARY_BASENAME", "Basename of the file against which the coverage will be run"
36
-
37
- def execute
38
- puts "Slathering..."
39
-
40
- setup_service_name
41
- setup_ignore_list
42
- setup_build_directory
43
- setup_source_directory
44
- setup_output_directory
45
- setup_coverage_service
46
- setup_verbose_mode
47
- setup_input_format
48
- setup_scheme
49
- setup_binary_file
50
- setup_binary_basename
51
-
52
- project.configure
53
-
54
- post
55
-
56
- puts "Slathered"
57
- end
58
-
59
- def setup_build_directory
60
- project.build_directory = build_directory if build_directory
61
- end
62
-
63
- def setup_source_directory
64
- project.source_directory = source_directory if source_directory
65
- end
66
-
67
- def setup_output_directory
68
- project.output_directory = output_directory if output_directory
69
- end
70
-
71
- def setup_ignore_list
72
- project.ignore_list = ignore_list if !ignore_list.empty?
73
- end
74
-
75
- def setup_service_name
76
- if travis?
77
- project.ci_service = :travis_ci
78
- elsif circleci?
79
- project.ci_service = :circleci
80
- elsif jenkins?
81
- project.ci_service = :jenkins
82
- elsif buildkite?
83
- project.ci_service = :buildkite
84
- end
85
- end
86
-
87
- def post
88
- project.post
89
- end
90
-
91
- def project
92
- @project ||= begin
93
- xcodeproj_path_to_open = xcodeproj_path || Slather::Project.yml["xcodeproj"]
94
- if xcodeproj_path_to_open
95
- project = Slather::Project.open(xcodeproj_path_to_open)
96
- else
97
- raise StandardError, "Must provide an xcodeproj either via the 'slather [SUBCOMMAND] [PROJECT].xcodeproj' command or through .slather.yml"
98
- end
99
- end
100
- end
101
-
102
- def setup_coverage_service
103
- if coveralls?
104
- project.coverage_service = :coveralls
105
- elsif simple_output?
106
- project.coverage_service = :terminal
107
- elsif gutter_json?
108
- project.coverage_service = :gutter_json
109
- elsif cobertura_xml?
110
- project.coverage_service = :cobertura_xml
111
- elsif html?
112
- project.coverage_service = :html
113
- project.show_html = show?
114
- end
115
- end
116
-
117
- def setup_verbose_mode
118
- project.verbose_mode = verbose?
119
- end
120
-
121
- def setup_input_format
122
- project.input_format = input_format
123
- end
124
-
125
- def setup_scheme
126
- project.scheme = scheme
127
- end
128
-
129
- def setup_binary_file
130
- project.binary_file = binary_file
131
- end
132
-
133
- def setup_binary_basename
134
- project.binary_basename = binary_basename
135
- end
136
-
137
- end
138
-
139
- subcommand "setup", "Configures a .xcodeproj for test coverage generation" do
140
-
141
- parameter "[PROJECT]", "Path to the .xcodeproj", :attribute_name => :xcodeproj_path
142
-
143
- option ["--format"], "FORMAT", "Type of coverage to use (gcov, clang, auto)"
144
-
145
- def execute
146
- xcodeproj_path_to_open = xcodeproj_path || Slather::Project.yml["xcodeproj"]
147
- unless xcodeproj_path_to_open
148
- raise StandardError, "Must provide a .xcodeproj either via the 'slather [SUBCOMMAND] [PROJECT].xcodeproj' command or through .slather.yml"
149
- end
150
- project = Slather::Project.open(xcodeproj_path_to_open)
151
- project.setup_for_coverage(format ? format.to_sym : :auto)
152
- project.save
153
- end
154
-
155
- end
11
+ subcommand "setup", "Configures a .xcodeproj for test coverage generation", SetupCommand
12
+ subcommand "coverage", "Computes coverage for the supplied project", CoverageCommand
156
13
  end
14
+
15
+ MainCommand.run
@@ -0,0 +1,127 @@
1
+ class CoverageCommand < Clamp::Command
2
+
3
+ parameter "[PROJECT]", "Path to the xcodeproj", :attribute_name => :xcodeproj_path
4
+
5
+ option ["--travis", "-t"], :flag, "Indicate that the builds are running on Travis CI"
6
+ option ["--circleci"], :flag, "Indicate that the builds are running on CircleCI"
7
+ option ["--jenkins"], :flag, "Indicate that the builds are running on Jenkins"
8
+ option ["--buildkite"], :flag, "Indicate that the builds are running on Buildkite"
9
+
10
+ option ["--coveralls", "-c"], :flag, "Post coverage results to coveralls"
11
+ option ["--simple-output", "-s"], :flag, "Output coverage results to the terminal"
12
+ option ["--gutter-json", "-g"], :flag, "Output coverage results as Gutter JSON format"
13
+ option ["--cobertura-xml", "-x"], :flag, "Output coverage results as Cobertura XML format"
14
+ option ["--html"], :flag, "Output coverage results as static html pages"
15
+ option ["--show"], :flag, "Indicate that the static html pages will open automatically"
16
+
17
+ option ["--build-directory", "-b"], "BUILD_DIRECTORY", "The directory where gcno files will be written to. Defaults to derived data."
18
+ option ["--source-directory"], "SOURCE_DIRECTORY", "The directory where your source files are located."
19
+ option ["--output-directory"], "OUTPUT_DIRECTORY", "The directory where your Cobertura XML report will be written to."
20
+ option ["--ignore", "-i"], "IGNORE", "ignore files conforming to a path", :multivalued => true
21
+ option ["--verbose", "-v"], :flag, "Enable verbose mode"
22
+
23
+ option ["--input-format"], "INPUT_FORMAT", "Input format (gcov, profdata)"
24
+ option ["--scheme"], "SCHEME", "The scheme for which the coverage was generated"
25
+ option ["--binary-file"], "BINARY_FILE", "The binary file against the which the coverage will be run"
26
+ option ["--binary-basename"], "BINARY_BASENAME", "Basename of the file against which the coverage will be run"
27
+
28
+ def execute
29
+ puts "Slathering..."
30
+
31
+ setup_service_name
32
+ setup_ignore_list
33
+ setup_build_directory
34
+ setup_source_directory
35
+ setup_output_directory
36
+ setup_coverage_service
37
+ setup_verbose_mode
38
+ setup_input_format
39
+ setup_scheme
40
+ setup_binary_file
41
+ setup_binary_basename
42
+
43
+ project.configure
44
+
45
+ post
46
+
47
+ puts "Slathered"
48
+ end
49
+
50
+ def setup_build_directory
51
+ project.build_directory = build_directory if build_directory
52
+ end
53
+
54
+ def setup_source_directory
55
+ project.source_directory = source_directory if source_directory
56
+ end
57
+
58
+ def setup_output_directory
59
+ project.output_directory = output_directory if output_directory
60
+ end
61
+
62
+ def setup_ignore_list
63
+ project.ignore_list = ignore_list if !ignore_list.empty?
64
+ end
65
+
66
+ def setup_service_name
67
+ if travis?
68
+ project.ci_service = :travis_ci
69
+ elsif circleci?
70
+ project.ci_service = :circleci
71
+ elsif jenkins?
72
+ project.ci_service = :jenkins
73
+ elsif buildkite?
74
+ project.ci_service = :buildkite
75
+ end
76
+ end
77
+
78
+ def post
79
+ project.post
80
+ end
81
+
82
+ def project
83
+ @project ||= begin
84
+ xcodeproj_path_to_open = xcodeproj_path || Slather::Project.yml["xcodeproj"]
85
+ if xcodeproj_path_to_open
86
+ project = Slather::Project.open(xcodeproj_path_to_open)
87
+ else
88
+ raise StandardError, "Must provide an xcodeproj either via the 'slather [SUBCOMMAND] [PROJECT].xcodeproj' command or through .slather.yml"
89
+ end
90
+ end
91
+ end
92
+
93
+ def setup_coverage_service
94
+ if coveralls?
95
+ project.coverage_service = :coveralls
96
+ elsif simple_output?
97
+ project.coverage_service = :terminal
98
+ elsif gutter_json?
99
+ project.coverage_service = :gutter_json
100
+ elsif cobertura_xml?
101
+ project.coverage_service = :cobertura_xml
102
+ elsif html?
103
+ project.coverage_service = :html
104
+ project.show_html = show?
105
+ end
106
+ end
107
+
108
+ def setup_verbose_mode
109
+ project.verbose_mode = verbose?
110
+ end
111
+
112
+ def setup_input_format
113
+ project.input_format = input_format
114
+ end
115
+
116
+ def setup_scheme
117
+ project.scheme = scheme
118
+ end
119
+
120
+ def setup_binary_file
121
+ project.binary_file = binary_file
122
+ end
123
+
124
+ def setup_binary_basename
125
+ project.binary_basename = binary_basename
126
+ end
127
+ end
@@ -0,0 +1,15 @@
1
+ class SetupCommand < Clamp::Command
2
+ parameter "[PROJECT]", "Path to the .xcodeproj", :attribute_name => :xcodeproj_path
3
+
4
+ option ["--format"], "FORMAT", "Type of coverage to use (gcov, clang, auto)"
5
+
6
+ def execute
7
+ xcodeproj_path_to_open = xcodeproj_path || Slather::Project.yml["xcodeproj"]
8
+ unless xcodeproj_path_to_open
9
+ raise StandardError, "Must provide a .xcodeproj either via the 'slather [SUBCOMMAND] [PROJECT].xcodeproj' command or through .slather.yml"
10
+ end
11
+ project = Slather::Project.open(xcodeproj_path_to_open)
12
+ project.setup_for_coverage(format ? format.to_sym : :auto)
13
+ project.save
14
+ end
15
+ end
@@ -1,4 +1,5 @@
1
1
  require 'nokogiri'
2
+ require "cgi"
2
3
 
3
4
  module Slather
4
5
  module CoverageService
@@ -99,7 +100,7 @@ module Slather
99
100
  cov.tbody(:class => "list") {
100
101
  coverage_files.each { |coverage_file|
101
102
  filename = File.basename(coverage_file.source_file_pathname_relative_to_repo_root)
102
- filename_link = "#{filename}.html"
103
+ filename_link = CGI.escape(filename) + ".html"
103
104
 
104
105
  cov.tr {
105
106
  percentage = coverage_file.percentage_lines_tested
@@ -26,6 +26,22 @@ module Slather
26
26
 
27
27
  puts "#{coverage_file.source_file_pathname_relative_to_repo_root}: #{lines_tested} of #{total_lines} lines (#{percentage}%)"
28
28
  end
29
+
30
+ # check if there needs to be custom reporting based on the ci service
31
+ if ci_service == :teamcity
32
+ # TeamCity Build Statistic Reporting
33
+ #
34
+ # Reporting format ##teamcity[buildStatisticValue key='<valueTypeKey>' value='<value>']
35
+ # key='CodeCoverageAbsLCovered' is total number of lines covered
36
+ # key='CodeCoverageAbsLTotal' is total number of lines
37
+ #
38
+ # Sources:
39
+ # - https://confluence.jetbrains.com/display/TCDL/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ReportingBuildStatistics
40
+ # - https://confluence.jetbrains.com/display/TCDL/Custom+Chart#CustomChart-listOfDefaultStatisticValues
41
+ puts "##teamcity[buildStatisticValue key='CodeCoverageAbsLCovered' value='%i']" % total_project_lines_tested
42
+ puts "##teamcity[buildStatisticValue key='CodeCoverageAbsLTotal' value='%i']" % total_project_lines
43
+ end
44
+
29
45
  total_percentage = '%.2f' % [(total_project_lines_tested / total_project_lines.to_f) * 100.0]
30
46
  puts "Test Coverage: #{total_percentage}%"
31
47
  end
@@ -62,7 +62,23 @@ module Slather
62
62
  end
63
63
 
64
64
  def derived_data_path
65
- File.expand_path('~') + "/Library/Developer/Xcode/DerivedData/"
65
+ # Get the derived data path from xcodebuild
66
+ # Use OBJROOT when possible, as it provides regardless of whether or not the Derived Data location is customized
67
+ if self.scheme
68
+ build_settings = `xcodebuild -project "#{self.path}" -scheme "#{self.scheme}" -showBuildSettings`
69
+ else
70
+ build_settings = `xcodebuild -project "#{self.path}" -showBuildSettings`
71
+ end
72
+
73
+ if build_settings
74
+ derived_data_path = build_settings.match(/ OBJROOT = (.+)/)[1]
75
+ end
76
+
77
+ if derived_data_path == nil
78
+ derived_data_path = File.expand_path('~') + "/Library/Developer/Xcode/DerivedData/"
79
+ end
80
+
81
+ derived_data_path
66
82
  end
67
83
  private :derived_data_path
68
84
 
@@ -120,6 +136,11 @@ module Slather
120
136
  dir = Dir[File.join("#{build_directory}","/**/#{first_product_name}")].first
121
137
  end
122
138
 
139
+ if dir == nil
140
+ # Xcode 7.3 moved the location of Coverage.profdata
141
+ dir = Dir[File.join("#{build_directory}","/**/CodeCoverage")].first
142
+ end
143
+
123
144
  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
124
145
  dir
125
146
  end
@@ -138,21 +159,6 @@ module Slather
138
159
  end
139
160
  private :profdata_file
140
161
 
141
- def find_binary_file_for_app(app_bundle_file)
142
- app_bundle_file_name_noext = Pathname.new(app_bundle_file).basename.to_s.gsub(".app", "")
143
- Dir["#{app_bundle_file}/**/#{app_bundle_file_name_noext}"].first
144
- end
145
-
146
- def find_binary_file_for_dynamic_lib(framework_bundle_file)
147
- framework_bundle_file_name_noext = Pathname.new(framework_bundle_file).basename.to_s.gsub(".framework", "")
148
- "#{framework_bundle_file}/#{framework_bundle_file_name_noext}"
149
- end
150
-
151
- def find_binary_file_for_static_lib(xctest_bundle_file)
152
- xctest_bundle_file_name_noext = Pathname.new(xctest_bundle_file).basename.to_s.gsub(".xctest", "")
153
- Dir["#{xctest_bundle_file}/**/#{xctest_bundle_file_name_noext}"].first
154
- end
155
-
156
162
  def unsafe_profdata_llvm_cov_output
157
163
  profdata_file_arg = profdata_file
158
164
  if profdata_file_arg == nil
@@ -283,25 +289,64 @@ module Slather
283
289
  end
284
290
  end
285
291
 
292
+ def find_binary_file_in_bundle(bundle_file)
293
+ bundle_file_noext = File.basename(bundle_file, File.extname(bundle_file))
294
+ Dir["#{bundle_file}/**/#{bundle_file_noext}"].first
295
+ end
296
+
286
297
  def find_binary_file
287
- xctest_bundle = Dir["#{profdata_coverage_dir}/**/*.xctest"].reject { |bundle|
288
- bundle.include? "-Runner.app/PlugIns/"
289
- }.first
290
- 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 xctest_bundle != nil
291
-
292
- # Find the matching binary file
293
- search_for = self.binary_basename || self.class.yml["binary_basename"] || '*'
294
- xctest_bundle_file_directory = Pathname.new(xctest_bundle).dirname
295
- app_bundle = Dir["#{xctest_bundle_file_directory}/#{search_for}.app"].first
296
- dynamic_lib_bundle = Dir["#{xctest_bundle_file_directory}/#{search_for}.framework"].first
297
-
298
- if app_bundle != nil
299
- find_binary_file_for_app(app_bundle)
300
- elsif dynamic_lib_bundle != nil
301
- find_binary_file_for_dynamic_lib(dynamic_lib_bundle)
298
+ binary_basename = self.binary_basename || self.class.yml["binary_basename"] || nil
299
+
300
+ # Get scheme info out of the xcodeproj
301
+ if self.scheme
302
+ schemes_path = Xcodeproj::XCScheme.shared_data_dir(self.path)
303
+ xcscheme_path = "#{schemes_path + self.scheme}.xcscheme"
304
+ xcscheme = Xcodeproj::XCScheme.new(xcscheme_path)
305
+
306
+ buildable_name = xcscheme.build_action.entries[0].buildable_references[0].buildable_name
307
+ configuration = xcscheme.test_action.build_configuration
308
+
309
+ search_for = binary_basename || buildable_name
310
+ found_product = Dir["#{profdata_coverage_dir}/Products/#{configuration}*/#{search_for}*"].sort { |x, y|
311
+ # Sort the matches without the file extension to ensure better matches when there are multiple candidates
312
+ # For example, if the binary_basename is Test then we want Test.app to be matched before Test Helper.app
313
+ File.basename(x, File.extname(x)) <=> File.basename(y, File.extname(y))
314
+ }.reject { |path|
315
+ path.end_with? ".dSYM"
316
+ }.first
317
+
318
+ if found_product and File.directory? found_product
319
+ found_binary = find_binary_file_in_bundle(found_product)
320
+ else
321
+ found_binary = found_product
322
+ end
302
323
  else
303
- find_binary_file_for_static_lib(xctest_bundle)
324
+ xctest_bundle = Dir["#{profdata_coverage_dir}/**/*.xctest"].reject { |bundle|
325
+ # Ignore xctest bundles that are in the UI runner app
326
+ bundle.include? "-Runner.app/PlugIns/"
327
+ }.first
328
+
329
+ # Find the matching binary file
330
+ search_for = binary_basename || '*'
331
+ xctest_bundle_file_directory = Pathname.new(xctest_bundle).dirname
332
+ app_bundle = Dir["#{xctest_bundle_file_directory}/#{search_for}.app"].first
333
+ dynamic_lib_bundle = Dir["#{xctest_bundle_file_directory}/#{search_for}.framework"].first
334
+ matched_xctest_bundle = Dir["#{xctest_bundle_file_directory}/#{search_for}.xctest"].first
335
+
336
+ if app_bundle != nil
337
+ found_binary = find_binary_file_in_bundle(app_bundle)
338
+ elsif dynamic_lib_bundle != nil
339
+ found_binary = find_binary_file_in_bundle(dynamic_lib_bundle)
340
+ elsif matched_xctest_bundle != nil
341
+ found_binary = find_binary_file_in_bundle(matched_xctest_bundle)
342
+ else
343
+ found_binary = find_binary_file_in_bundle(xctest_bundle)
344
+ end
304
345
  end
346
+
347
+ 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
348
+
349
+ found_binary
305
350
  end
306
351
 
307
352
  end
@@ -1,3 +1,3 @@
1
1
  module Slather
2
- VERSION = "2.0.1"
2
+ VERSION = "2.0.2"
3
3
  end
@@ -30,5 +30,30 @@ describe Slather::CoverageService::SimpleOutput do
30
30
 
31
31
  fixtures_project.post
32
32
  end
33
+
34
+ describe 'ci_service reporting output' do
35
+
36
+ context "ci_service is :teamcity" do
37
+ before(:each) { fixtures_project.ci_service = :teamcity }
38
+
39
+ it "should print out the coverage" do
40
+ ["spec/fixtures/fixtures/fixtures.m: 3 of 6 lines (50.00%)",
41
+ "spec/fixtures/fixtures/more_files/Branches.m: 13 of 30 lines (43.33%)",
42
+ "spec/fixtures/fixturesTests/BranchesTests.m: 16 of 16 lines (100.00%)",
43
+ "spec/fixtures/fixturesTests/fixturesTests.m: 12 of 12 lines (100.00%)",
44
+ "spec/fixtures/fixturesTests/peekaviewTests.m: 11 of 11 lines (100.00%)",
45
+ "##teamcity[buildStatisticValue key='CodeCoverageAbsLCovered' value='55']",
46
+ "##teamcity[buildStatisticValue key='CodeCoverageAbsLTotal' value='75']",
47
+ "Test Coverage: 73.33%"
48
+ ].each do |line|
49
+ expect(fixtures_project).to receive(:puts).with(line)
50
+ end
51
+
52
+ fixtures_project.post
53
+ end
54
+ end
55
+
56
+ end
57
+
33
58
  end
34
59
  end
@@ -8,24 +8,12 @@ describe Slather::Project do
8
8
  Slather::Project.open(FIXTURES_PROJECT_PATH)
9
9
  end
10
10
 
11
- describe "#derived_data_path" do
12
- it "should return the system's derived data directory" do
13
- expect(fixtures_project.send(:derived_data_path)).to eq(File.expand_path('~') + "/Library/Developer/Xcode/DerivedData/")
14
- end
15
- end
16
-
17
11
  describe "#build_directory" do
18
12
  it "should return the build_directory property, if it has been explicitly set" do
19
13
  build_directory_mock = double(String)
20
14
  fixtures_project.build_directory = build_directory_mock
21
15
  expect(fixtures_project.build_directory).to eq(build_directory_mock)
22
16
  end
23
-
24
- it "should return the derived_data_path if no build_directory has been set" do
25
- derived_data_path = File.expand_path('~') + "/Library/Developer/Xcode/DerivedData/"
26
- fixtures_project.send(:configure_build_directory)
27
- expect(fixtures_project.build_directory).to eq(derived_data_path)
28
- end
29
17
  end
30
18
 
31
19
  describe "::yml" do
@@ -141,31 +129,15 @@ describe Slather::Project do
141
129
  allow(Dir).to receive(:[]).and_call_original
142
130
  allow(fixtures_project).to receive(:build_directory).and_return(build_directory)
143
131
  allow(fixtures_project).to receive(:input_format).and_return("profdata")
144
- allow(fixtures_project).to receive(:scheme).and_return("FixtureScheme")
132
+ allow(fixtures_project).to receive(:scheme).and_return("fixtures")
145
133
  allow(Dir).to receive(:[]).with("#{build_directory}/**/CodeCoverage/FixtureScheme").and_return(["#{build_directory}/Build/Intermediates/CodeCoverage/FixtureScheme"])
146
134
  allow(Dir).to receive(:[]).with("#{build_directory}/Build/Intermediates/CodeCoverage/FixtureScheme/**/*.xctest").and_return(["#{build_directory}/Build/Intermediates/CodeCoverage/FixtureScheme/FixtureAppTests.xctest"])
147
135
  end
148
136
 
149
- it "should return the binary file location for an app bundle provided a scheme" do
150
- allow(Dir).to receive(:[]).with("#{build_directory}/Build/Intermediates/CodeCoverage/FixtureScheme/*.app").and_return(["/FixtureScheme/FixtureApp.app"])
151
- allow(Dir).to receive(:[]).with("/FixtureScheme/FixtureApp.app/**/FixtureApp").and_return(["/FixtureScheme/FixtureApp.app/FixtureApp"])
152
- fixtures_project.send(:configure_binary_file)
153
- binary_file_location = fixtures_project.send(:binary_file)
154
- expect(binary_file_location).to eq("/FixtureScheme/FixtureApp.app/FixtureApp")
155
- end
156
-
157
- it "should return the binary file location for a framework bundle provided a scheme" do
158
- allow(Dir).to receive(:[]).with("#{build_directory}/Build/Intermediates/CodeCoverage/FixtureScheme/*.framework").and_return(["/FixtureScheme/FixtureFramework.framework"])
137
+ it "should find the product path provided a scheme" do
159
138
  fixtures_project.send(:configure_binary_file)
160
139
  binary_file_location = fixtures_project.send(:binary_file)
161
- expect(binary_file_location).to eq("/FixtureScheme/FixtureFramework.framework/FixtureFramework")
162
- end
163
-
164
- it "should return the binary file location for a test bundle provided a scheme" do
165
- allow(Dir).to receive(:[]).with("#{build_directory}/Build/Intermediates/CodeCoverage/FixtureScheme/FixtureAppTests.xctest/**/FixtureAppTests").and_return(["/FixtureScheme/FixtureAppTests.xctest/Contents/MacOS/FixtureAppTests"])
166
- fixtures_project.send(:configure_binary_file)
167
- binary_file_location = fixtures_project.send(:binary_file)
168
- expect(binary_file_location).to eq("/FixtureScheme/FixtureAppTests.xctest/Contents/MacOS/FixtureAppTests")
140
+ expect(binary_file_location).to end_with("Debug/libfixtures.a")
169
141
  end
170
142
 
171
143
  let(:fixture_yaml) do
@@ -184,26 +156,18 @@ describe Slather::Project do
184
156
 
185
157
  let(:other_fixture_yaml) do
186
158
  yaml_text = <<-EOF
187
- binary_basename: "FixtureFramework"
159
+ binary_basename: "fixtures"
188
160
  EOF
189
161
  yaml = YAML.load(yaml_text)
190
162
  end
191
163
 
192
164
  it "should configure the binary_basename from yml" do
193
165
  allow(Slather::Project).to receive(:yml).and_return(other_fixture_yaml)
194
- allow(Dir).to receive(:[]).with("#{build_directory}/Build/Intermediates/CodeCoverage/FixtureScheme/FixtureFramework.framework").and_return(["/FixtureScheme/FixtureFramework.framework"])
166
+ allow(Dir).to receive(:[]).with("#{build_directory}/Build/Intermediates/CodeCoverage/Products/Debug/fixtureTests.xctest").and_return(["fixtureTests.xctest"])
195
167
  fixtures_project.send(:configure_binary_file)
196
168
  binary_file_location = fixtures_project.send(:binary_file)
197
- expect(binary_file_location).to eq("/FixtureScheme/FixtureFramework.framework/FixtureFramework")
169
+ expect(binary_file_location).to end_with("/fixturesTests.xctest/Contents/MacOS/fixturesTests")
198
170
  end
199
-
200
- # it "should find the binary file without any yml setting" do
201
- # fixtures_project.configure_binary_file
202
- # Dir.stub(:[]).with("#{build_directory}/Build/Intermediates/CodeCoverage/FixtureScheme/*.app").and_return(["/FixtureScheme/FixtureApp.app"])
203
- # Dir.stub(:[]).with("/FixtureScheme/FixtureApp.app/**/FixtureApp").and_return(["/FixtureScheme/FixtureApp.app/FixtureApp"])
204
- # binary_file_location = fixtures_project.send(:binary_file)
205
- # expect(binary_file_location).to eq("/FixtureScheme/FixtureApp.app/FixtureApp")
206
- # end
207
171
  end
208
172
 
209
173
  describe "#dedupe" do
@@ -449,8 +413,8 @@ describe Slather::Project do
449
413
 
450
414
  project_root = Pathname("./").realpath
451
415
 
452
- ["\nProcessing coverage file: #{project_root}/spec/DerivedData/libfixtures/Build/Intermediates/CodeCoverage/fixtures/Coverage.profdata",
453
- "Against binary file: #{project_root}/spec/DerivedData/libfixtures/Build/Intermediates/CodeCoverage/fixtures/Products/Debug/fixturesTests.xctest/Contents/MacOS/fixturesTests\n\n"
416
+ ["\nProcessing coverage file: #{project_root}/spec/DerivedData/libfixtures/Build/Intermediates/CodeCoverage/Coverage.profdata",
417
+ "Against binary file: #{project_root}/spec/DerivedData/libfixtures/Build/Intermediates/CodeCoverage/Products/Debug/fixturesTests.xctest/Contents/MacOS/fixturesTests\n\n"
454
418
  ].each do |line|
455
419
  expect(fixtures_project).to receive(:puts).with(line)
456
420
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slather
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Larsen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-23 00:00:00.000000000 Z
11
+ date: 2016-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -200,6 +200,8 @@ files:
200
200
  - docs/logo.jpg
201
201
  - lib/cocoapods_plugin.rb
202
202
  - lib/slather.rb
203
+ - lib/slather/command/coverage_command.rb
204
+ - lib/slather/command/setup_command.rb
203
205
  - lib/slather/coverage_file.rb
204
206
  - lib/slather/coverage_info.rb
205
207
  - lib/slather/coverage_service/cobertura_xml_output.rb