Class: Danger::DangerJacoco
- Inherits:
-
Plugin
- Object
- Plugin
- Danger::DangerJacoco
- Defined in:
- lib/jacoco/plugin.rb
Overview
Verify code coverage inside your projects This is done using the jacoco output Results are passed out as a table in markdown
Instance Attribute Summary collapse
-
#fail_no_coverage_data_found ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#files_extension ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#minimum_class_coverage_map ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#minimum_class_coverage_percentage ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#minimum_package_coverage_map ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#minimum_project_coverage_percentage ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#title ⇒ Object
rubocop:disable Metrics/ClassLength.
Instance Method Summary collapse
-
#classes(delimiter) ⇒ Object
Select modified and added files in this PR.
-
#coverage_status(coverage, minimum_percentage) ⇒ Object
it returns an emoji for coverage status.
-
#package_coverage(class_name) ⇒ Object
it returns the most suitable coverage by package name to class or nil.
-
#parse(path) ⇒ Object
Parses the xml output of jacoco to Ruby model classes This is slow since it’s basically DOM parsing.
-
#report(path, report_url = '', delimiter = %r{/java/|/kotlin/|/scala/}, fail_no_coverage_data_found: true) ⇒ Object
This is a fast report based on SAX parser.
-
#report_class(jacoco_class) ⇒ Object
It returns a specific class code coverage and an emoji status as well.
-
#required_class_coverage(jacoco_class) ⇒ Object
Determines the required coverage for the class.
-
#setup ⇒ Object
Initialize the plugin with configured parameters or defaults.
-
#total_coverage(report_path) ⇒ Object
It returns total of project code coverage and an emoji status as well.
Instance Attribute Details
#fail_no_coverage_data_found ⇒ Object
rubocop:disable Metrics/ClassLength
23 24 25 |
# File 'lib/jacoco/plugin.rb', line 23 def fail_no_coverage_data_found @fail_no_coverage_data_found end |
#files_extension ⇒ Object
rubocop:disable Metrics/ClassLength
23 24 25 |
# File 'lib/jacoco/plugin.rb', line 23 def files_extension @files_extension end |
#minimum_class_coverage_map ⇒ Object
rubocop:disable Metrics/ClassLength
23 24 25 |
# File 'lib/jacoco/plugin.rb', line 23 def minimum_class_coverage_map @minimum_class_coverage_map end |
#minimum_class_coverage_percentage ⇒ Object
rubocop:disable Metrics/ClassLength
23 24 25 |
# File 'lib/jacoco/plugin.rb', line 23 def minimum_class_coverage_percentage @minimum_class_coverage_percentage end |
#minimum_package_coverage_map ⇒ Object
rubocop:disable Metrics/ClassLength
23 24 25 |
# File 'lib/jacoco/plugin.rb', line 23 def minimum_package_coverage_map @minimum_package_coverage_map end |
#minimum_project_coverage_percentage ⇒ Object
rubocop:disable Metrics/ClassLength
23 24 25 |
# File 'lib/jacoco/plugin.rb', line 23 def minimum_project_coverage_percentage @minimum_project_coverage_percentage end |
#title ⇒ Object
rubocop:disable Metrics/ClassLength
23 24 25 |
# File 'lib/jacoco/plugin.rb', line 23 def title @title end |
Instance Method Details
#classes(delimiter) ⇒ Object
Select modified and added files in this PR
83 84 85 86 87 88 |
# File 'lib/jacoco/plugin.rb', line 83 def classes(delimiter) git = @dangerfile.git affected_files = git.modified_files + git.added_files affected_files.select { |file| files_extension.reduce(false) { |state, el| state || file.end_with?(el) } } .map { |file| file.split('.').first.split(delimiter)[1] } end |
#coverage_status(coverage, minimum_percentage) ⇒ Object
it returns an emoji for coverage status
138 139 140 141 142 143 |
# File 'lib/jacoco/plugin.rb', line 138 def coverage_status(coverage, minimum_percentage) if coverage < (minimum_percentage / 2) then ':skull:' elsif coverage < minimum_percentage then ':warning:' else ':white_check_mark:' end end |
#package_coverage(class_name) ⇒ Object
it returns the most suitable coverage by package name to class or nil
124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/jacoco/plugin.rb', line 124 def package_coverage(class_name) path = class_name package_parts = class_name.split('/') package_parts.reverse_each do |item| size = item.size path = path[0...-size] coverage = minimum_package_coverage_map[path] path = path[0...-1] unless path.empty? return coverage unless coverage.nil? end nil end |
#parse(path) ⇒ Object
Parses the xml output of jacoco to Ruby model classes This is slow since it’s basically DOM parsing
41 42 43 |
# File 'lib/jacoco/plugin.rb', line 41 def parse(path) Jacoco::DOMParser.read_path(path) end |
#report(path, report_url = '', delimiter = %r{/java/|/kotlin/|/scala/}, fail_no_coverage_data_found: true) ⇒ Object
This is a fast report based on SAX parser
changed files. We need to get the class from this path to check the Jacoco report,
e.g. src/java/com/example/SomeJavaClass.java -> com/example/SomeJavaClass e.g. src/kotlin/com/example/SomeKotlinClass.kt -> com/example/SomeKotlinClass
The default value supposes that you’re using gradle structure, that is your path to source files is something like
Java => blah/blah/java/slashed_package/Source.java Kotlin => blah/blah/kotlin/slashed_package/Source.kt
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/jacoco/plugin.rb', line 62 def report(path, report_url = '', delimiter = %r{/java/|/kotlin/|/scala/}, fail_no_coverage_data_found: true) @fail_no_coverage_data_found = fail_no_coverage_data_found setup classes = classes(delimiter) parser = Jacoco::SAXParser.new(classes) Nokogiri::XML::SAX::Parser.new(parser).parse(File.open(path)) total_covered = total_coverage(path) report_markdown = "### #{title} Code Coverage #{total_covered[:covered]}% #{total_covered[:status]}\n" report_markdown += "| Class | Covered | Meta | Status |\n" report_markdown += "|:---|:---:|:---:|:---:|\n" class_coverage_above_minimum = markdown_class(parser, report_markdown, report_url) markdown(report_markdown) report_fails(class_coverage_above_minimum, total_covered) end |
#report_class(jacoco_class) ⇒ Object
It returns a specific class code coverage and an emoji status as well
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/jacoco/plugin.rb', line 91 def report_class(jacoco_class) report_result = { covered: 'No coverage data found : -', status: ':black_joker:', required_coverage_percentage: 'No coverage data found : -' } counter = coverage_counter(jacoco_class) unless counter.nil? coverage = (counter.covered.fdiv(counter.covered + counter.missed) * 100).floor required_coverage = required_class_coverage(jacoco_class) status = coverage_status(coverage, required_coverage) report_result = { covered: coverage, status: status, required_coverage_percentage: required_coverage } end report_result end |
#required_class_coverage(jacoco_class) ⇒ Object
Determines the required coverage for the class
115 116 117 118 119 120 121 |
# File 'lib/jacoco/plugin.rb', line 115 def required_class_coverage(jacoco_class) key = minimum_class_coverage_map.keys.detect { |k| jacoco_class.name.match(k) } || jacoco_class.name required_coverage = minimum_class_coverage_map[key] required_coverage = package_coverage(jacoco_class.name) if required_coverage.nil? required_coverage = minimum_class_coverage_percentage if required_coverage.nil? required_coverage end |
#setup ⇒ Object
Initialize the plugin with configured parameters or defaults
27 28 29 30 31 32 33 34 |
# File 'lib/jacoco/plugin.rb', line 27 def setup @minimum_project_coverage_percentage = 0 unless minimum_project_coverage_percentage @minimum_class_coverage_percentage = 0 unless minimum_class_coverage_percentage @minimum_package_coverage_map = {} unless minimum_package_coverage_map @minimum_class_coverage_map = {} unless minimum_class_coverage_map @files_extension = ['.kt', '.java'] unless files_extension @title = 'JaCoCo' unless title end |
#total_coverage(report_path) ⇒ Object
It returns total of project code coverage and an emoji status as well
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/jacoco/plugin.rb', line 146 def total_coverage(report_path) jacoco_report = Nokogiri::XML(File.open(report_path)) report = jacoco_report.xpath('report/counter').select { |item| item['type'] == 'INSTRUCTION' } missed_instructions = report.first['missed'].to_f covered_instructions = report.first['covered'].to_f total_instructions = missed_instructions + covered_instructions covered_percentage = (covered_instructions * 100 / total_instructions).round(2) coverage_status = coverage_status(covered_percentage, minimum_project_coverage_percentage) { covered: covered_percentage, status: coverage_status } end |