slather 2.0.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
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