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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3bdbe837c78361b3aeaf31da767e58129ccd508d
4
- data.tar.gz: 4f2f77ba7fd3921e11a89f12f974181d33e8f469
3
+ metadata.gz: a541fad0337d84ad690cb556ead08462a202d4ca
4
+ data.tar.gz: 92103ad669d1a7b30a7873ed400ea928bc1ba296
5
5
  SHA512:
6
- metadata.gz: a8ac0d10a2ece773d76ff02f7394c244f8d992bc951826367fbaa2e4e5df9b1601a3c71c4c0a4be42221e8243c4f9237b4d55281ab79ea1bbbfb2650037322f7
7
- data.tar.gz: 5ba1246ccfb26b870b46494848b901592c61a2e68bc1bf72a7d37977bdea6864859b7f3fcd9fef976793fbf630a78a409f6b600dd40e4602653c8dd466904726
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
@@ -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
- coverage = 0
22
- targets.each do |target|
23
- coverage = coverage + target.coverage
22
+ executable = targets.reduce(0) do |partial_result, target|
23
+ partial_result + target.executable_lines
24
24
  end
25
- coverage / targets.count
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
 
@@ -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
- Source.new(name, location, coverage, functions)
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)
@@ -4,14 +4,18 @@ module Xcov
4
4
  class Target < Xcov::Base
5
5
 
6
6
  attr_accessor :name
7
- attr_accessor :coverage
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, coverage, files)
12
+ def initialize (name, executable, covered, files)
12
13
  @name = CGI::escapeHTML(name)
13
- @coverage = coverage
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.new(name, coverage, files)
62
- end
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
- coverage
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
@@ -1,6 +1,6 @@
1
1
  module Xcov
2
2
 
3
- VERSION = "0.12.5"
3
+ VERSION = "1.0.0"
4
4
  DESCRIPTION = "xcov is a friendly visualizer for Xcode's code coverage files"
5
5
 
6
6
  end
Binary file
@@ -1,5 +1,5 @@
1
1
  module Xcov
2
2
  module Core
3
- VERSION = "0.3"
3
+ VERSION = "0.4"
4
4
  end
5
5
  end
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} --add-location"
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.12.5
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: 2016-12-17 00:00:00.000000000 Z
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