From b4946a31e5c0c1db140be72e818c6bf2ea902b81 Mon Sep 17 00:00:00 2001 From: Valentin Kiselev Date: Mon, 29 May 2023 13:31:10 +0300 Subject: [PATCH] feat: support coveralls format feat: support coveralls format --- README.md | 1 + .../parsers/coveralls_parser_spec.cr | 44 ++++++++ spec/fixtures/coveralls/coveralls.json | 105 ++++++++++++++++++ .../parsers/cobertura_parser.cr | 2 +- .../parsers/coveralls_parser.cr | 54 +++++++++ 5 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 spec/coverage_reporter/parsers/coveralls_parser_spec.cr create mode 100644 spec/fixtures/coveralls/coveralls.json create mode 100644 src/coverage_reporter/parsers/coveralls_parser.cr diff --git a/README.md b/README.md index fcf799cb..8afef7d2 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,7 @@ With values used for `--format` option: - [x] Jacoco - `jacoco` - [x] Gcov - `gcov` - [x] Golang coverage format - `golang` +- [x] Coveralls JSON format - `coveralls` - [x] Pytest-Cov ([:test_tube: beta](#pytest-cov-test_tube-beta)) - `python` You can add a report parser to this project by following [these instructions](./doc/development.md#add-coverage-format-support). diff --git a/spec/coverage_reporter/parsers/coveralls_parser_spec.cr b/spec/coverage_reporter/parsers/coveralls_parser_spec.cr new file mode 100644 index 00000000..a8f437f2 --- /dev/null +++ b/spec/coverage_reporter/parsers/coveralls_parser_spec.cr @@ -0,0 +1,44 @@ +require "../../spec_helper" + +Spectator.describe CoverageReporter::CoverallsParser do + subject { described_class.new(base_path) } + + let(base_path) { nil } + + describe "#matches?" do + it "matches only coveralls.json" do + expect(subject.matches?("spec/fixtures/jacoco/jacoco-report.xml")).to eq false + expect(subject.matches?("spec/fixtures/coveralls/coveralls.json")).to eq true + end + end + + describe "#parse" do + let(filename) { "spec/fixtures/coveralls/coveralls.json" } + + it "parses" do + result = subject.parse(filename) + + expect(result[0].to_h).to eq({ + :name => "file.cpp", + :coverage => [nil, nil, 1, 1, 1, nil, 1, 1, 1], + :branches => [] of Array(Int64?), + :source_digest => "74a2a8e2849b4ebf97c08c3da0d83703", + }) + end + + context "with base_path" do + let(base_path) { "spec/fixtures/gcov" } + + it "parses" do + result = subject.parse(filename) + + expect(result[0].to_h).to eq({ + :name => "#{base_path}/file.cpp", + :coverage => [nil, nil, 1, 1, 1, nil, 1, 1, 1], + :branches => [] of Array(Int64?), + :source_digest => "74a2a8e2849b4ebf97c08c3da0d83703", + }) + end + end + end +end diff --git a/spec/fixtures/coveralls/coveralls.json b/spec/fixtures/coveralls/coveralls.json new file mode 100644 index 00000000..a7f1f809 --- /dev/null +++ b/spec/fixtures/coveralls/coveralls.json @@ -0,0 +1,105 @@ +{ + "git": { + "branch": "master", + "head": { + "author_email": "", + "author_name": "", + "committer_email": "", + "committer_name": "", + "id": "COMMIT", + "message": "" + }, + "remotes": [ + { + "name": "origin", + "url": "git@github.com:coverallsapp/coverage-reporter.git" + } + ] + }, + "parallel": false, + "repo_token": "TOKEN", + "service_job_id": "", + "service_name": "", + "service_number": "", + "service_pull_request": "", + "source_files": [ + { + "branches": [], + "coverage": [ + null, + null, + 1, + 1, + 1, + null, + 1, + 1, + 1 + ], + "name": "file.cpp", + "source_digest": "74a2a8e2849b4ebf97c08c3da0d83703" + }, + { + "branches": [], + "coverage": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + 1 + ], + "name": "include.h", + "source_digest": "d6261acc27f21cbf7b44654ef8db5be9" + }, + { + "branches": [ + 7, + 0, + 0, + 1, + 7, + 0, + 1, + 0, + 7, + 0, + 2, + 1, + 7, + 0, + 3, + 0, + 8, + 0, + 0, + 1, + 8, + 0, + 1, + 0 + ], + "coverage": [ + null, + null, + 1, + null, + 1, + null, + 1, + 1, + null, + 1, + 1 + ], + "name": "main.cpp", + "source_digest": "3d6c13992a5a8f14b972702307216222" + } + ] +} diff --git a/src/coverage_reporter/parsers/cobertura_parser.cr b/src/coverage_reporter/parsers/cobertura_parser.cr index ed64860f..cb684154 100644 --- a/src/coverage_reporter/parsers/cobertura_parser.cr +++ b/src/coverage_reporter/parsers/cobertura_parser.cr @@ -1,5 +1,5 @@ -require "xml" require "./base_parser" +require "xml" module CoverageReporter class CoberturaParser < BaseParser diff --git a/src/coverage_reporter/parsers/coveralls_parser.cr b/src/coverage_reporter/parsers/coveralls_parser.cr new file mode 100644 index 00000000..02365c0e --- /dev/null +++ b/src/coverage_reporter/parsers/coveralls_parser.cr @@ -0,0 +1,54 @@ +require "./base_parser" + +module CoverageReporter + class CoverallsParser < BaseParser + class SourceFiles + include JSON::Serializable + + property name : String + property coverage : Array(Int64?) + property branches : Array(Int64?) | Nil + property source_digest : String? + end + + class CoverallsFormat + include JSON::Serializable + + property source_files : Array(SourceFiles) + end + + def initialize(@base_path : String?) + end + + def globs : Array(String) + [ + "coveralls.json", + "**/*/coveralls.json", + ] + end + + def matches?(filename : String) : Bool + File.open(filename) do |f| + parsed = JSON.parse(f) + parsed["source_files"].as_a? != nil + end + rescue Exception + false + end + + def parse(filename : String) : Array(FileReport) + data = CoverallsFormat.from_json(File.read(filename)) + data.source_files.map do |source_file| + name = File.join(@base_path.to_s, source_file.name) + + FileReport.new( + name: name, + coverage: source_file.coverage, + branches: source_file.branches, + source_digest: source_file.source_digest || BaseParser.source_digest(name), + format: self.class.name, + ) + end + end + end +end