Skip to content

Add reusable ArchUnit rule and example project for coverage annotations#14

Merged
Arc-E-Tect merged 4 commits into
mainfrom
add-archunit-check-with-example
May 4, 2026
Merged

Add reusable ArchUnit rule and example project for coverage annotations#14
Arc-E-Tect merged 4 commits into
mainfrom
add-archunit-check-with-example

Conversation

@Arc-E-Tect

Copy link
Copy Markdown
Owner

What's Changed

  • Docs: Updated README.adoc:

    • Corrected version information in the 'Latest version' section.
    • Added documentation for enforcing justification conventions using test-fixtures.
    • Included an example project (jacoco-marker) with usage details.
  • Feature: Introduced test-fixtures artifact for ArchUnit conventions:

    • Simplifies enforcing non-blank justifications in @ExcludeFromJacocoGeneratedCodeCoverage annotations.
    • Added AbstractCoverageExclusionConventionsTest with extendable functionality for custom scenarios.
  • Feature: Added standalone jacoco-marker example project:

    • Demonstrates usage of @ExcludeFromJacocoGeneratedCodeCoverage and reusable tests.
    • Includes production and test files, Gradle wrapper, and configuration.
  • Fix: Corrected invalid annotation syntax in Javadoc of ExcludeFromJacocoGeneratedCodeCoverage to avoid errors when referenced.

Purpose

This pull request enhances usability by:

  • Providing reusable tools for consistent ArchUnit rules.
  • Including concrete example projects to simplify feature adoption.
  • Ensuring documentation accuracy for straightforward implementation.

Arc-E-Tect added 4 commits May 4, 2026 09:54
…amples

Both <pre> blocks in ExcludeFromJacocoGeneratedCodeCoverage.java used
the invalid positional (single-argument) annotation syntax:

  @ExcludeFromJacocoGeneratedCodeCoverage("Spring Boot entry point")

The annotation declares only a named element (justification), so the
positional shorthand is not legal and would cause a compile error if
copied verbatim by a consumer.

Both occurrences are replaced with the correct named syntax:

  @ExcludeFromJacocoGeneratedCodeCoverage(justification = "Spring Boot entry point – not unit-testable")

No behaviour change — Javadoc only.
…xtures artifact

Motivation
----------
Consumers of sedr-library need a ready-made ArchUnit rule that enforces the
convention that every @ExcludeFromJacocoGeneratedCodeCoverage annotation must
carry a non-blank justification.
Shipping this rule as a test-fixtures artifact means every project can reuse
it with a single dependency declaration instead of copy-pasting the check.

What changed
------------
sedr-library/build.gradle
- Apply the built-in 'java-test-fixtures' Gradle plugin so the testFixtures
  source set is compiled and published alongside the main jar.
- Remove the unused 'import groovy.json.JsonSlurper' (caused a VS Code
  compile error; the import was pre-existing but latent).
- Refactor resolveVersion to use gh's built-in --jq filter instead of
  JsonSlurper for JSON parsing, eliminating the Groovy dependency.
- Add a dependencies block declaring testFixturesApi for archunit-junit5 and
  junit-jupiter-api so they are transitive to consumers of the fixture.

sedr-library/gradle/libs.versions.toml
- Add archunit = "1.4.2" and junit-jupiter = "5.14.4" to [versions].
- Add archunit-junit5 and junit-jupiter-api entries to [libraries].
- Includes refreshVersions comment-style candidates for both artifacts.

sedr-library/src/testFixtures/java/.../AbstractCoverageExclusionConventionsTest.java
- New public abstract class in the same package as the annotation.
- Declares protected abstract String getBasePackage() for subclasses to scope
  the scan to their own root package.
- Single @test coverageExclusionAnnotationsMustHaveJustification() uses
  ClassFileImporter (DO_NOT_INCLUDE_TESTS) + a custom ArchCondition that
  separately checks class-level, constructor-level, and method-level usages of
  @ExcludeFromJacocoGeneratedCodeCoverage for a non-blank justification value.
- Javadoc shows the extend-and-override pattern and the Gradle dependency snippet.

How consumers use it
--------------------
1. Add to build:
     testImplementation(testFixtures("com.arc-e-tect.sedr.utils:sedr-library:VERSION"))
2. Write a one-method subclass overriding getBasePackage().
3. The inherited test runs automatically in the JUnit Platform.

Side effects / caveats
-----------------------
- Gradle emits POM metadata warnings about testFixtures capability mapping.
  This is cosmetic and only affects Maven consumers on Gradle < 6; Gradle 6+
  module metadata handles it correctly.
- 'from components.java' in the existing MavenPublication block automatically
  includes the testFixtures variant — no changes to the publishing block needed.
Motivation
----------
A runnable example makes it concrete how consumers integrate both the
@ExcludeFromJacocoGeneratedCodeCoverage annotation and the reusable
AbstractCoverageExclusionConventionsTest, and demonstrates that the ArchUnit
rule correctly distinguishes compliant from non-compliant usage.

Location
--------
examples/sedr-library/jacoco-marker/

What's included
---------------
Build infrastructure
- settings.gradle  — standalone Gradle project named 'jacoco-marker-example'.
- build.gradle     — applies java plugin; declares mavenLocal() first then
                     mavenCentral() so locally published snapshots resolve
                     during development without any change post-release;
                     declares implementation and testImplementation(testFixtures)
                     against sedr-library 0.2.6; adds junit-jupiter-engine and
                     junit-platform-launcher as testRuntimeOnly.
- gradle/wrapper/  — Gradle wrapper copied from sedr-library so the example
                     is self-contained.

Production sources
- CompliantService.java   — method annotated with @ExcludeFromJacocoGeneratedCodeCoverage
                            with a non-blank justification; the ArchUnit rule passes.
- NonCompliantService.java — method annotated with @ExcludeFromJacocoGeneratedCodeCoverage
                             without a justification; the ArchUnit rule raises a violation.

Test sources
- CoverageExclusionConventionsTest.java — extends AbstractCoverageExclusionConventionsTest;
  overrides getBasePackage() to return 'com.arc_e_tect.sedr.example.jacoco.marker'.

Verified behaviour
------------------
Running './gradlew test' (after publishToMavenLocal on sedr-library) produces
exactly one violation:

  Method com.arc_e_tect.sedr.example.jacoco.marker.NonCompliantService.stop()
  uses @ExcludeFromJacocoGeneratedCodeCoverage without a justification

CompliantService is not mentioned in the output.
…ADME

What changed
------------
README.adoc
- Correct 'Latest version' table entry from 0.2.1 to 0.2.6.
- Add section 'Enforcing the justification convention with ArchUnit':
    - Explains the purpose of the test-fixtures artifact.
    - Shows how to declare testImplementation(testFixtures(...)) in Kotlin
      and Groovy DSL.
    - Explains the need for junit-jupiter-engine and junit-platform-launcher
      as testRuntimeOnly dependencies with version examples.
    - Shows the one-method subclass pattern for CoverageExclusionConventionsTest.
    - Side-by-side compliant vs. non-compliant annotation usage examples.
- Add section 'Example project':
    - Links to examples/sedr-library/jacoco-marker/.
    - Table describing each source file and its role.
    - Two-step instructions (publishToMavenLocal then ./gradlew test).
    - States the expected violation output (NonCompliantService named;
      CompliantService absent).
@Arc-E-Tect Arc-E-Tect self-assigned this May 4, 2026
@Arc-E-Tect Arc-E-Tect added bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request labels May 4, 2026
@Arc-E-Tect Arc-E-Tect merged commit f797cc8 into main May 4, 2026
4 checks passed
@Arc-E-Tect Arc-E-Tect deleted the add-archunit-check-with-example branch May 4, 2026 06:10
Arc-E-Tect added a commit that referenced this pull request May 4, 2026
# [0.3.0](v0.2.6...v0.3.0) (2026-05-04)

### ✨ New and updated features

* Add reusable ArchUnit rule and example project for coverage annotations ([#14](#14)) ([f797cc8](f797cc8)), closes [#14](#14)

### 📝 Documentation

* **readme:** update version to 0.2.6 [skip ci] ([0e6915f](0e6915f))
@Arc-E-Tect

Copy link
Copy Markdown
Owner Author

🎉 This PR is included in version 0.3.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request released

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant