Skip to content

Commit

Permalink
Rename code coverage reporter for console -> text (#12054)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jarred-Sumner authored Jun 22, 2024
1 parent 484ce2c commit 1a8ec98
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 36 deletions.
22 changes: 15 additions & 7 deletions docs/test/coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,24 @@ coverageIgnoreSourcemaps = true # default false

By default, coverage reports will be printed to the console.

You can specify the reporters and the directory where the reports will be saved.
This is needed, especially when you integrate coverages with tools like CodeCov, CodeClimate, Coveralls and so on.
For persistent code coverage reports in CI environments and for other tools, you can pass a `--coverage-reporter=lcov` CLI option or `coverageReporter` option in `bunfig.toml`.

```toml
coverageReporters = ["console", "lcov"] # default ["console"]
[test]
coverageReporter = ["text", "lcov"] # default ["text"]
coverageDir = "path/to/somewhere" # default "coverage"
```

| Reporter | Description |
|-----------|-------------|
| `console` | Prints a text summary of the coverage to the console. |
| `lcov` | Save coverage in [lcov](https://github.com/linux-test-project/lcov) format. |
| Reporter | Description |
| -------- | --------------------------------------------------------------------------- |
| `text` | Prints a text summary of the coverage to the console. |
| `lcov` | Save coverage in [lcov](https://github.com/linux-test-project/lcov) format. |

#### lcov coverage reporter

To generate an lcov report, you can use the `lcov` reporter. This will generate an `lcov.info` file in the `coverage` directory.

```toml
[test]
coverageReporter = "lcov"
```
21 changes: 17 additions & 4 deletions src/bunfig.zig
Original file line number Diff line number Diff line change
Expand Up @@ -258,15 +258,28 @@ pub const Bunfig = struct {
this.ctx.test_options.coverage.enabled = expr.data.e_boolean.value;
}

if (test_.get("coverageReporters")) |expr| {
this.ctx.test_options.coverage.reporters = .{ .console = false, .lcov = false };
if (test_.get("coverageReporter")) |expr| brk: {
this.ctx.test_options.coverage.reporters = .{ .text = false, .lcov = false };
if (expr.data == .e_string) {
const item_str = expr.asString(bun.default_allocator) orelse "";
if (bun.strings.eqlComptime(item_str, "text")) {
this.ctx.test_options.coverage.reporters.text = true;
} else if (bun.strings.eqlComptime(item_str, "lcov")) {
this.ctx.test_options.coverage.reporters.lcov = true;
} else {
try this.addErrorFormat(expr.loc, allocator, "Invalid coverage reporter \"{s}\"", .{item_str});
}

break :brk;
}

try this.expect(expr, .e_array);
const items = expr.data.e_array.items.slice();
for (items) |item| {
try this.expectString(item);
const item_str = item.asString(bun.default_allocator) orelse "";
if (bun.strings.eqlComptime(item_str, "console")) {
this.ctx.test_options.coverage.reporters.console = true;
if (bun.strings.eqlComptime(item_str, "text")) {
this.ctx.test_options.coverage.reporters.text = true;
} else if (bun.strings.eqlComptime(item_str, "lcov")) {
this.ctx.test_options.coverage.reporters.lcov = true;
} else {
Expand Down
8 changes: 4 additions & 4 deletions src/cli.zig
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ pub const Arguments = struct {
clap.parseParam("--only Only run tests that are marked with \"test.only()\"") catch unreachable,
clap.parseParam("--todo Include tests that are marked with \"test.todo()\"") catch unreachable,
clap.parseParam("--coverage Generate a coverage profile") catch unreachable,
clap.parseParam("--coverage-reporter <STR>... Report coverage in 'console' and/or 'lcov'. Defaults to 'console'.") catch unreachable,
clap.parseParam("--coverage-reporter <STR>... Report coverage in 'text' and/or 'lcov'. Defaults to 'text'.") catch unreachable,
clap.parseParam("--coverage-dir <STR> Directory for coverage files. Defaults to 'coverage'.") catch unreachable,
clap.parseParam("--bail <NUMBER>? Exit the test suite after <NUMBER> failures. If you do not specify a number, it defaults to 1.") catch unreachable,
clap.parseParam("-t, --test-name-pattern <STR> Run only tests with a name that matches the given regex.") catch unreachable,
Expand Down Expand Up @@ -444,10 +444,10 @@ pub const Arguments = struct {
}

if (args.options("--coverage-reporter").len > 0) {
ctx.test_options.coverage.reporters = .{ .console = false, .lcov = false };
ctx.test_options.coverage.reporters = .{ .text = false, .lcov = false };
for (args.options("--coverage-reporter")) |reporter| {
if (bun.strings.eqlComptime(reporter, "console")) {
ctx.test_options.coverage.reporters.console = true;
if (bun.strings.eqlComptime(reporter, "text")) {
ctx.test_options.coverage.reporters.text = true;
} else if (bun.strings.eqlComptime(reporter, "lcov")) {
ctx.test_options.coverage.reporters.lcov = true;
} else {
Expand Down
38 changes: 19 additions & 19 deletions src/cli/test_command.zig
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ pub const CommandLineReporter = struct {
}

pub fn generateCodeCoverage(this: *CommandLineReporter, vm: *JSC.VirtualMachine, opts: *TestCommand.CodeCoverageOptions, comptime reporters: TestCommand.Reporters, comptime enable_ansi_colors: bool) !void {
if (comptime !reporters.console and !reporters.lcov) {
if (comptime !reporters.text and !reporters.lcov) {
return;
}

Expand All @@ -296,12 +296,12 @@ pub const CommandLineReporter = struct {
pub fn printCodeCoverage(this: *CommandLineReporter, vm: *JSC.VirtualMachine, opts: *TestCommand.CodeCoverageOptions, byte_ranges: []bun.sourcemap.ByteRangeMapping, comptime reporters: TestCommand.Reporters, comptime enable_ansi_colors: bool) !void {
_ = this; // autofix
const trace = bun.tracy.traceNamed(@src(), comptime brk: {
if (reporters.console and reporters.lcov) {
break :brk "TestCommand.printCodeCoverageLCovAndConsole";
if (reporters.text and reporters.lcov) {
break :brk "TestCommand.printCodeCoverageLCovAndText";
}

if (reporters.console) {
break :brk "TestCommand.printCodeCoverageConsole";
if (reporters.text) {
break :brk "TestCommand.printCodeCoverageText";
}

if (reporters.lcov) {
Expand All @@ -312,14 +312,14 @@ pub const CommandLineReporter = struct {
});
defer trace.end();

if (comptime !reporters.console and !reporters.lcov) {
if (comptime !reporters.text and !reporters.lcov) {
@compileError("No reporters enabled");
}

const relative_dir = vm.bundler.fs.top_level_dir;

// --- Console ---
const max_filepath_length: usize = if (reporters.console) brk: {
// --- Text ---
const max_filepath_length: usize = if (reporters.text) brk: {
var len = "All files".len;
for (byte_ranges) |*entry| {
const utf8 = entry.source_url.slice();
Expand All @@ -333,7 +333,7 @@ pub const CommandLineReporter = struct {
const base_fraction = opts.fractions;
var failing = false;

if (comptime reporters.console) {
if (comptime reporters.text) {
console.writeAll(Output.prettyFmt("<r><d>", enable_ansi_colors)) catch return;
console.writeByteNTimes('-', max_filepath_length + 2) catch return;
console.writeAll(Output.prettyFmt("|---------|---------|-------------------<r>\n", enable_ansi_colors)) catch return;
Expand All @@ -356,7 +356,7 @@ pub const CommandLineReporter = struct {
.stmts = 0.0,
};
var avg_count: f64 = 0;
// --- Console ---
// --- Text ---

// --- LCOV ---
var lcov_name_buf: bun.PathBuffer = undefined;
Expand Down Expand Up @@ -429,9 +429,9 @@ pub const CommandLineReporter = struct {
var report = CodeCoverageReport.generate(vm.global, bun.default_allocator, entry, opts.ignore_sourcemap) orelse continue;
defer report.deinit(bun.default_allocator);

if (comptime reporters.console) {
if (comptime reporters.text) {
var fraction = base_fraction;
CodeCoverageReport.Console.writeFormat(&report, max_filepath_length, &fraction, relative_dir, console_writer, enable_ansi_colors) catch continue;
CodeCoverageReport.Text.writeFormat(&report, max_filepath_length, &fraction, relative_dir, console_writer, enable_ansi_colors) catch continue;
avg.functions += fraction.functions;
avg.lines += fraction.lines;
avg.stmts += fraction.stmts;
Expand All @@ -452,13 +452,13 @@ pub const CommandLineReporter = struct {
}
}

if (comptime reporters.console) {
if (comptime reporters.text) {
{
avg.functions /= avg_count;
avg.lines /= avg_count;
avg.stmts /= avg_count;

try CodeCoverageReport.Console.writeFormatWithValues(
try CodeCoverageReport.Text.writeFormatWithValues(
"All files",
max_filepath_length,
avg,
Expand Down Expand Up @@ -705,19 +705,19 @@ pub const TestCommand = struct {
pub const name = "test";
pub const CodeCoverageOptions = struct {
skip_test_files: bool = !Environment.allow_assert,
reporters: Reporters = .{ .console = true, .lcov = false },
reporters: Reporters = .{ .text = true, .lcov = false },
reports_directory: string = "coverage",
fractions: bun.sourcemap.CoverageFraction = .{},
ignore_sourcemap: bool = false,
enabled: bool = false,
fail_on_low_coverage: bool = false,
};
pub const Reporter = enum {
console,
text,
lcov,
};
const Reporters = struct {
console: bool,
text: bool,
lcov: bool,
};

Expand Down Expand Up @@ -1002,10 +1002,10 @@ pub const TestCommand = struct {

if (coverage.enabled) {
switch (Output.enable_ansi_colors_stderr) {
inline else => |colors| switch (coverage.reporters.console) {
inline else => |colors| switch (coverage.reporters.text) {
inline else => |console| switch (coverage.reporters.lcov) {
inline else => |lcov| {
try reporter.generateCodeCoverage(vm, &coverage, .{ .console = console, .lcov = lcov }, colors);
try reporter.generateCodeCoverage(vm, &coverage, .{ .text = console, .lcov = lcov }, colors);
},
},
},
Expand Down
4 changes: 2 additions & 2 deletions src/sourcemap/CodeCoverage.zig
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ pub const CodeCoverageReport = struct {
return (@as(f64, @floatFromInt(this.functions_which_have_executed.count())) / total_count);
}

pub const Console = struct {
pub const Text = struct {
pub fn writeFormatWithValues(
filename: []const u8,
max_filename_length: usize,
Expand Down Expand Up @@ -685,7 +685,7 @@ pub const ByteRangeMapping = struct {
var buffered_writer = mutable_str.bufferedWriter();
var writer = buffered_writer.writer();

CodeCoverageReport.Console.writeFormat(&report, source_url.utf8ByteLength(), &coverage_fraction, "", &writer, false) catch {
CodeCoverageReport.Text.writeFormat(&report, source_url.utf8ByteLength(), &coverage_fraction, "", &writer, false) catch {
globalThis.throwOutOfMemory();
return .zero;
};
Expand Down

0 comments on commit 1a8ec98

Please sign in to comment.