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 +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
|