Skip to content

Commit

Permalink
Add simple html coverage report
Browse files Browse the repository at this point in the history
  • Loading branch information
lukfor committed Jun 13, 2024
1 parent 2f73ec3 commit 5bfd088
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ public class CoverageCommand extends AbstractCommand {
"--csv" }, description = "Write coverage results in csv format", required = false, showDefaultValue = Visibility.ALWAYS)
private String csv = null;

@Option(names = {
"--html" }, description = "Write coverage results in html format", required = false, showDefaultValue = Visibility.ALWAYS)
private String html = null;


@Option(names = { "--config",
"-c" }, description = "nf-test.config filename", required = false, showDefaultValue = Visibility.ALWAYS)
private String configFilename = Config.FILENAME;
Expand Down Expand Up @@ -71,6 +76,8 @@ public Integer execute() throws Exception {
Coverage coverage = new Coverage(resolver).getAll();
if (csv != null) {
coverage.exportAsCsv(csv);
} else if (html != null) {
coverage.exportAsHtml(html);
} else {
coverage.printDetails();
}
Expand Down
41 changes: 34 additions & 7 deletions src/main/java/com/askimed/nf/test/lang/dependencies/Coverage.java
Original file line number Diff line number Diff line change
@@ -1,24 +1,31 @@
package com.askimed.nf.test.lang.dependencies;

import com.askimed.nf.test.commands.init.InitTemplates;
import com.askimed.nf.test.core.TestExecutionResult;
import com.askimed.nf.test.core.TestSuiteExecutionResult;
import com.askimed.nf.test.core.reports.CsvReportWriter;
import com.askimed.nf.test.util.AnsiColors;
import com.askimed.nf.test.util.AnsiText;
import com.askimed.nf.test.util.FileUtil;
import com.opencsv.CSVWriter;
import groovy.lang.Writable;
import groovy.text.SimpleTemplateEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Paths;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Vector;
import java.text.DecimalFormatSymbols;
import java.util.*;

public class Coverage {

private static final String HTML_TEMPLATE = "coverage-report.html";

private int coveredItems = 0;

private DependencyGraph graph;
Expand Down Expand Up @@ -118,23 +125,32 @@ public void printDetails() {
System.out.println();
System.out.println("Files:");
for (Coverage.CoverageItem item : getItems()) {
String label = item.getFile().getAbsolutePath();
if (baseDir != null) {
label = Paths.get(baseDir.getAbsolutePath()).relativize(item.getFile().toPath()).toString();
}
String label = getFileLabel(item.getFile());
System.out.println(" \u2022 " + (item.isCovered() ? AnsiColors.green(label) : AnsiColors.red(label)));
}
System.out.println();
printLabel();
System.out.println();
}

public String getFileLabel(File file) {
String label = file.getAbsolutePath();
if (baseDir != null) {
label = Paths.get(baseDir.getAbsolutePath()).relativize(file.toPath()).toString();
}
return label;
}

private void printLabel() {
float coverage = getCoveredItems() / (float) getItems().size();
System.out.print(getColor("COVERAGE:", coverage) + " " + formatCoverage(coverage));
System.out.println( " [" + getCoveredItems() + " of " + getItems().size() + " files]");
}

public float getCoverage() {
return getCoveredItems() / (float) getItems().size();
}

private String getColor(String label, float value) {
if (value < 0.5) {
return AnsiColors.red(label);
Expand All @@ -146,7 +162,7 @@ private String getColor(String label, float value) {
}

private String formatCoverage(float value) {
DecimalFormat decimalFormat = new DecimalFormat("#.##");
DecimalFormat decimalFormat = new DecimalFormat("#.##", DecimalFormatSymbols.getInstance(Locale.US));
return decimalFormat.format(value * 100) + "%";
}

Expand Down Expand Up @@ -177,12 +193,23 @@ public void exportAsCsv(String filename) throws IOException {

}

public void exportAsHtml(String filename) throws IOException, ClassNotFoundException {
Map<Object, Object> binding = new HashMap<Object, Object>();
binding.put("coverage", this);
URL templateUrl = Coverage.class.getResource(HTML_TEMPLATE);
SimpleTemplateEngine engine = new SimpleTemplateEngine();
Writable template = engine.createTemplate(templateUrl).make(binding);
FileUtil.write(new File(filename), template);
}

public static class CoverageItem {

private File file;

private boolean covered = false;

//TODO: add number of tests??

public CoverageItem(File file, boolean covered) {
this.file = file;
this.covered = covered;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.min.css">
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.min.js"></script>
<script>
\$(document).ready(function() {
\$('#fileTable').DataTable({
"pageLength": 50
});
});
</script>
</head>
<body>
<div class="container">
<h1>Coverage Report</h1>
<p>This report was generated by <a href="https://www.nf-test.com">nf-test</a> on <%= new Date() %>.</p>
<p>
Coverage: <span class="badge <%= coverage.getCoverage() < 0.5 ? 'bg-danger' : (coverage.getCoverage() < 0.9 ? 'bg-warning' : 'bg-success') %>"><%= coverage.formatCoverage(coverage.getCoverage()) %></span>
</p>

<div class="progress bg-danger">
<div class="progress-bar bg-success" role="progressbar" style="width: <%= coverage.formatCoverage(coverage.getCoverage()) %>;" aria-valuenow="<%= coverage.formatCoverage(coverage.getCoverage()) %>" aria-valuemin="0" aria-valuemax="100"></div>
</div>

<hr>

<table id="fileTable" class="table table-bordered table-striped table-sm">
<thead>
<tr>
<th>File</th>
<th>Covered</th>
</tr>
</thead>
<tbody>
<% coverage.items.each { item -> %>
<tr class="<%= item.isCovered() ? 'table-success' : 'table-danger' %>">
<td><%= coverage.getFileLabel(item.getFile()) %></td>
<td><%= item.isCovered() %></td>
</tr>
<% } %>
</tbody>
</table>
</div>
</body>
</html>

0 comments on commit 5bfd088

Please sign in to comment.