Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
[versions]
aspectj-version = "1.9.24"
byteBuddy-version = "1.17.7"
gsonVersion = "2.13.2"
guavaVersion = "33.4.8-jre"
gson-version = "2.13.2"
guava-version = "33.4.8-jre"
jakarta-version = "3.0.0"
junit4-version = "4.13.2"
paranamerVersion = "2.8.3"
mockito-version = "5.18.0"
paranamer-version = "2.8.3"
slf4j-version = "2.0.17"
spring-version = "6.2.11"
androidx-test-version = "1.7.0"
Expand All @@ -22,8 +23,8 @@ aspectj-jrt = { module = "org.aspectj:aspectjrt", version.ref = "aspectj-version
aspectj-jweaver = { module = "org.aspectj:aspectjweaver", version.ref = "aspectj-version" }
byteBuddy = { module = "net.bytebuddy:byte-buddy", version.ref = "byteBuddy-version" }
byteBuddy-agent = { module = "net.bytebuddy:byte-buddy-agent", version.ref = "byteBuddy-version" }
gson = { module = "com.google.code.gson:gson", version.ref = "gsonVersion" }
guava = { module = "com.google.guava:guava", version.ref = "guavaVersion" }
gson = { module = "com.google.code.gson:gson", version.ref = "gson-version" }
guava = { module = "com.google.guava:guava", version.ref = "guava-version" }
hypersql-database = { module = "org.hsqldb:hsqldb", version = "2.7.4" }
jakarta-annotation = { module = "jakarta.annotation:jakarta.annotation-api", version.ref = "jakarta-version" }
junit-bom = { module = "org.junit:junit-bom", version = "5.13.4" }
Expand All @@ -32,7 +33,8 @@ junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher
junit4 = { module = "junit:junit", version.ref = "junit4-version" }
junit4-dataprovider = { module = "com.tngtech.java:junit-dataprovider", version = "1.13.1" }
junit4-params = { module = "pl.pragmatists:JUnitParams", version = "1.1.1" }
paranamer = { module = "com.thoughtworks.paranamer:paranamer", version.ref = "paranamerVersion" }
mockito = { module = "org.mockito:mockito-core", version.ref = "mockito-version" }
paranamer = { module = "com.thoughtworks.paranamer:paranamer", version.ref = "paranamer-version" }
publish = { module = "com.vanniktech.maven.publish:com.vanniktech.maven.publish.gradle.plugin", version.ref = "vanniktech-version" }
quickcheck = { module = "net.java.quickcheck:quickcheck", version = "0.6" }
slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j-version" }
Expand Down
5 changes: 5 additions & 0 deletions jgiven-asciidoc-report/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# AsciiDoc Report

This plug-in will generate test reports in the [AsciiDoc](https://asciidoc.org/) format.
It thus combines the simplicity of plain text with lean markup elements for structure, links etc.
Easily convertible to formats like HTML or PDF.
10 changes: 10 additions & 0 deletions jgiven-asciidoc-report/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
plugins {
id 'java-library'
id 'jgiven-publishing'
}

dependencies {
implementation libs.guava
implementation libs.slf4j.api
implementation project(':jgiven-core')
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
import com.tngtech.jgiven.report.model.ReportStatistics;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -101,7 +99,7 @@ private void writeFeatureFiles() {
completeReportModel.getAllReportModels().stream()
.sorted(Comparator.comparing(AsciiDocReportGenerator::byFeatureName))
.forEach(reportModelFile -> {
final String featureFileName = Files.getNameWithoutExtension(
final var featureFileName = Files.getNameWithoutExtension(
reportModelFile.file().getName()) + ".asciidoc";
writeAsciiDocBlocksToFile(new File(featuresDir, featureFileName),
collectReportBlocks(reportModelFile, featureFileName));
Expand All @@ -111,7 +109,7 @@ private void writeFeatureFiles() {
private List<String> collectReportBlocks(final ReportModelFile reportModelFile, final String featureFileName) {
featureFiles.add(featureFileName);

final ReportStatistics statistics = completeReportModel.getStatistics(reportModelFile);
final var statistics = completeReportModel.getStatistics(reportModelFile);
if (statistics.numFailedScenarios > 0) {
failedScenarioFiles.add(featureFileName);
}
Expand All @@ -122,14 +120,14 @@ private List<String> collectReportBlocks(final ReportModelFile reportModelFile,
abortedScenarioFiles.add(featureFileName);
}

final AsciiDocReportModelVisitor visitor = new AsciiDocReportModelVisitor(blockConverter, statistics);
final var visitor = new AsciiDocReportModelVisitor(blockConverter, statistics);
reportModelFile.model().accept(visitor);

return visitor.getResult();
}

private void writeIndexFileForAllScenarios() {
final AsciiDocSnippetGenerator snippetGenerator = new AsciiDocSnippetGenerator(
final var snippetGenerator = new AsciiDocSnippetGenerator(
"All Scenarios", "scenarios in total", this.featureFiles, "",
this.completeReportModel.getTotalStatistics().numScenarios);

Expand All @@ -138,8 +136,8 @@ private void writeIndexFileForAllScenarios() {
}

private void writeIndexFileForFailedScenarios() {
final String scenarioKind = "failed";
final AsciiDocSnippetGenerator snippetGenerator = new AsciiDocSnippetGenerator(
final var scenarioKind = "failed";
final var snippetGenerator = new AsciiDocSnippetGenerator(
"Failed Scenarios", "failed scenarios", this.failedScenarioFiles, scenarioKind,
this.completeReportModel.getTotalStatistics().numFailedScenarios);

Expand All @@ -148,8 +146,8 @@ private void writeIndexFileForFailedScenarios() {
}

private void writeIndexFileForPendingScenarios() {
final String scenarioKind = "pending";
final AsciiDocSnippetGenerator snippetGenerator = new AsciiDocSnippetGenerator(
final var scenarioKind = "pending";
final var snippetGenerator = new AsciiDocSnippetGenerator(
"Pending Scenarios", "pending scenarios", this.pendingScenarioFiles, scenarioKind,
this.completeReportModel.getTotalStatistics().numPendingScenarios);

Expand All @@ -158,8 +156,8 @@ private void writeIndexFileForPendingScenarios() {
}

private void writeIndexFileForAbortedScenarios() {
final String scenarioKind = "aborted";
final AsciiDocSnippetGenerator snippetGenerator = new AsciiDocSnippetGenerator(
final var scenarioKind = "aborted";
final var snippetGenerator = new AsciiDocSnippetGenerator(
"Aborted Scenarios", "aborted scenarios", this.abortedScenarioFiles, scenarioKind,
this.completeReportModel.getTotalStatistics().numAbortedScenarios);

Expand All @@ -176,19 +174,19 @@ private void writeTotalStatisticsFile() {
completeReportModel::getStatistics,
MultimapBuilder.hashKeys().arrayListValues()::build));

final String statisticsBlock = blockConverter.convertStatisticsBlock(
final var statisticsBlock = blockConverter.convertStatisticsBlock(
featureStatistics, completeReportModel.getTotalStatistics());

writeAsciiDocBlocksToFile(new File(targetDir, "totalStatistics.asciidoc"),
Collections.singletonList(statisticsBlock));
}

private void writeIndexFileForFullReport(final String reportTitle) {
final URL resourceUrl = Resources.getResource(this.getClass(), "index.asciidoc");
final var resourceUrl = Resources.getResource(this.getClass(), "index.asciidoc");
try {
final List<String> indexLines = Resources.readLines(resourceUrl, Charset.defaultCharset());
final var indexLines = Resources.readLines(resourceUrl, Charset.defaultCharset());

try (PrintWriter writer = PrintWriterUtil.getPrintWriter(new File(targetDir, "index.asciidoc"))) {
try (var writer = PrintWriterUtil.getPrintWriter(new File(targetDir, "index.asciidoc"))) {
writer.println("= " + reportTitle);
indexLines.forEach(writer::println);
}
Expand All @@ -212,7 +210,7 @@ private static String byFeatureName(ReportModelFile modelFile) {
}

private static void writeAsciiDocBlocksToFile(final File file, final List<String> asciiDocBlocks) {
try (final PrintWriter writer = PrintWriterUtil.getPrintWriter(file)) {
try (final var writer = PrintWriterUtil.getPrintWriter(file)) {
for (final String block : asciiDocBlocks) {
writer.println(block);
writer.println();
Expand Down
1 change: 1 addition & 0 deletions jgiven-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ dependencies {
implementation libs.byteBuddy
implementation 'org.fusesource.jansi:jansi:2.4.2'

testImplementation libs.mockito
testImplementation 'com.github.stefanbirkner:system-rules:1.19.0'
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@

import com.tngtech.jgiven.exception.JGivenInstallationException;
import com.tngtech.jgiven.exception.JGivenInternalDefectException;
import com.tngtech.jgiven.report.asciidoc.AsciiDocReportGenerator;
import com.tngtech.jgiven.report.config.ConfigOptionParser;
import com.tngtech.jgiven.report.text.PlainTextReportGenerator;

import java.util.Arrays;

/**
* This is an interface to create a report based on command line flags
*/
public class ReportGenerator {
/**
private static final String ASCIIDOC_GENERATOR_FQCN = "com.tngtech.jgiven.report.asciidoc.AsciiDocReportGenerator";
private static final String HTML5_REPORT_GENERATOR_FQCN = "com.tngtech.jgiven.report.html5.Html5ReportGenerator";

/**
* to create a custom report, extend this enum with the name of your choice
*/
public enum Format {
Expand Down Expand Up @@ -43,39 +44,32 @@ public String formatName() {
* Starts the respective report (default is HTML5)
*/
public void generate( String... args ) {
Format format = ConfigOptionParser.getFormat( args );
var format = ConfigOptionParser.getFormat( args );
switch( format ) {
case ASCIIDOC:
new AsciiDocReportGenerator().generateFromCommandLine( args );
loadReportGenerator(ASCIIDOC_GENERATOR_FQCN).generateFromCommandLine(args);
break;
case TEXT:
new PlainTextReportGenerator().generateFromCommandLine( args );
break;
case HTML:
case HTML5:
case HTML, HTML5:
default:
ReportGenerator.generateHtml5Report().generateFromCommandLine( args );
loadReportGenerator(HTML5_REPORT_GENERATOR_FQCN).generateFromCommandLine(args);
break;
}
}

/**
* Searches the Html5ReportGenerator in Java path and instantiates the report
*/
public static AbstractReportGenerator generateHtml5Report() {
AbstractReportGenerator report;
private static AbstractReportGenerator loadReportGenerator(String fqcn) {
try {
Class<?> aClass = ReportGenerator.class.getClassLoader()
.loadClass( "com.tngtech.jgiven.report.html5.Html5ReportGenerator" );
report = (AbstractReportGenerator) aClass.getDeclaredConstructor().newInstance();
Class<?> aClass = ReportGenerator.class.getClassLoader().loadClass(fqcn);
return (AbstractReportGenerator) aClass.getDeclaredConstructor().newInstance();
} catch( ClassNotFoundException e ) {
throw new JGivenInstallationException( "The JGiven HTML5 Report Generator seems not to be on the classpath.\n"
+ "Ensure that you have a dependency to jgiven-html5-report." );
throw new JGivenInstallationException( "The requested JGiven report generator seems not to be on the classpath.\n"
+ "Ensure that you have a dependency to the corresponding plugin." );
} catch( Exception e ) {
throw new JGivenInternalDefectException( "The HTML5 Report Generator could not be instantiated.", e );
throw new JGivenInternalDefectException( "The report generator could not be instantiated.", e );
}
return report;
}
}

public static void main( String... args ) {
new ReportGenerator().generate( args );
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.tngtech.jgiven.report;

import com.tngtech.jgiven.report.config.ConfigOption;
import java.io.File;
import java.util.List;
import java.util.Map;
import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class ReportConfigArgumentTest {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the former ReportGeneratorArgumentTest (next file; deleted). Like the test further down after that, it does not really require the asciidoc reporter, so I replaced it with anonymous classes. It might be worthwhile extracting those or moving/renaming the tests to signify that they are really testing the AbstractReportConfig and AbstractReportGenerator, respectively.


@Test
public void testArgumentParsing() {
var testConfig = new AbstractReportConfig("--sourceDir=source/dir", "--targetDir=target/dir") {

@Override
public void useConfigMap(Map<String, Object> configMap) {
}

@Override
public void additionalConfigOptions(List<ConfigOption> configOptions) {
}
};

assertThat(testConfig.getSourceDir()).isEqualTo(new File("source/dir"));
assertThat(testConfig.getTargetDir()).isEqualTo(new File("target/dir"));
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.tngtech.jgiven.report.json;

import com.google.common.base.Charsets;
import com.google.common.io.Files;
import com.tngtech.jgiven.exception.JGivenWrongUsageException;
import com.tngtech.jgiven.report.AbstractReportConfig;
import java.io.File;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class ReportModelReaderTest {

@Rule
public final TemporaryFolder tmpFolder = new TemporaryFolder();

@Mock
private AbstractReportConfig config;

@Test
public void wrong_json_files_are_handled_gracefully() throws Exception {
var folder = tmpFolder.newFolder();

Files.asCharSink( new File( folder, "wrong.json" ), Charsets.UTF_8 ).write( "no json");

when(config.getSourceDir()).thenReturn(tmpFolder.getRoot());
var reportModelReader = new ReportModelReader(config);

assertThatThrownBy(reportModelReader::readDirectory).isInstanceOf(JGivenWrongUsageException.class)
.hasMessageContaining("Error while reading file");
}
}
1 change: 1 addition & 0 deletions jgiven-gradle-plugin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ plugins {
dependencies {
implementation localGroovy() //we're a gradle plugin, we want to use the same groovy version as gradle
implementation project(':jgiven-core')
implementation project(':jgiven-asciidoc-report')
implementation project(':jgiven-html5-report')
implementation(platform(libs.junit.bom))
implementation(libs.jakarta.annotation)
Expand Down
Loading