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 +4 -4
- data/.gitignore +3 -0
- data/.travis.yml +1 -1
- data/CHANGELOG.md +29 -1
- data/README.md +8 -0
- data/bin/slather +8 -149
- data/lib/slather/command/coverage_command.rb +127 -0
- data/lib/slather/command/setup_command.rb +15 -0
- data/lib/slather/coverage_service/html_output.rb +2 -1
- data/lib/slather/coverage_service/simple_output.rb +16 -0
- data/lib/slather/project.rb +77 -32
- data/lib/slather/version.rb +1 -1
- data/spec/slather/coverage_service/simple_output_spec.rb +25 -0
- data/spec/slather/project_spec.rb +8 -44
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3091b591850a4c53ba0f5d19fea4f62b01f833e
|
4
|
+
data.tar.gz: dc3b6ed662c319e4d3cb7f0abd463ab80047ad8d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9abc7f87812d4f98fff3bbc4f90fa04c68516885b187fe5d6a60066b3084e814059de68d418b7c971af219d16aedc7acdc24f8526e0ce56a98070872ea32000
|
7
|
+
data.tar.gz: b3eac9e758b90f7b74e3cc3280ec4d9b21c668f1b6249d2568d89d411815054d4210e644ed7a0619c52f767af601f354e682ca059d898bee7e233257564faf48
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -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
|
data/bin/slather
CHANGED
@@ -1,156 +1,15 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'clamp'
|
3
3
|
require 'yaml'
|
4
|
-
|
5
|
-
|
6
|
-
|
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 "
|
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 = "
|
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
|
data/lib/slather/project.rb
CHANGED
@@ -62,7 +62,23 @@ module Slather
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def derived_data_path
|
65
|
-
|
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
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
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
|
-
|
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
|
data/lib/slather/version.rb
CHANGED
@@ -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("
|
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
|
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
|
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: "
|
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/
|
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
|
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/
|
453
|
-
"Against binary file: #{project_root}/spec/DerivedData/libfixtures/Build/Intermediates/CodeCoverage/
|
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.
|
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-
|
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
|