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