From 6c20ab9a9339f52a887d68d2468bdffa492c11a0 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Tue, 12 Nov 2024 17:44:15 +0100 Subject: [PATCH 01/10] Fix name of integration test class --- pom.xml | 3 --- ...raceMojoVerifierTest.java => TraceMojoIT.java} | 15 ++++++++------- 2 files changed, 8 insertions(+), 10 deletions(-) rename src/test/java/org/itsallcode/openfasttrace/maven/{TraceMojoVerifierTest.java => TraceMojoIT.java} (96%) diff --git a/pom.xml b/pom.xml index 136d485..65caaff 100644 --- a/pom.xml +++ b/pom.xml @@ -468,9 +468,6 @@ maven-failsafe-plugin 3.4.0 - - **VerifierTest.java - true src/test/resources/logging.properties diff --git a/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoVerifierTest.java b/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoIT.java similarity index 96% rename from src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoVerifierTest.java rename to src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoIT.java index b76f574..12e60a0 100644 --- a/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoVerifierTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoIT.java @@ -19,9 +19,9 @@ import com.exasol.mavenpluginintegrationtesting.MavenIntegrationTestEnvironment; -class TraceMojoVerifierTest +class TraceMojoIT { - private static final Logger LOG = Logger.getLogger(TraceMojoVerifierTest.class.getName()); + private static final Logger LOG = Logger.getLogger(TraceMojoIT.class.getName()); private static final Path BASE_TEST_DIR = Paths.get("src/test/resources").toAbsolutePath(); private static final String CURRENT_PLUGIN_VERSION = getCurrentProjectVersion(); private static final String OFT_GOAL = "org.itsallcode:openfasttrace-maven-plugin:" + CURRENT_PLUGIN_VERSION @@ -42,7 +42,8 @@ class TraceMojoVerifierTest .resolve("project-with-tracing-defects-fail-build"); private static final Path HTML_REPORT_PROJECT = BASE_TEST_DIR .resolve("html-report"); - public static final Path PARTIAL_ARTIFACT_COVERAGE_PROJECT = BASE_TEST_DIR.resolve("project-with-partial-artifact-coverage"); + public static final Path PARTIAL_ARTIFACT_COVERAGE_PROJECT = BASE_TEST_DIR + .resolve("project-with-partial-artifact-coverage"); private static MavenIntegrationTestEnvironment mvnITEnv; @BeforeAll @@ -65,8 +66,8 @@ void testTracingWithMultipleLanguages() throws Exception verifier.setCliOptions(List.of("-pl .")); verifier.executeGoals(List.of("generate-sources", "generate-test-sources", OFT_GOAL)); verifier.verifyErrorFreeLog(); - assertThat(fileContent(PROJECT_WITH_MULTIPLE_LANGUAGES.resolve("target/tracing-report.txt")) - , equalTo("ok - 8 total\n")); + assertThat(fileContent(PROJECT_WITH_MULTIPLE_LANGUAGES.resolve("target/tracing-report.txt")), + equalTo("ok - 8 total\n")); } @Test @@ -173,7 +174,7 @@ void testTracingFindsDefectsFailBuild() () -> runTracingMojo(TRACING_DEFECTS_FAIL_BUILD)); assertAll(() -> assertThat(exception.getMessage(), containsString("Tracing found 1 defects out of 2 items")), () -> assertThat(fileContent(TRACING_DEFECTS_FAIL_BUILD.resolve("target/tracing-report.txt")), - containsString("not ok - 2 total, 1 defect"))); + containsString("not ok - 2 total, 1 defect"))); } @Test @@ -183,7 +184,7 @@ void testHtmlReport() throws Exception final String content = fileContent(HTML_REPORT_PROJECT.resolve("target/tracing-report.html")); assertAll(() -> assertThat(content, containsString(" 3 total")), - () ->assertThat(content, containsString("
"))); + () -> assertThat(content, containsString("
"))); } @Test From b0568e50249be24b1f405648a80b772eaf33c667 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Tue, 12 Nov 2024 17:55:58 +0100 Subject: [PATCH 02/10] Upgrade dependencies --- pom.xml | 25 ++++++++--------- .../openfasttrace/maven/TraceMojo.java | 27 ++++++++++--------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/pom.xml b/pom.xml index 65caaff..d7eeb1d 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ 4.1.0 3.8.7 true - 5.11.0 + 5.11.3 0.8.12 itsallcode https://sonarcloud.io @@ -98,7 +98,7 @@ org.apache.maven.plugin-tools maven-plugin-annotations - 3.13.1 + 3.15.1 provided @@ -118,7 +118,7 @@ commons-io commons-io - 2.16.1 + 2.17.0 test @@ -199,7 +199,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.2.5 + 3.2.7 sign-artifacts @@ -322,7 +322,7 @@ org.apache.maven.plugins maven-plugin-plugin - 3.14.0 + 3.15.1 openfasttrace false @@ -365,7 +365,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.8.0 + 3.11.1 attach-javadocs @@ -379,7 +379,7 @@ true true - + false @@ -433,7 +433,7 @@ org.apache.maven.plugins maven-dependency-plugin - 3.7.1 + 3.8.1 copy-jacoco @@ -453,11 +453,8 @@ org.apache.maven.plugins maven-surefire-plugin - 3.4.0 + 3.5.2 - - **VerifierTest.java - src/test/resources/logging.properties @@ -466,7 +463,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 3.4.0 + 3.5.2 true @@ -550,7 +547,7 @@ org.apache.maven.plugins maven-artifact-plugin - 3.5.1 + 3.5.3 verify-reproducible-build diff --git a/src/main/java/org/itsallcode/openfasttrace/maven/TraceMojo.java b/src/main/java/org/itsallcode/openfasttrace/maven/TraceMojo.java index 5db9532..a9518d5 100644 --- a/src/main/java/org/itsallcode/openfasttrace/maven/TraceMojo.java +++ b/src/main/java/org/itsallcode/openfasttrace/maven/TraceMojo.java @@ -5,26 +5,25 @@ import java.io.*; import java.nio.file.Files; import java.nio.file.Path; -import java.util.List; -import java.util.Optional; -import java.util.Set; +import java.util.*; import java.util.stream.Stream; +import javax.inject.Inject; + import org.apache.maven.execution.MavenSession; import org.apache.maven.model.Resource; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.*; import org.apache.maven.project.*; -import org.itsallcode.openfasttrace.api.DetailsSectionDisplay; -import org.itsallcode.openfasttrace.api.FilterSettings; -import org.itsallcode.openfasttrace.api.ReportSettings; +import org.itsallcode.openfasttrace.api.*; import org.itsallcode.openfasttrace.api.core.*; import org.itsallcode.openfasttrace.api.importer.ImportSettings; import org.itsallcode.openfasttrace.api.report.ReportVerbosity; import org.itsallcode.openfasttrace.core.Oft; import org.itsallcode.openfasttrace.core.OftRunner; + /** * Trace requirements using * OpenFastTrace. @@ -114,19 +113,21 @@ public class TraceMojo extends AbstractMojo @Parameter(defaultValue = "${project}", readonly = true) private MavenProject project; - @Component - private ProjectBuilder mavenProjectBuilder; - @Parameter(defaultValue = "${session}", readonly = true) private MavenSession session; + private final ProjectBuilder mavenProjectBuilder; /** - * Create a new instance + * Create a new instance. + * + * @param mavenProjectBuilder + * maven project builder */ - public TraceMojo() + @Inject + public TraceMojo(final ProjectBuilder mavenProjectBuilder) { - // Added default constructor to fix javadoc warning + this.mavenProjectBuilder = mavenProjectBuilder; } @Override @@ -230,7 +231,7 @@ private ImportSettings createImportSettings() } if (artifactTypes != null) { - FilterSettings filterSettings = FilterSettings.builder() + final FilterSettings filterSettings = FilterSettings.builder() .artifactTypes(artifactTypes) .build(); settings.filter(filterSettings); From 3dabb73814079db2fd61d36d96ae64be66a71f83 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Tue, 12 Nov 2024 17:59:58 +0100 Subject: [PATCH 03/10] Add changelog entry --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1984e5b..f72fde7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.3.0] - 2024-11-12 + +- [#70](https://github.com/itsallcode/openfasttrace-maven-plugin/issues/70) Add support for OFT's command line option `--wanted-tags` +- [PR #71](https://github.com/itsallcode/openfasttrace-maven-plugin/pull/71) Upgrade dependencies and plugins, minor refactoring. + ## [2.2.0] - 2024-08-21 - [PR #66](https://github.com/itsallcode/openfasttrace-maven-plugin/issues/66) Add filter for artifact types. From b74cfddbbfa1a5c080c54dc198857e04d86c9005 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Tue, 12 Nov 2024 18:00:22 +0100 Subject: [PATCH 04/10] Deactivate scheduled execution of CodeQL --- .github/workflows/codeql-analysis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 57aeae1..12f006d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -5,8 +5,6 @@ on: branches: [ main ] pull_request: branches: [ main ] - schedule: - - cron: '0 4 * * 3' jobs: analyze: From e03b4f29430b6bbe7efb3b3f74c5afc07e6bb55f Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Wed, 13 Nov 2024 06:29:31 +0100 Subject: [PATCH 05/10] Add unit tests --- pom.xml | 12 +++ .../openfasttrace/maven/TraceMojo.java | 24 ++++- .../openfasttrace/maven/TraceMojoTest.java | 99 +++++++++++++++++++ 3 files changed, 130 insertions(+), 5 deletions(-) create mode 100644 src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoTest.java diff --git a/pom.xml b/pom.xml index d7eeb1d..01a6c1d 100644 --- a/pom.xml +++ b/pom.xml @@ -171,6 +171,18 @@ ${junit.version} test + + org.mockito + mockito-junit-jupiter + 5.14.2 + test + + + org.itsallcode + hamcrest-auto-matcher + 0.8.1 + test + org.jacoco org.jacoco.agent diff --git a/src/main/java/org/itsallcode/openfasttrace/maven/TraceMojo.java b/src/main/java/org/itsallcode/openfasttrace/maven/TraceMojo.java index a9518d5..b137121 100644 --- a/src/main/java/org/itsallcode/openfasttrace/maven/TraceMojo.java +++ b/src/main/java/org/itsallcode/openfasttrace/maven/TraceMojo.java @@ -100,7 +100,7 @@ public class TraceMojo extends AbstractMojo * match the specified types will be imported. */ @Parameter(property = "artifactTypes") - private Set artifactTypes; + Set artifactTypes; /** * Skip running OFT. @@ -130,6 +130,20 @@ public TraceMojo(final ProjectBuilder mavenProjectBuilder) this.mavenProjectBuilder = mavenProjectBuilder; } + /** + * Constructor used in unit tests. + * + * @param mavenProjectBuilder + * maven project builder + * @param project + * maven project + */ + TraceMojo(final ProjectBuilder mavenProjectBuilder, final MavenProject project) + { + this(mavenProjectBuilder); + this.project = project; + } + @Override public void execute() throws MojoFailureException { @@ -217,7 +231,7 @@ private static void createDir(final Path path) } } - private ImportSettings createImportSettings() + ImportSettings createImportSettings() { final List sourcePaths = getSourcePaths(); logSourcePaths(sourcePaths); @@ -285,15 +299,15 @@ private List getSourcePathOfProject(final MavenProject mavenProject) final List compileSourceRoots = mavenProject.getCompileSourceRoots(); final List testCompileSourceRoots = mavenProject.getTestCompileSourceRoots(); final List resourceDirs = mavenProject.getResources().stream().map(Resource::getDirectory) - .collect(toList()); + .toList(); final List testResourceDirs = mavenProject.getTestResources().stream().map(Resource::getDirectory) - .collect(toList()); + .toList(); final Stream sourcePaths = Stream .of(compileSourceRoots, resourceDirs, testCompileSourceRoots, testResourceDirs) .flatMap(List::stream) .map(Path::of) .filter(Files::exists); - return Stream.concat(sourcePathsOfSubModules, sourcePaths).collect(toList()); + return Stream.concat(sourcePathsOfSubModules, sourcePaths).toList(); } private Optional getProjectSubPath(final String dir) diff --git a/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoTest.java b/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoTest.java new file mode 100644 index 0000000..815c224 --- /dev/null +++ b/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoTest.java @@ -0,0 +1,99 @@ +package org.itsallcode.openfasttrace.maven; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Set; + +import org.apache.maven.model.Resource; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.ProjectBuilder; +import org.itsallcode.matcher.auto.AutoMatcher; +import org.itsallcode.openfasttrace.api.FilterSettings; +import org.itsallcode.openfasttrace.api.importer.ImportSettings; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.io.TempDir; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class TraceMojoTest +{ + @Mock + ProjectBuilder mavenProjectBuilderMock; + @Mock + MavenProject projectMock; + @TempDir + Path baseDir; + + @Test + void createDefaultImportSettings() + { + final TraceMojo testee = testee(); + testee.artifactTypes = null; + assertThat(testee.createImportSettings(), AutoMatcher.equalTo(ImportSettings.builder().build())); + } + + @Test + void createImportSettingsAddsSourceRootPaths() throws IOException + { + final TraceMojo testee = testee(); + final Path compileSrcPath = baseDir.resolve("src"); + final Path testCompileSrcPath = baseDir.resolve("test"); + Files.createDirectories(compileSrcPath); + Files.createDirectories(testCompileSrcPath); + when(projectMock.getCompileSourceRoots()).thenReturn(List.of(compileSrcPath.toString())); + when(projectMock.getTestCompileSourceRoots()).thenReturn(List.of(testCompileSrcPath.toString())); + assertThat(testee.createImportSettings(), + AutoMatcher.equalTo(ImportSettings.builder().addInputs(compileSrcPath, testCompileSrcPath).build())); + } + + @Test + void createImportSettingsAddsResourcesDir() throws IOException + { + final TraceMojo testee = testee(); + final Path resourcesPath = baseDir.resolve("res"); + Files.createDirectories(resourcesPath); + when(projectMock.getResources()).thenReturn(List.of(resource(resourcesPath))); + assertThat(testee.createImportSettings(), + AutoMatcher.equalTo(ImportSettings.builder().addInputs(resourcesPath).build())); + } + + private static Resource resource(final Path directory) + { + final Resource resource = new Resource(); + resource.setDirectory(directory.toString()); + return resource; + } + + @Test + void createImportSettingsAddsDocPath() throws IOException + { + final TraceMojo testee = testee(); + final Path docDir = baseDir.resolve("doc"); + Files.createDirectories(docDir); + assertThat(testee.createImportSettings(), + AutoMatcher.equalTo(ImportSettings.builder().addInputs(docDir).build())); + } + + @Test + void createImportSettingsWithArtifactTypes() + { + final TraceMojo testee = testee(); + testee.artifactTypes = Set.of("feat", "req"); + assertThat(testee.createImportSettings(), AutoMatcher.equalTo( + ImportSettings.builder().filter(FilterSettings.builder().artifactTypes(Set.of("feat", "req")).build()) + .build())); + } + + TraceMojo testee() + { + when(projectMock.getBasedir()).thenReturn(baseDir.toFile()); + return new TraceMojo(mavenProjectBuilderMock, projectMock); + } +} From 45e4e913d1c9185d1ebbab1274c6da6bb84e9a04 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Wed, 13 Nov 2024 09:12:41 +0100 Subject: [PATCH 06/10] Adapt eclipse config --- .settings/org.eclipse.jdt.core.prefs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index 6711c38..f6b15fb 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -106,7 +106,7 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.processAnnotations=enabled +org.eclipse.jdt.core.compiler.processAnnotations=disabled org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=17 org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false From 88f5428cf86d94d21c457507055e18c102cf7891 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Wed, 13 Nov 2024 13:04:43 +0100 Subject: [PATCH 07/10] #70: Add configuration option for tags --- README.md | 23 ++++- pom.xml | 2 +- .../openfasttrace/maven/TraceMojo.java | 55 +++++++++-- .../openfasttrace/maven/TraceMojoIT.java | 29 ++++++ .../openfasttrace/maven/TraceMojoTest.java | 96 +++++++++++++++---- .../resources/project-with-tags/doc/spec.md | 13 +++ src/test/resources/project-with-tags/pom.xml | 36 +++++++ 7 files changed, 225 insertions(+), 29 deletions(-) create mode 100644 src/test/resources/project-with-tags/doc/spec.md create mode 100644 src/test/resources/project-with-tags/pom.xml diff --git a/README.md b/README.md index 4585bc5..ac60f00 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ Add the openfasttrace-maven-plugin to your `pom.xml`: true COLLAPSE feat,req + prototype,mvp ``` @@ -62,7 +63,7 @@ See [src/test/resources/empty-project](src/test/resources/simple-project/) for a ### OpenFastTrace Plugins -You can use OpenFastTrace plugins to import and export requirements in additional formats. Include plugins by adding them as a dependency to the `openfasttrace-maven-plugin`, see [project-with-plugins](src/test/resources/project-with-plugins) as an example. +You can use OpenFastTrace plugins to import and export requirements in additional formats. Include plugins by adding them as a dependency to the `openfasttrace-maven-plugin`, see [project-with-plugins](./src/test/resources/project-with-plugins) as an example. ```xml @@ -153,11 +154,13 @@ You can add additional resource directories using the [Maven Resources Plugin](h ``` -#### Selecting the Imported ArtifactTypes +#### Selecting the Imported Specification Items Sometimes you don't want to trace the whole requirement chain. Instead, you are interested in the consistency of a subset. For instance, if you need to deliver a system requirement specification to another team, your job is to assure that the document is consistent in itself. -For those cases you can add an include list to the configuration that explicitly lists all artifact types to be imported. Note that this also affects which required coverage is imported — which is exactly what you want in this situation. +For those cases you can add an include list to the configuration that explicitly lists all artifact types or tags to be imported. Note that this also affects which required coverage is imported — which is exactly what you want in this situation. + +##### Select Artifact Types The following example configuration limits import to artifact types `feat` and `req`. @@ -167,6 +170,20 @@ The following example configuration limits import to artifact types `feat` and ` ``` +##### Select Tags + +The following example configuration limits import to tags `prototype` and `mvp`. + +```xml + + prototype,mvp + +``` + +You can also specify the underscore `_` to import specification items without tags. + +You can also specify the tags on the command line: `-Dtags=prototype,mvp` + #### Report ##### Report Format diff --git a/pom.xml b/pom.xml index 01a6c1d..f987cee 100644 --- a/pom.xml +++ b/pom.xml @@ -180,7 +180,7 @@ org.itsallcode hamcrest-auto-matcher - 0.8.1 + 0.8.2 test diff --git a/src/main/java/org/itsallcode/openfasttrace/maven/TraceMojo.java b/src/main/java/org/itsallcode/openfasttrace/maven/TraceMojo.java index b137121..2e6aab9 100644 --- a/src/main/java/org/itsallcode/openfasttrace/maven/TraceMojo.java +++ b/src/main/java/org/itsallcode/openfasttrace/maven/TraceMojo.java @@ -1,5 +1,6 @@ package org.itsallcode.openfasttrace.maven; +import static java.util.Collections.emptySet; import static java.util.stream.Collectors.toList; import java.io.*; @@ -23,7 +24,6 @@ import org.itsallcode.openfasttrace.core.Oft; import org.itsallcode.openfasttrace.core.OftRunner; - /** * Trace requirements using * OpenFastTrace. @@ -31,6 +31,8 @@ @Mojo(name = "trace", defaultPhase = LifecyclePhase.VERIFY, threadSafe = true) public class TraceMojo extends AbstractMojo { + private static final String WILDCARD_TAG = "_"; + /** * Location of the directory where the reports are generated. *

@@ -98,10 +100,23 @@ public class TraceMojo extends AbstractMojo * will be applied. *

  • If the artifactTypes set is not null, only artifacts with types that * match the specified types will be imported.
  • + * */ @Parameter(property = "artifactTypes") Set artifactTypes; - + + /** + * Determines which tags should be imported. + *

    + * Import only specification items that have at least one of the listed + * tags. If you add a single underscore {@code _}, specification items that + * have no tags at all are also imported. + *

    + * Default: Import all specification items. + */ + @Parameter(property = "tags") + Set tags; + /** * Skip running OFT. *

    @@ -243,14 +258,38 @@ ImportSettings createImportSettings() getLog().info("Tracing doc directory " + docPath.get()); settings.addInputs(docPath.get()); } - if (artifactTypes != null) + final FilterSettings filterSettings = FilterSettings.builder() + .artifactTypes(getFilteredArtifactTypes()) + .tags(getFilteredTags()) + .withoutTags(isFilterWithoutTags()) + .build(); + settings.filter(filterSettings); + return settings.build(); + } + + private Set getFilteredArtifactTypes() + { + return artifactTypes == null ? emptySet() : artifactTypes; + } + + private Set getFilteredTags() + { + if (tags == null) { - final FilterSettings filterSettings = FilterSettings.builder() - .artifactTypes(artifactTypes) - .build(); - settings.filter(filterSettings); + return emptySet(); } - return settings.build(); + final Set copy = new HashSet<>(tags); + copy.remove(WILDCARD_TAG); + return copy; + } + + private boolean isFilterWithoutTags() + { + if (tags == null || tags.isEmpty()) + { + return true; + } + return tags.contains(WILDCARD_TAG); } private void logSourcePaths(final List sourcePaths) diff --git a/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoIT.java b/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoIT.java index 12e60a0..df542e6 100644 --- a/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoIT.java +++ b/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoIT.java @@ -16,6 +16,8 @@ import org.apache.maven.it.Verifier; import org.hamcrest.MatcherAssert; import org.junit.jupiter.api.*; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; import com.exasol.mavenpluginintegrationtesting.MavenIntegrationTestEnvironment; @@ -37,6 +39,7 @@ class TraceMojoIT private static final Path EMPTY_PROJECT = BASE_TEST_DIR.resolve("empty-project"); private static final Path SIMPLE_PROJECT = BASE_TEST_DIR.resolve("simple-project"); private static final Path PROJECT_WITH_PLUGINS = BASE_TEST_DIR.resolve("project-with-plugins"); + private static final Path PROJECT_WITH_TAGS = BASE_TEST_DIR.resolve("project-with-tags"); private static final Path TRACING_DEFECTS = BASE_TEST_DIR.resolve("project-with-tracing-defects"); private static final Path TRACING_DEFECTS_FAIL_BUILD = BASE_TEST_DIR .resolve("project-with-tracing-defects-fail-build"); @@ -210,6 +213,32 @@ void testTracingSelectedArtifactTypes() throws Exception equalTo("ok - 2 total\n")); } + @ParameterizedTest(name = "wanted tags {0} finds {1} items") + @CsvSource(delimiter = ';', nullValues = "NULL", value = + { "NULL; 3", "tagA; 1", "tagB; 1", "tagA,tagB; 2", "tagA,tagB,_; 3", "tagC; 0" }) + void testTracingSelectedTags(final String tags, final int expectedItemCount) throws Exception + { + final Verifier verifier = mvnITEnv.getVerifier(PROJECT_WITH_TAGS); + verifier.addCliOption("-DfailBuild=false"); + if (tags != null) + { + verifier.addCliOption("-Dtags=" + tags); + } + verifier.executeGoal(OFT_GOAL); + verifier.verifyErrorFreeLog(); + final String expectedResult; + if (expectedItemCount > 0) + { + expectedResult = "not ok - %1$d total, %1$d defect".formatted(expectedItemCount); + } + else + { + expectedResult = "ok - 0 total"; + } + assertThat(fileContent(PROJECT_WITH_TAGS.resolve("target/tracing-report.txt")), + containsString(expectedResult)); + } + private static void runTracingMojo(final Path projectDir) throws Exception { final Verifier verifier = mvnITEnv.getVerifier(projectDir); diff --git a/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoTest.java b/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoTest.java index 815c224..8e006ce 100644 --- a/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoTest.java @@ -1,5 +1,6 @@ package org.itsallcode.openfasttrace.maven; +import static java.util.Collections.emptySet; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.when; @@ -15,6 +16,7 @@ import org.itsallcode.matcher.auto.AutoMatcher; import org.itsallcode.openfasttrace.api.FilterSettings; import org.itsallcode.openfasttrace.api.importer.ImportSettings; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.io.TempDir; @@ -31,10 +33,23 @@ class TraceMojoTest @TempDir Path baseDir; + TraceMojo testee; + + @BeforeEach + void setup() + { + this.testee = createMojo(); + } + + TraceMojo createMojo() + { + when(projectMock.getBasedir()).thenReturn(baseDir.toFile()); + return new TraceMojo(mavenProjectBuilderMock, projectMock); + } + @Test void createDefaultImportSettings() { - final TraceMojo testee = testee(); testee.artifactTypes = null; assertThat(testee.createImportSettings(), AutoMatcher.equalTo(ImportSettings.builder().build())); } @@ -42,26 +57,24 @@ void createDefaultImportSettings() @Test void createImportSettingsAddsSourceRootPaths() throws IOException { - final TraceMojo testee = testee(); final Path compileSrcPath = baseDir.resolve("src"); final Path testCompileSrcPath = baseDir.resolve("test"); Files.createDirectories(compileSrcPath); Files.createDirectories(testCompileSrcPath); when(projectMock.getCompileSourceRoots()).thenReturn(List.of(compileSrcPath.toString())); when(projectMock.getTestCompileSourceRoots()).thenReturn(List.of(testCompileSrcPath.toString())); - assertThat(testee.createImportSettings(), - AutoMatcher.equalTo(ImportSettings.builder().addInputs(compileSrcPath, testCompileSrcPath).build())); + + assertImportSettings(ImportSettings.builder().addInputs(compileSrcPath, testCompileSrcPath)); } @Test void createImportSettingsAddsResourcesDir() throws IOException { - final TraceMojo testee = testee(); final Path resourcesPath = baseDir.resolve("res"); Files.createDirectories(resourcesPath); when(projectMock.getResources()).thenReturn(List.of(resource(resourcesPath))); - assertThat(testee.createImportSettings(), - AutoMatcher.equalTo(ImportSettings.builder().addInputs(resourcesPath).build())); + + assertImportSettings(ImportSettings.builder().addInputs(resourcesPath)); } private static Resource resource(final Path directory) @@ -74,26 +87,75 @@ private static Resource resource(final Path directory) @Test void createImportSettingsAddsDocPath() throws IOException { - final TraceMojo testee = testee(); final Path docDir = baseDir.resolve("doc"); Files.createDirectories(docDir); - assertThat(testee.createImportSettings(), - AutoMatcher.equalTo(ImportSettings.builder().addInputs(docDir).build())); + + assertImportSettings(ImportSettings.builder().addInputs(docDir)); + } + + @Test + void createImportSettingsWithNullArtifactTypes() + { + testee.artifactTypes = null; + assertFilterSettings(FilterSettings.builder()); + } + + @Test + void createImportSettingsWithEmptyArtifactTypes() + { + testee.artifactTypes = emptySet(); + assertFilterSettings(FilterSettings.builder()); } @Test void createImportSettingsWithArtifactTypes() { - final TraceMojo testee = testee(); testee.artifactTypes = Set.of("feat", "req"); - assertThat(testee.createImportSettings(), AutoMatcher.equalTo( - ImportSettings.builder().filter(FilterSettings.builder().artifactTypes(Set.of("feat", "req")).build()) - .build())); + assertFilterSettings(FilterSettings.builder().artifactTypes(Set.of("feat", "req"))); } - TraceMojo testee() + @Test + void createImportSettingsWithNullTags() { - when(projectMock.getBasedir()).thenReturn(baseDir.toFile()); - return new TraceMojo(mavenProjectBuilderMock, projectMock); + testee.tags = null; + assertFilterSettings(FilterSettings.builder()); + } + + @Test + void createImportSettingsWithEmptyTags() + { + testee.tags = emptySet(); + assertFilterSettings(FilterSettings.builder()); + } + + @Test + void createImportSettingsWithTags() + { + testee.tags = Set.of("tag1", "tag2"); + assertFilterSettings(FilterSettings.builder().tags(Set.of("tag1", "tag2")).withoutTags(false)); + } + + @Test + void createImportSettingsWithWildcardTag() + { + testee.tags = Set.of("_", "tag1", "tag2"); + assertFilterSettings(FilterSettings.builder().tags(Set.of("tag1", "tag2")).withoutTags(true)); + } + + @Test + void createImportSettingsWithOnlyWildcardTag() + { + testee.tags = Set.of("_"); + assertFilterSettings(FilterSettings.builder().tags(emptySet()).withoutTags(true)); + } + + private void assertImportSettings(final ImportSettings.Builder importSettingsBuilder) + { + assertThat(testee.createImportSettings(), AutoMatcher.equalTo(importSettingsBuilder.build())); + } + + private void assertFilterSettings(final FilterSettings.Builder filterSettingsBuilder) + { + assertImportSettings(ImportSettings.builder().filter(filterSettingsBuilder.build())); } } diff --git a/src/test/resources/project-with-tags/doc/spec.md b/src/test/resources/project-with-tags/doc/spec.md new file mode 100644 index 0000000..25433a6 --- /dev/null +++ b/src/test/resources/project-with-tags/doc/spec.md @@ -0,0 +1,13 @@ +# Without Tag +`dsn~without-tag~1` +Needs: impl + +# With Tag A +`dsn~with-tag-a~1` +Tags: tagA +Needs: impl + +# With Tag B +`dsn~with-tag-b~1` +Tags: tagB +Needs: impl diff --git a/src/test/resources/project-with-tags/pom.xml b/src/test/resources/project-with-tags/pom.xml new file mode 100644 index 0000000..70e1448 --- /dev/null +++ b/src/test/resources/project-with-tags/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + + org.itsallcode + openfasttrace-maven-plugin-test + 0.0.0 + jar + + + 17 + 17 + UTF-8 + + + + + + org.itsallcode + openfasttrace-maven-plugin + + + trace-requirements + + trace + + + + + plain + + + + + From 82539f749c617affbd8ee4be58e13d77df527903 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Wed, 13 Nov 2024 13:10:26 +0100 Subject: [PATCH 08/10] Improve user guide --- CHANGELOG.md | 1 - README.md | 10 ++++++++-- .../org/itsallcode/openfasttrace/maven/TraceMojo.java | 3 +-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f72fde7..b0be730 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2.3.0] - 2024-11-12 - [#70](https://github.com/itsallcode/openfasttrace-maven-plugin/issues/70) Add support for OFT's command line option `--wanted-tags` -- [PR #71](https://github.com/itsallcode/openfasttrace-maven-plugin/pull/71) Upgrade dependencies and plugins, minor refactoring. ## [2.2.0] - 2024-08-21 diff --git a/README.md b/README.md index ac60f00..d0862fe 100644 --- a/README.md +++ b/README.md @@ -160,6 +160,8 @@ Sometimes you don't want to trace the whole requirement chain. Instead, you are For those cases you can add an include list to the configuration that explicitly lists all artifact types or tags to be imported. Note that this also affects which required coverage is imported — which is exactly what you want in this situation. +See the [OFT user guide on import options](https://github.com/itsallcode/openfasttrace/blob/main/doc/user_guide.md#import-options) for details. + ##### Select Artifact Types The following example configuration limits import to artifact types `feat` and `req`. @@ -170,6 +172,8 @@ The following example configuration limits import to artifact types `feat` and ` ``` +This works similar to OFT's command line argument `--wanted-artifact-types`. + ##### Select Tags The following example configuration limits import to tags `prototype` and `mvp`. @@ -180,9 +184,11 @@ The following example configuration limits import to tags `prototype` and `mvp`. ``` -You can also specify the underscore `_` to import specification items without tags. +This works similar to OFT's command line argument `--wanted-tags`. + +You can specify the underscore `_` to import specification items without tags. -You can also specify the tags on the command line: `-Dtags=prototype,mvp` +You can also specify the tags to import using CLI option `-Dtags=prototype,mvp`. #### Report diff --git a/src/main/java/org/itsallcode/openfasttrace/maven/TraceMojo.java b/src/main/java/org/itsallcode/openfasttrace/maven/TraceMojo.java index 2e6aab9..aa7be2d 100644 --- a/src/main/java/org/itsallcode/openfasttrace/maven/TraceMojo.java +++ b/src/main/java/org/itsallcode/openfasttrace/maven/TraceMojo.java @@ -1,7 +1,6 @@ package org.itsallcode.openfasttrace.maven; import static java.util.Collections.emptySet; -import static java.util.stream.Collectors.toList; import java.io.*; import java.nio.file.Files; @@ -299,7 +298,7 @@ private void logSourcePaths(final List sourcePaths) return; } final Path baseDir = project.getBasedir().toPath(); - final List relativePaths = sourcePaths.stream().map(baseDir::relativize).collect(toList()); + final List relativePaths = sourcePaths.stream().map(baseDir::relativize).toList(); getLog().info( "Tracing " + sourcePaths.size() + " sub-directories of base dir " + baseDir + ": " + relativePaths); From e807d63a393d511dd98340a3274342b5b3bd4199 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Wed, 13 Nov 2024 13:21:39 +0100 Subject: [PATCH 09/10] Fix release date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0be730..a084115 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [2.3.0] - 2024-11-12 +## [2.3.0] - 2024-11-13 - [#70](https://github.com/itsallcode/openfasttrace-maven-plugin/issues/70) Add support for OFT's command line option `--wanted-tags` From f9fbbed2b4d54e5ca0086f813ddc4ffe159830a8 Mon Sep 17 00:00:00 2001 From: kaklakariada Date: Wed, 13 Nov 2024 14:39:05 +0100 Subject: [PATCH 10/10] Implement review findings --- .../java/org/itsallcode/openfasttrace/maven/TraceMojoIT.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoIT.java b/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoIT.java index df542e6..5d7719a 100644 --- a/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoIT.java +++ b/src/test/java/org/itsallcode/openfasttrace/maven/TraceMojoIT.java @@ -215,7 +215,10 @@ void testTracingSelectedArtifactTypes() throws Exception @ParameterizedTest(name = "wanted tags {0} finds {1} items") @CsvSource(delimiter = ';', nullValues = "NULL", value = - { "NULL; 3", "tagA; 1", "tagB; 1", "tagA,tagB; 2", "tagA,tagB,_; 3", "tagC; 0" }) + { "NULL; 3", "tagA; 1", "tagB; 1", "tagA,tagB; 2", "tagA,tagB,_; 3", "tagC; 0", "_,tagA; 2", + // This should find 1 item but finds 3 due to a bug in OFT: + // https://github.com/itsallcode/openfasttrace/issues/432 + "_; 3" }) void testTracingSelectedTags(final String tags, final int expectedItemCount) throws Exception { final Verifier verifier = mvnITEnv.getVerifier(PROJECT_WITH_TAGS);