xcov 0.12.5 → 1.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/README.md +1 -0
- data/lib/xcov/model/line.rb +31 -0
- data/lib/xcov/model/range.rb +25 -0
- data/lib/xcov/model/report.rb +20 -4
- data/lib/xcov/model/source.rb +18 -2
- data/lib/xcov/model/target.rb +31 -12
- data/lib/xcov/options.rb +10 -3
- data/lib/xcov/project_extensions.rb +33 -0
- data/lib/xcov/version.rb +1 -1
- data/lib/xcov-core/bin/xcov-core +0 -0
- data/lib/xcov-core/version.rb +1 -1
- data/lib/xcov-core.rb +1 -1
- data/lib/xcov.rb +3 -0
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a541fad0337d84ad690cb556ead08462a202d4ca
|
4
|
+
data.tar.gz: 92103ad669d1a7b30a7873ed400ea928bc1ba296
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a0cd8ee13eec12362f5b89e92c3b91711f7fa7ead460985166439026cdc34c858a7f2b281503203f86e4aa8d75280359d0ca4ad2ef7a49b74e01da2e3b7f754
|
7
|
+
data.tar.gz: 25996d44347d50e596b0c0546917c146417c24498f6ef71534730aa8560c13aa603163aae0c5e50cc8ae42a157a2e3a6bde380c20eca7bcd9fc6e3357d678c85
|
data/README.md
CHANGED
@@ -58,6 +58,7 @@ xcov -w LystSDK.xcworkspace -s LystSDK -o xcov_output
|
|
58
58
|
* `--json_report`: Enables the creation of a json report (optional).
|
59
59
|
* `--markdown_report`: Enables the creation of a markdown report (optional).
|
60
60
|
* `--skip_slack`: Add this flag to avoid publishing results on Slack (optional).
|
61
|
+
* `--only_project_targets`: Display the coverage only for main project targets (e.g. skip Pods targets).
|
61
62
|
|
62
63
|
_**Note:** All paths you provide should be absolute and unescaped_
|
63
64
|
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Xcov
|
2
|
+
class Line
|
3
|
+
|
4
|
+
attr_reader :execution_count
|
5
|
+
attr_reader :executable
|
6
|
+
attr_reader :ranges
|
7
|
+
|
8
|
+
def initialize (execution_count, executable, ranges = nil)
|
9
|
+
@execution_count = execution_count
|
10
|
+
@executable = executable
|
11
|
+
@ranges = ranges
|
12
|
+
end
|
13
|
+
|
14
|
+
def covered?
|
15
|
+
execution_count > 0
|
16
|
+
end
|
17
|
+
|
18
|
+
# Class methods
|
19
|
+
|
20
|
+
def self.map (dictionary)
|
21
|
+
ranges = map_ranges(dictionary["ranges"])
|
22
|
+
Line.new(dictionary["executionCount"], dictionary["executable"], ranges)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.map_ranges (dictionaries)
|
26
|
+
return nil if dictionaries.nil?
|
27
|
+
dictionaries.map { |dictionary| Range.map(dictionary) }
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Xcov
|
2
|
+
class Range
|
3
|
+
|
4
|
+
attr_reader :execution_count
|
5
|
+
attr_reader :location
|
6
|
+
attr_reader :length
|
7
|
+
|
8
|
+
def initialize (execution_count, location, length)
|
9
|
+
@execution_count = execution_count
|
10
|
+
@location = location
|
11
|
+
@length = length
|
12
|
+
end
|
13
|
+
|
14
|
+
# Class methods
|
15
|
+
|
16
|
+
def self.map (dictionary)
|
17
|
+
Range.new(
|
18
|
+
dictionary["executionCount"],
|
19
|
+
dictionary["location"],
|
20
|
+
dictionary["length"]
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
data/lib/xcov/model/report.rb
CHANGED
@@ -17,12 +17,19 @@ module Xcov
|
|
17
17
|
|
18
18
|
def average_coverage targets
|
19
19
|
return 0 if targets.count == 0
|
20
|
+
return targets.first.coverage if targets.count == 1
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
coverage = coverage + target.coverage
|
22
|
+
executable = targets.reduce(0) do |partial_result, target|
|
23
|
+
partial_result + target.executable_lines
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
|
+
covered = targets.reduce(0) do |partial_result, target|
|
27
|
+
partial_result + target.covered_lines
|
28
|
+
end
|
29
|
+
|
30
|
+
return 0 if executable == 0 # avoid ZeroDivisionError
|
31
|
+
|
32
|
+
covered.to_f / executable.to_f
|
26
33
|
end
|
27
34
|
|
28
35
|
def print_description
|
@@ -75,6 +82,15 @@ module Xcov
|
|
75
82
|
filtered_targets = filtered_targets.select { |target| self.included_targets.include?(target["name"])}
|
76
83
|
end
|
77
84
|
|
85
|
+
supported_targets = Xcov.project.targets
|
86
|
+
if Xcov.config[:only_project_targets] && !supported_targets.empty?
|
87
|
+
filtered_targets = filtered_targets.select do |target|
|
88
|
+
name = target["name"]
|
89
|
+
name.slice! File.extname(name) # remove target extensions
|
90
|
+
supported_targets.include?(name)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
78
94
|
filtered_targets
|
79
95
|
end
|
80
96
|
|
data/lib/xcov/model/source.rb
CHANGED
@@ -10,8 +10,9 @@ module Xcov
|
|
10
10
|
attr_accessor :coverage
|
11
11
|
attr_accessor :functions
|
12
12
|
attr_accessor :function_templates
|
13
|
+
attr_accessor :lines
|
13
14
|
|
14
|
-
def initialize (name, location, coverage, functions)
|
15
|
+
def initialize (name, location, coverage, functions, lines = nil)
|
15
16
|
@name = CGI::escapeHTML(name)
|
16
17
|
@location = CGI::escapeHTML(location)
|
17
18
|
@coverage = coverage
|
@@ -21,6 +22,7 @@ module Xcov
|
|
21
22
|
@coverage_color = self.create_coverage_color
|
22
23
|
@id = Source.create_id(name)
|
23
24
|
@type = Source.type(name)
|
25
|
+
@lines = lines
|
24
26
|
|
25
27
|
if @ignored
|
26
28
|
UI.message "Ignoring #{name} coverage".yellow
|
@@ -60,6 +62,15 @@ module Xcov
|
|
60
62
|
return value
|
61
63
|
end
|
62
64
|
|
65
|
+
def number_of_executable_lines
|
66
|
+
return 0 if lines.nil? || lines.empty?
|
67
|
+
lines.select { |line| line.executable }.count
|
68
|
+
end
|
69
|
+
|
70
|
+
def number_of_covered_lines
|
71
|
+
return 0 if lines.nil? || lines.empty?
|
72
|
+
lines.select { |line| line.covered? }.count
|
73
|
+
end
|
63
74
|
|
64
75
|
# Class methods
|
65
76
|
|
@@ -68,8 +79,13 @@ module Xcov
|
|
68
79
|
location = dictionary["location"]
|
69
80
|
coverage = dictionary["coverage"]
|
70
81
|
functions = dictionary["functions"].map { |function| Function.map(function)}
|
82
|
+
lines = map_lines(dictionary["lines"])
|
83
|
+
Source.new(name, location, coverage, functions, lines)
|
84
|
+
end
|
71
85
|
|
72
|
-
|
86
|
+
def self.map_lines (dictionaries)
|
87
|
+
return nil if dictionaries.nil?
|
88
|
+
dictionaries.map { |line| Line.map(line) }
|
73
89
|
end
|
74
90
|
|
75
91
|
def self.type (name)
|
data/lib/xcov/model/target.rb
CHANGED
@@ -4,14 +4,18 @@ module Xcov
|
|
4
4
|
class Target < Xcov::Base
|
5
5
|
|
6
6
|
attr_accessor :name
|
7
|
-
attr_accessor :
|
7
|
+
attr_accessor :executable_lines # number of executable lines in target
|
8
|
+
attr_accessor :covered_lines # number of covered lines in target
|
8
9
|
attr_accessor :files
|
9
10
|
attr_accessor :file_templates
|
10
11
|
|
11
|
-
def initialize (name,
|
12
|
+
def initialize (name, executable, covered, files)
|
12
13
|
@name = CGI::escapeHTML(name)
|
13
|
-
@
|
14
|
+
@executable_lines = executable
|
15
|
+
@covered_lines = covered
|
14
16
|
@files = files
|
17
|
+
# we cast to floats because integers always return 0
|
18
|
+
@coverage = executable == 0 ? 0.0 : covered.to_f / executable # avoid ZeroDivisionError
|
15
19
|
@displayable_coverage = self.create_displayable_coverage
|
16
20
|
@coverage_color = self.create_coverage_color
|
17
21
|
@id = Target.create_id(name)
|
@@ -56,18 +60,13 @@ module Xcov
|
|
56
60
|
name = dictionary["name"]
|
57
61
|
files = dictionary["files"].map { |file| Source.map(file)}
|
58
62
|
files = files.sort &by_coverage_with_ignored_at_the_end
|
59
|
-
coverage = Target.calculate_coverage(files)
|
60
63
|
|
61
|
-
Target.
|
62
|
-
|
64
|
+
non_ignored_files = Target.select_non_ignored_files(files)
|
65
|
+
executable = Target.calculate_number_of_executable_lines(non_ignored_files)
|
66
|
+
covered = Target.calculate_number_of_covered_lines(non_ignored_files)
|
63
67
|
|
64
|
-
def self.calculate_coverage (files)
|
65
|
-
coverage = 0
|
66
|
-
non_ignored_files = files.select { |file| !file.ignored }
|
67
|
-
non_ignored_files.each { |file| coverage += file.coverage }
|
68
|
-
coverage = coverage / non_ignored_files.count unless non_ignored_files.empty?
|
69
68
|
|
70
|
-
|
69
|
+
Target.new(name, executable, covered, files)
|
71
70
|
end
|
72
71
|
|
73
72
|
def self.by_coverage_with_ignored_at_the_end
|
@@ -83,5 +82,25 @@ module Xcov
|
|
83
82
|
}
|
84
83
|
end
|
85
84
|
|
85
|
+
def self.select_non_ignored_files(files)
|
86
|
+
files.select { |file| !file.ignored }
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.calculate_number_of_covered_lines (files)
|
90
|
+
return 0 if files.nil? || files.empty?
|
91
|
+
|
92
|
+
files.reduce(0) do |partial_result, file|
|
93
|
+
partial_result + file.number_of_covered_lines
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.calculate_number_of_executable_lines (files)
|
98
|
+
return 0 if files.nil? || files.empty?
|
99
|
+
|
100
|
+
files.reduce(0) do |partial_result, file|
|
101
|
+
partial_result + file.number_of_executable_lines
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
86
105
|
end
|
87
106
|
end
|
data/lib/xcov/options.rb
CHANGED
@@ -119,12 +119,19 @@ module Xcov
|
|
119
119
|
default_value: false),
|
120
120
|
FastlaneCore::ConfigItem.new(key: :exclude_targets,
|
121
121
|
optional: true,
|
122
|
-
conflicting_options: [:include_targets],
|
122
|
+
conflicting_options: [:include_targets, :only_project_targets],
|
123
123
|
description: "Comma separated list of targets to exclude from coverage report"),
|
124
124
|
FastlaneCore::ConfigItem.new(key: :include_targets,
|
125
125
|
optional: true,
|
126
|
-
conflicting_options: [:exclude_targets],
|
127
|
-
description: "Comma separated list of targets to include in coverage report. If specified then exlude_targets will be ignored")
|
126
|
+
conflicting_options: [:exclude_targets, :only_project_targets],
|
127
|
+
description: "Comma separated list of targets to include in coverage report. If specified then exlude_targets will be ignored"),
|
128
|
+
FastlaneCore::ConfigItem.new(key: :only_project_targets,
|
129
|
+
optional: true,
|
130
|
+
conflicting_options: [:exclude_targets, :include_targets],
|
131
|
+
description: "Display the coverage only for main project targets (e.g. skip Pods targets)",
|
132
|
+
is_string: false,
|
133
|
+
default_value: false)
|
134
|
+
|
128
135
|
]
|
129
136
|
end
|
130
137
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "fastlane_core"
|
2
|
+
require "xcodeproj"
|
3
|
+
|
4
|
+
module FastlaneCore
|
5
|
+
class Project
|
6
|
+
|
7
|
+
# Returns project targets
|
8
|
+
def targets
|
9
|
+
project_path = get_project_path
|
10
|
+
return [] if project_path.nil?
|
11
|
+
|
12
|
+
proj = Xcodeproj::Project.open(project_path)
|
13
|
+
|
14
|
+
proj.targets.map do |target|
|
15
|
+
target.name
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def get_project_path
|
22
|
+
# Given the workspace and scheme, we can compute project path
|
23
|
+
if workspace?
|
24
|
+
if options[:workspace] && options[:scheme]
|
25
|
+
build_settings(key: "PROJECT_FILE_PATH")
|
26
|
+
end
|
27
|
+
else
|
28
|
+
options[:project]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
data/lib/xcov/version.rb
CHANGED
data/lib/xcov-core/bin/xcov-core
CHANGED
Binary file
|
data/lib/xcov-core/version.rb
CHANGED
data/lib/xcov-core.rb
CHANGED
@@ -13,7 +13,7 @@ module Xcov
|
|
13
13
|
|
14
14
|
def self.parse(file)
|
15
15
|
report_output = Tempfile.new("report.json")
|
16
|
-
command = "#{ENV['XCOV_CORE_LIBRARY_PATH'].shellescape} -s #{file.shellescape} -o #{report_output.path.shellescape} --
|
16
|
+
command = "#{ENV['XCOV_CORE_LIBRARY_PATH'].shellescape} -s #{file.shellescape} -o #{report_output.path.shellescape} --include-lines-info"
|
17
17
|
description = [{ prefix: "Parsing .xccoverage file: " }]
|
18
18
|
execute_command(command, description)
|
19
19
|
output_file = File.read(report_output.path)
|
data/lib/xcov.rb
CHANGED
@@ -11,6 +11,9 @@ require 'xcov/model/report'
|
|
11
11
|
require 'xcov/model/target'
|
12
12
|
require 'xcov/model/source'
|
13
13
|
require 'xcov/model/function'
|
14
|
+
require 'xcov/model/line'
|
15
|
+
require 'xcov/model/range'
|
16
|
+
require 'xcov/project_extensions'
|
14
17
|
require 'fastlane_core'
|
15
18
|
|
16
19
|
module Xcov
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xcov
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carlos Vidal
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-01-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fastlane
|
@@ -44,6 +44,20 @@ dependencies:
|
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '1.3'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: xcodeproj
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.4'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '1.4'
|
47
61
|
- !ruby/object:Gem::Dependency
|
48
62
|
name: terminal-table
|
49
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -203,10 +217,13 @@ files:
|
|
203
217
|
- lib/xcov/manager.rb
|
204
218
|
- lib/xcov/model/base.rb
|
205
219
|
- lib/xcov/model/function.rb
|
220
|
+
- lib/xcov/model/line.rb
|
221
|
+
- lib/xcov/model/range.rb
|
206
222
|
- lib/xcov/model/report.rb
|
207
223
|
- lib/xcov/model/source.rb
|
208
224
|
- lib/xcov/model/target.rb
|
209
225
|
- lib/xcov/options.rb
|
226
|
+
- lib/xcov/project_extensions.rb
|
210
227
|
- lib/xcov/runner.rb
|
211
228
|
- lib/xcov/slack_poster.rb
|
212
229
|
- lib/xcov/version.rb
|