slather 1.8.3 → 2.0.0
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 +2 -1
- data/.travis.yml +1 -0
- data/CHANGELOG.md +21 -1
- data/README.md +15 -10
- data/README_Images/test_scheme.png +0 -0
- data/Rakefile +6 -0
- data/bin/slather +45 -6
- data/lib/slather/coverage_file.rb +37 -90
- data/lib/slather/coverage_info.rb +84 -0
- data/lib/slather/coverage_service/cobertura_xml_output.rb +10 -6
- data/lib/slather/coverage_service/coveralls.rb +5 -1
- data/lib/slather/coverage_service/gutter_json_output.rb +12 -8
- data/lib/slather/coverage_service/hardcover.rb +5 -1
- data/lib/slather/coverage_service/html_output.rb +32 -19
- data/lib/slather/coverage_service/simple_output.rb +5 -1
- data/lib/slather/{coveralls_coverage_file.rb → coveralls_coverage.rb} +1 -1
- data/lib/slather/profdata_coverage_file.rb +130 -0
- data/lib/slather/project.rb +191 -27
- data/lib/slather/version.rb +1 -1
- data/lib/slather.rb +9 -1
- data/slather.gemspec +4 -4
- data/spec/fixtures/cobertura.xml +56 -79
- data/spec/fixtures/fixtures/Fixtures.swift +15 -0
- data/spec/fixtures/fixtures/other_fixtures.m +23 -0
- data/spec/fixtures/fixtures_html/Branches.m.html +244 -258
- data/spec/fixtures/fixtures_html/BranchesTests.m.html +209 -225
- data/spec/fixtures/fixtures_html/fixtures.m.html +134 -148
- data/spec/fixtures/fixtures_html/fixturesTests.m.html +199 -213
- data/spec/fixtures/fixtures_html/index.html +68 -131
- data/spec/fixtures/fixtures_html/peekaviewTests.m.html +189 -203
- data/spec/fixtures/gutter.json +1 -1
- data/spec/slather/coverage_file_spec.rb +20 -12
- data/spec/slather/coverage_service/cobertura_xml_spec.rb +7 -3
- data/spec/slather/coverage_service/coveralls_spec.rb +61 -20
- data/spec/slather/coverage_service/gutter_json_spec.rb +6 -2
- data/spec/slather/coverage_service/hardcover_spec.rb +33 -3
- data/spec/slather/coverage_service/html_output_spec.rb +48 -7
- data/spec/slather/coverage_service/simple_output_spec.rb +12 -13
- data/spec/slather/profdata_coverage_spec.rb +128 -0
- data/spec/slather/project_spec.rb +222 -49
- data/spec/spec_helper.rb +28 -2
- metadata +58 -46
- data/spec/fixtures/fixtures_html/Empty.m.html +0 -30
- data/spec/fixtures/fixtures_html/fixtures_cpp.cpp.html +0 -30
- data/spec/fixtures/fixtures_html/fixtures_m.m.html +0 -30
- data/spec/fixtures/fixtures_html/fixtures_mm.mm.html +0 -30
- data/spec/fixtures/fixtures_html/peekaview.m.html +0 -190
@@ -5,7 +5,11 @@ module Slather
|
|
5
5
|
module HtmlOutput
|
6
6
|
|
7
7
|
def coverage_file_class
|
8
|
-
|
8
|
+
if input_format == "profdata"
|
9
|
+
Slather::ProfdataCoverageFile
|
10
|
+
else
|
11
|
+
Slather::CoverageFile
|
12
|
+
end
|
9
13
|
end
|
10
14
|
private :coverage_file_class
|
11
15
|
|
@@ -46,6 +50,11 @@ module Slather
|
|
46
50
|
FileUtils.rm_rf(directory_path) if Dir.exist?(directory_path)
|
47
51
|
FileUtils.mkdir_p(directory_path)
|
48
52
|
|
53
|
+
FileUtils.cp(File.join(gem_root_path, "docs/logo.jpg"), directory_path)
|
54
|
+
FileUtils.cp(File.join(gem_root_path, "assets/slather.css"), directory_path)
|
55
|
+
FileUtils.cp(File.join(gem_root_path, "assets/highlight.pack.js"), directory_path)
|
56
|
+
FileUtils.cp(File.join(gem_root_path, "assets/list.min.js"), directory_path)
|
57
|
+
|
49
58
|
reports.each do |name, doc|
|
50
59
|
html_file = File.join(directory_path, "#{name}.html")
|
51
60
|
File.write(html_file, doc.to_html)
|
@@ -141,18 +150,20 @@ module Slather
|
|
141
150
|
next
|
142
151
|
end
|
143
152
|
|
153
|
+
line_number_separator = coverage_file.line_number_separator
|
154
|
+
|
144
155
|
cov.table(:class => "source_code") {
|
145
156
|
cleaned_gcov_lines.each do |line|
|
146
|
-
data = line.split(
|
157
|
+
data = line.split(line_number_separator, 3)
|
147
158
|
|
148
159
|
line_number = data[1].to_i
|
149
160
|
next unless line_number > 0
|
150
161
|
|
151
162
|
coverage_data = data[0].strip
|
152
|
-
line_data = [line_number, data[2],
|
163
|
+
line_data = [line_number, data[2], hits_for_coverage_line(coverage_file, line)]
|
153
164
|
classes = ["num", "src", "coverage"]
|
154
165
|
|
155
|
-
cov.tr(:class =>
|
166
|
+
cov.tr(:class => class_for_coverage_line(coverage_file,line)) {
|
156
167
|
line_data.each_with_index { |line, idx|
|
157
168
|
if idx != 1
|
158
169
|
cov.td(line, :class => classes[idx])
|
@@ -171,10 +182,10 @@ module Slather
|
|
171
182
|
end
|
172
183
|
|
173
184
|
def generate_html_template(title, is_index, is_file_empty)
|
174
|
-
logo_path =
|
175
|
-
css_path =
|
176
|
-
highlight_js_path =
|
177
|
-
list_js_path =
|
185
|
+
logo_path = "logo.jpg"
|
186
|
+
css_path = "slather.css"
|
187
|
+
highlight_js_path = "highlight.pack.js"
|
188
|
+
list_js_path = "list.min.js"
|
178
189
|
|
179
190
|
builder = Nokogiri::HTML::Builder.new do |doc|
|
180
191
|
doc.html {
|
@@ -191,7 +202,7 @@ module Slather
|
|
191
202
|
doc.div(:class => "row") { doc.div(:id => "reports") }
|
192
203
|
doc.footer {
|
193
204
|
doc.div(:class => "row") {
|
194
|
-
doc.p { doc.a("Fork me on Github", :href => "https://github.com/
|
205
|
+
doc.p { doc.a("Fork me on Github", :href => "https://github.com/SlatherOrg/slather") }
|
195
206
|
doc.p("© #{Date.today.year} Slather")
|
196
207
|
}
|
197
208
|
}
|
@@ -215,19 +226,21 @@ module Slather
|
|
215
226
|
File.expand_path File.join(File.dirname(__dir__), "../..")
|
216
227
|
end
|
217
228
|
|
218
|
-
def
|
219
|
-
|
220
|
-
|
221
|
-
when
|
222
|
-
|
229
|
+
def class_for_coverage_line(coverage_file, coverage_line)
|
230
|
+
hits = coverage_file.coverage_for_line(coverage_line)
|
231
|
+
case
|
232
|
+
when hits == nil then "never"
|
233
|
+
when hits > 0 then "covered"
|
234
|
+
else "missed"
|
223
235
|
end
|
224
236
|
end
|
225
237
|
|
226
|
-
def
|
227
|
-
|
228
|
-
|
229
|
-
when
|
230
|
-
|
238
|
+
def hits_for_coverage_line(coverage_file, coverage_line)
|
239
|
+
hits = coverage_file.coverage_for_line(coverage_line)
|
240
|
+
case
|
241
|
+
when hits == nil then ""
|
242
|
+
when hits > 0 then "#{hits}x"
|
243
|
+
else "!"
|
231
244
|
end
|
232
245
|
end
|
233
246
|
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'slather/coverage_info'
|
2
|
+
require 'slather/coveralls_coverage'
|
3
|
+
|
4
|
+
module Slather
|
5
|
+
class ProfdataCoverageFile
|
6
|
+
|
7
|
+
include CoverageInfo
|
8
|
+
include CoverallsCoverage
|
9
|
+
|
10
|
+
attr_accessor :project, :source, :line_data
|
11
|
+
|
12
|
+
def initialize(project, source)
|
13
|
+
self.project = project
|
14
|
+
self.source = source
|
15
|
+
create_line_data
|
16
|
+
end
|
17
|
+
|
18
|
+
def create_line_data
|
19
|
+
all_lines = self.source.split("\n")[1..-1]
|
20
|
+
line_data = Hash.new
|
21
|
+
all_lines.each { |line| line_data[line_number_in_line(line)] = line }
|
22
|
+
self.line_data = line_data
|
23
|
+
end
|
24
|
+
private :create_line_data
|
25
|
+
|
26
|
+
def source_file_pathname
|
27
|
+
@source_file_pathname ||= begin
|
28
|
+
path = self.source.split("\n")[0].sub ":", ""
|
29
|
+
path &&= Pathname(path)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def source_file
|
34
|
+
File.new(source_file_pathname)
|
35
|
+
end
|
36
|
+
|
37
|
+
def source_data
|
38
|
+
all_lines.join("\n")
|
39
|
+
end
|
40
|
+
|
41
|
+
def all_lines
|
42
|
+
if @all_lines == nil
|
43
|
+
@all_lines = self.source.split("\n")[1..-1]
|
44
|
+
end
|
45
|
+
@all_lines
|
46
|
+
end
|
47
|
+
|
48
|
+
def cleaned_gcov_data
|
49
|
+
source_data
|
50
|
+
end
|
51
|
+
|
52
|
+
def raw_data
|
53
|
+
self.source
|
54
|
+
end
|
55
|
+
|
56
|
+
def line_number_in_line(line)
|
57
|
+
line =~ /^(\s*)(\d*)\|(\s*)(\d+)\|/
|
58
|
+
if $4 != nil
|
59
|
+
match = $4.strip
|
60
|
+
case match
|
61
|
+
when /[0-9]+/
|
62
|
+
return match.to_i
|
63
|
+
end
|
64
|
+
end
|
65
|
+
0
|
66
|
+
end
|
67
|
+
|
68
|
+
def line_coverage_data
|
69
|
+
self.source.split("\n")[1..-1].map do |line|
|
70
|
+
coverage_for_line(line)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def coverage_for_line(line)
|
75
|
+
line = line.gsub(":", "|")
|
76
|
+
line =~ /^(\s*)(\d*)\|/
|
77
|
+
|
78
|
+
if $2 == nil
|
79
|
+
return nil
|
80
|
+
end
|
81
|
+
|
82
|
+
match = $2.strip
|
83
|
+
case match
|
84
|
+
when /[0-9]+/
|
85
|
+
match.to_i
|
86
|
+
when /#+/
|
87
|
+
0
|
88
|
+
when "-"
|
89
|
+
nil
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def branch_coverage_data
|
94
|
+
@branch_coverage_data ||= begin
|
95
|
+
Hash.new
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def source_file_basename
|
100
|
+
File.basename(source_file_pathname, '.swift')
|
101
|
+
end
|
102
|
+
|
103
|
+
def line_number_separator
|
104
|
+
"|"
|
105
|
+
end
|
106
|
+
|
107
|
+
def supported_file_extensions
|
108
|
+
["swift"]
|
109
|
+
end
|
110
|
+
private :supported_file_extensions
|
111
|
+
|
112
|
+
def ignored?
|
113
|
+
ignore = false
|
114
|
+
platform_ignore_list.map do |ignore_suffix|
|
115
|
+
ignore = source_file_pathname.to_s.end_with? ignore_suffix
|
116
|
+
if ignore
|
117
|
+
break
|
118
|
+
end
|
119
|
+
end
|
120
|
+
ignore ? ignore : super
|
121
|
+
end
|
122
|
+
|
123
|
+
def platform_ignore_list
|
124
|
+
["MacOSX.platform/Developer/Library/Frameworks/XCTest.framework/Headers/XCTestAssertionsImpl.h",
|
125
|
+
"MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/objc/objc.h",
|
126
|
+
"MacOSX.platform/Developer/Library/Frameworks/XCTest.framework/Headers/XCTestAssertions.h"]
|
127
|
+
end
|
128
|
+
private :platform_ignore_list
|
129
|
+
end
|
130
|
+
end
|
data/lib/slather/project.rb
CHANGED
@@ -2,14 +2,45 @@ require 'fileutils'
|
|
2
2
|
require 'xcodeproj'
|
3
3
|
require 'json'
|
4
4
|
require 'yaml'
|
5
|
+
require 'shellwords'
|
5
6
|
|
6
7
|
module Xcodeproj
|
8
|
+
|
7
9
|
class Project
|
8
10
|
|
9
|
-
def slather_setup_for_coverage
|
11
|
+
def slather_setup_for_coverage(format = :auto)
|
12
|
+
unless [:gcov, :clang, :auto].include?(format)
|
13
|
+
raise StandardError, "Only supported formats for setup are gcov, clang or auto"
|
14
|
+
end
|
15
|
+
if format == :auto
|
16
|
+
format = Slather.xcode_version[0] < 7 ? :gcov : :clang
|
17
|
+
end
|
18
|
+
|
10
19
|
build_configurations.each do |build_configuration|
|
11
|
-
|
12
|
-
|
20
|
+
if format == :clang
|
21
|
+
build_configuration.build_settings["CLANG_ENABLE_CODE_COVERAGE"] = "YES"
|
22
|
+
else
|
23
|
+
build_configuration.build_settings["GCC_INSTRUMENT_PROGRAM_FLOW_ARCS"] = "YES"
|
24
|
+
build_configuration.build_settings["GCC_GENERATE_TEST_COVERAGE_FILES"] = "YES"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Patch xcschemes too
|
29
|
+
if format == :clang
|
30
|
+
if Gem::Requirement.new('~> 0.27') =~ Gem::Version.new(Xcodeproj::VERSION)
|
31
|
+
# @todo This will require to bump the xcodeproj dependency to ~> 0.27
|
32
|
+
# (which would require to bump cocoapods too)
|
33
|
+
schemes_path = Xcodeproj::XCScheme.shared_data_dir(self.path)
|
34
|
+
Xcodeproj::Project.schemes(self.path).each do |scheme_name|
|
35
|
+
xcscheme_path = "#{schemes_path + scheme_name}.xcscheme"
|
36
|
+
xcscheme = Xcodeproj::XCScheme.new(xcscheme_path)
|
37
|
+
xcscheme.test_action.xml_element.attributes['codeCoverageEnabled'] = 'YES'
|
38
|
+
xcscheme.save_as(self.path, scheme_name)
|
39
|
+
end
|
40
|
+
else
|
41
|
+
# @todo In the meantime, simply inform the user to do it manually
|
42
|
+
puts %Q(Ensure you enabled "Gather coverage data" in each of your scheme's Test action)
|
43
|
+
end
|
13
44
|
end
|
14
45
|
end
|
15
46
|
|
@@ -19,27 +50,32 @@ end
|
|
19
50
|
module Slather
|
20
51
|
class Project < Xcodeproj::Project
|
21
52
|
|
22
|
-
attr_accessor :build_directory, :ignore_list, :ci_service, :coverage_service, :coverage_access_token, :source_directory,
|
53
|
+
attr_accessor :build_directory, :ignore_list, :ci_service, :coverage_service, :coverage_access_token, :source_directory,
|
54
|
+
:output_directory, :xcodeproj, :show_html, :verbose_mode, :input_format, :scheme, :binary_file, :binary_basename
|
23
55
|
|
24
56
|
alias_method :setup_for_coverage, :slather_setup_for_coverage
|
25
57
|
|
26
58
|
def self.open(xcodeproj)
|
27
59
|
proj = super
|
28
|
-
proj.configure_from_yml
|
29
60
|
proj.xcodeproj = xcodeproj
|
30
61
|
proj
|
31
62
|
end
|
32
63
|
|
33
|
-
def
|
64
|
+
def derived_data_path
|
34
65
|
File.expand_path('~') + "/Library/Developer/Xcode/DerivedData/"
|
35
66
|
end
|
36
|
-
private :
|
67
|
+
private :derived_data_path
|
37
68
|
|
38
|
-
def
|
39
|
-
|
69
|
+
def coverage_files
|
70
|
+
if self.input_format == "profdata"
|
71
|
+
profdata_coverage_files
|
72
|
+
else
|
73
|
+
gcov_coverage_files
|
74
|
+
end
|
40
75
|
end
|
76
|
+
private :coverage_files
|
41
77
|
|
42
|
-
def
|
78
|
+
def gcov_coverage_files
|
43
79
|
coverage_files = Dir["#{build_directory}/**/*.gcno"].map do |file|
|
44
80
|
coverage_file = coverage_file_class.new(self, file)
|
45
81
|
# If there's no source file for this gcno, it probably belongs to another project.
|
@@ -52,7 +88,79 @@ module Slather
|
|
52
88
|
dedupe(coverage_files)
|
53
89
|
end
|
54
90
|
end
|
55
|
-
private :
|
91
|
+
private :gcov_coverage_files
|
92
|
+
|
93
|
+
def profdata_coverage_files
|
94
|
+
files = profdata_llvm_cov_output.split("\n\n")
|
95
|
+
|
96
|
+
files.map do |source|
|
97
|
+
coverage_file = coverage_file_class.new(self, source)
|
98
|
+
!coverage_file.ignored? ? coverage_file : nil
|
99
|
+
end.compact
|
100
|
+
end
|
101
|
+
private :profdata_coverage_files
|
102
|
+
|
103
|
+
def profdata_coverage_dir
|
104
|
+
raise StandardError, "The specified build directory (#{self.build_directory}) does not exist" unless File.exists?(self.build_directory)
|
105
|
+
dir = nil
|
106
|
+
if self.scheme
|
107
|
+
dir = Dir["#{build_directory}/**/CodeCoverage/#{self.scheme}"].first
|
108
|
+
else
|
109
|
+
dir = Dir["#{build_directory}/**/#{self.products.first.name}"].first
|
110
|
+
end
|
111
|
+
|
112
|
+
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
|
113
|
+
dir
|
114
|
+
end
|
115
|
+
|
116
|
+
def profdata_file
|
117
|
+
profdata_coverage_dir = self.profdata_coverage_dir
|
118
|
+
if profdata_coverage_dir == nil
|
119
|
+
raise StandardError, "No coverage directory found. Please make sure the \"Code Coverage\" checkbox is enabled in your scheme's Test action or the build_directory property is set."
|
120
|
+
end
|
121
|
+
|
122
|
+
file = Dir["#{profdata_coverage_dir}/**/Coverage.profdata"].first
|
123
|
+
unless file != nil
|
124
|
+
return nil
|
125
|
+
end
|
126
|
+
return File.expand_path(file)
|
127
|
+
end
|
128
|
+
private :profdata_file
|
129
|
+
|
130
|
+
def find_binary_file_for_app(app_bundle_file)
|
131
|
+
app_bundle_file_name_noext = Pathname.new(app_bundle_file).basename.to_s.gsub(".app", "")
|
132
|
+
Dir["#{app_bundle_file}/**/#{app_bundle_file_name_noext}"].first
|
133
|
+
end
|
134
|
+
|
135
|
+
def find_binary_file_for_dynamic_lib(framework_bundle_file)
|
136
|
+
framework_bundle_file_name_noext = Pathname.new(framework_bundle_file).basename.to_s.gsub(".framework", "")
|
137
|
+
"#{framework_bundle_file}/#{framework_bundle_file_name_noext}"
|
138
|
+
end
|
139
|
+
|
140
|
+
def find_binary_file_for_static_lib(xctest_bundle_file)
|
141
|
+
xctest_bundle_file_name_noext = Pathname.new(xctest_bundle_file).basename.to_s.gsub(".xctest", "")
|
142
|
+
Dir["#{xctest_bundle_file}/**/#{xctest_bundle_file_name_noext}"].first
|
143
|
+
end
|
144
|
+
|
145
|
+
def unsafe_profdata_llvm_cov_output
|
146
|
+
profdata_file_arg = profdata_file
|
147
|
+
if profdata_file_arg == nil
|
148
|
+
raise StandardError, "No Coverage.profdata files found. Please make sure the \"Code Coverage\" checkbox is enabled in your scheme's Test action or the build_directory property is set."
|
149
|
+
end
|
150
|
+
|
151
|
+
if self.binary_file == nil
|
152
|
+
raise StandardError, "No binary file found."
|
153
|
+
end
|
154
|
+
|
155
|
+
llvm_cov_args = %W(show -instr-profile #{profdata_file_arg} #{self.binary_file})
|
156
|
+
`xcrun llvm-cov #{llvm_cov_args.shelljoin}`
|
157
|
+
end
|
158
|
+
private :unsafe_profdata_llvm_cov_output
|
159
|
+
|
160
|
+
def profdata_llvm_cov_output
|
161
|
+
unsafe_profdata_llvm_cov_output.encode!('UTF-8', 'binary', :invalid => :replace, undef: :replace)
|
162
|
+
end
|
163
|
+
private :profdata_llvm_cov_output
|
56
164
|
|
57
165
|
def dedupe(coverage_files)
|
58
166
|
coverage_files.group_by(&:source_file_pathname).values.map { |cf_array| cf_array.max_by(&:percentage_lines_tested) }
|
@@ -67,45 +175,73 @@ module Slather
|
|
67
175
|
@yml ||= File.exist?(yml_filename) ? YAML.load_file(yml_filename) : {}
|
68
176
|
end
|
69
177
|
|
70
|
-
def
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
178
|
+
def configure
|
179
|
+
configure_build_directory
|
180
|
+
configure_ignore_list
|
181
|
+
configure_ci_service
|
182
|
+
configure_coverage_access_token
|
183
|
+
configure_coverage_service
|
184
|
+
configure_source_directory
|
185
|
+
configure_output_directory
|
186
|
+
configure_input_format
|
187
|
+
configure_scheme
|
188
|
+
configure_binary_file
|
189
|
+
|
190
|
+
if self.verbose_mode
|
191
|
+
puts "\nProcessing coverage file: #{profdata_file}"
|
192
|
+
puts "Against binary file: #{self.binary_file}\n\n"
|
193
|
+
end
|
78
194
|
end
|
79
195
|
|
80
|
-
def
|
81
|
-
self.build_directory
|
196
|
+
def configure_build_directory
|
197
|
+
self.build_directory ||= self.class.yml["build_directory"] || derived_data_path
|
82
198
|
end
|
83
199
|
|
84
|
-
def
|
200
|
+
def configure_source_directory
|
85
201
|
self.source_directory ||= self.class.yml["source_directory"] if self.class.yml["source_directory"]
|
86
202
|
end
|
87
203
|
|
88
|
-
def
|
204
|
+
def configure_output_directory
|
89
205
|
self.output_directory ||= self.class.yml["output_directory"] if self.class.yml["output_directory"]
|
90
206
|
end
|
91
207
|
|
92
|
-
def
|
208
|
+
def configure_ignore_list
|
93
209
|
self.ignore_list ||= [(self.class.yml["ignore"] || [])].flatten
|
94
210
|
end
|
95
211
|
|
96
|
-
def
|
212
|
+
def configure_ci_service
|
97
213
|
self.ci_service ||= (self.class.yml["ci_service"] || :travis_ci)
|
98
214
|
end
|
99
215
|
|
216
|
+
def configure_input_format
|
217
|
+
self.input_format ||= self.class.yml["input_format"] || input_format
|
218
|
+
end
|
219
|
+
|
220
|
+
def input_format=(format)
|
221
|
+
format ||= "auto"
|
222
|
+
unless %w(gcov profdata auto).include?(format)
|
223
|
+
raise StandardError, "Only supported input formats are gcov, profdata or auto"
|
224
|
+
end
|
225
|
+
if format == "auto"
|
226
|
+
@input_format = Slather.xcode_version[0] < 7 ? "gcov" : "profdata"
|
227
|
+
else
|
228
|
+
@input_format = format
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def configure_scheme
|
233
|
+
self.scheme ||= self.class.yml["scheme"] if self.class.yml["scheme"]
|
234
|
+
end
|
235
|
+
|
100
236
|
def ci_service=(service)
|
101
237
|
@ci_service = service && service.to_sym
|
102
238
|
end
|
103
239
|
|
104
|
-
def
|
240
|
+
def configure_coverage_service
|
105
241
|
self.coverage_service ||= (self.class.yml["coverage_service"] || :terminal)
|
106
242
|
end
|
107
243
|
|
108
|
-
def
|
244
|
+
def configure_coverage_access_token
|
109
245
|
self.coverage_access_token ||= (ENV["COVERAGE_ACCESS_TOKEN"] || self.class.yml["coverage_access_token"] || "")
|
110
246
|
end
|
111
247
|
|
@@ -128,5 +264,33 @@ module Slather
|
|
128
264
|
end
|
129
265
|
@coverage_service = service
|
130
266
|
end
|
267
|
+
|
268
|
+
def configure_binary_file
|
269
|
+
if self.input_format == "profdata"
|
270
|
+
self.binary_file ||= self.class.yml["binary_file"] || File.expand_path(find_binary_file)
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
def find_binary_file
|
275
|
+
xctest_bundle = Dir["#{profdata_coverage_dir}/**/*.xctest"].reject { |bundle|
|
276
|
+
bundle.include? "-Runner.app/PlugIns/"
|
277
|
+
}.first
|
278
|
+
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
|
279
|
+
|
280
|
+
# Find the matching binary file
|
281
|
+
search_for = self.binary_basename || self.class.yml["binary_basename"] || '*'
|
282
|
+
xctest_bundle_file_directory = Pathname.new(xctest_bundle).dirname
|
283
|
+
app_bundle = Dir["#{xctest_bundle_file_directory}/#{search_for}.app"].first
|
284
|
+
dynamic_lib_bundle = Dir["#{xctest_bundle_file_directory}/#{search_for}.framework"].first
|
285
|
+
|
286
|
+
if app_bundle != nil
|
287
|
+
find_binary_file_for_app(app_bundle)
|
288
|
+
elsif dynamic_lib_bundle != nil
|
289
|
+
find_binary_file_for_dynamic_lib(dynamic_lib_bundle)
|
290
|
+
else
|
291
|
+
find_binary_file_for_static_lib(xctest_bundle)
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
131
295
|
end
|
132
296
|
end
|
data/lib/slather/version.rb
CHANGED
data/lib/slather.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
require 'slather/version'
|
2
2
|
require 'slather/project'
|
3
|
+
require 'slather/coverage_info'
|
3
4
|
require 'slather/coverage_file'
|
4
|
-
require 'slather/
|
5
|
+
require 'slather/coveralls_coverage'
|
6
|
+
require 'slather/profdata_coverage_file'
|
5
7
|
require 'slather/coverage_service/cobertura_xml_output'
|
6
8
|
require 'slather/coverage_service/coveralls'
|
7
9
|
require 'slather/coverage_service/hardcover'
|
@@ -17,4 +19,10 @@ module Slather
|
|
17
19
|
Pod::UI.warn("[Slather] prepare_pods is now deprecated. The call to prepare_pods in your Podfile can simply be ommitted.")
|
18
20
|
end
|
19
21
|
|
22
|
+
def self.xcode_version
|
23
|
+
xcode_path = `xcode-select -p`.strip
|
24
|
+
xcode_version = `mdls -name kMDItemVersion -raw #{xcode_path.shellescape}/../..`.strip
|
25
|
+
xcode_version.split('.').map(&:to_i)
|
26
|
+
end
|
27
|
+
|
20
28
|
end
|
data/slather.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Mark Larsen"]
|
10
10
|
spec.email = ["mark@venmo.com"]
|
11
11
|
spec.summary = %q{Test coverage reports for Xcode projects}
|
12
|
-
spec.homepage = "https://github.com/
|
12
|
+
spec.homepage = "https://github.com/SlatherOrg/slather"
|
13
13
|
spec.license = "MIT"
|
14
14
|
|
15
15
|
spec.files = `git ls-files -z`.split("\x0")
|
@@ -20,13 +20,13 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.add_development_dependency "bundler", "~> 1.6"
|
21
21
|
spec.add_development_dependency "coveralls"
|
22
22
|
spec.add_development_dependency "rake", "~> 10.3"
|
23
|
-
spec.add_development_dependency "rspec", "~>
|
23
|
+
spec.add_development_dependency "rspec", "~> 3.3"
|
24
24
|
spec.add_development_dependency "pry", "~> 0.9"
|
25
|
-
spec.add_development_dependency "cocoapods", "
|
25
|
+
spec.add_development_dependency "cocoapods", ">= 0.39.0", "< 1.1.0"
|
26
26
|
spec.add_development_dependency "json_spec", "~> 1.1.4"
|
27
27
|
spec.add_development_dependency "equivalent-xml", "~> 0.5.1"
|
28
28
|
|
29
29
|
spec.add_dependency "clamp", "~> 0.6"
|
30
|
-
spec.add_dependency "xcodeproj", "
|
30
|
+
spec.add_dependency "xcodeproj", ">= 0.28.2", "< 1.1.0"
|
31
31
|
spec.add_dependency "nokogiri", "~> 1.6.3"
|
32
32
|
end
|