From e47040cf6d6cb2ba1ab77f539a8d730a41dc868b Mon Sep 17 00:00:00 2001 From: Jimisola Laursen Date: Fri, 12 Jun 2026 22:14:59 +0200 Subject: [PATCH] feat(reqstool): add build config conventions for JUnit5 parameterized test names Document the Gradle/JUnit5 systemProperty fix for parameterized test display names so reqstool can map JUnit XML test results back to @SVCs-annotated methods, avoiding "Skipping parameterized test case" warnings. Adds reqstool-build-config-conventions.md (scoped to Gradle/JUnit5, with notes on the explicit @ParameterizedTest(name=...) override and Maven Surefire being unaffected), and links it from SKILL.md, reqstool-conventions.md, skills.adoc, and README.md. Closes #28 Signed-off-by: Jimisola Laursen --- .claude-plugin/marketplace.json | 2 +- README.md | 1 + docs/modules/ROOT/pages/skills.adoc | 3 + plugins/reqstool/.claude-plugin/plugin.json | 2 +- .../skills/reqstool-conventions/SKILL.md | 1 + .../reqstool-build-config-conventions.md | 60 +++++++++++++++++++ .../references/reqstool-conventions.md | 6 ++ 7 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 plugins/reqstool/skills/reqstool-conventions/references/reqstool-build-config-conventions.md diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 77124ef..d295e4c 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -5,7 +5,7 @@ "url": "https://github.com/reqstool" }, "metadata": { - "version": "0.4.1", + "version": "0.5.0", "description": "AI-assisted reqstool requirements traceability — skills and commands for managing requirements, SVCs, and filters, with optional OpenSpec integration." }, "plugins": [ diff --git a/README.md b/README.md index 39e48f5..9dcb74b 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,7 @@ Bundled convention docs that are auto-applied when working with reqstool files: - **reqstool-conventions.md** — overview of config fields and skill conventions - **reqstool-annotation-conventions.md** — `@Requirements` and `@SVCs` placement rules (Java, Python, TypeScript) - **reqstool-decomposition-conventions.md** — parent-child hierarchies, dot-notation IDs, lifecycle states +- **reqstool-build-config-conventions.md** — build-tool/test-runner config for correct `@SVCs` test result mapping (e.g. Gradle parameterized test display names) ### reqstool-openspec (separate plugin) diff --git a/docs/modules/ROOT/pages/skills.adoc b/docs/modules/ROOT/pages/skills.adoc index 3727980..fcaa03b 100644 --- a/docs/modules/ROOT/pages/skills.adoc +++ b/docs/modules/ROOT/pages/skills.adoc @@ -61,6 +61,9 @@ Bundled convention docs that guide the AI assistant: | `reqstool-decomposition-conventions.md` | Parent-child hierarchies, dot notation, lifecycle states + +| `reqstool-build-config-conventions.md` +| Build-tool/test-runner config for correct `@SVCs` test result mapping (e.g. Gradle parameterized test display names) |=== === reqstool-openspec (separate plugin) diff --git a/plugins/reqstool/.claude-plugin/plugin.json b/plugins/reqstool/.claude-plugin/plugin.json index 1ae3d88..ce4df49 100644 --- a/plugins/reqstool/.claude-plugin/plugin.json +++ b/plugins/reqstool/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "reqstool", "description": "AI-assisted reqstool requirements traceability — skills and commands for managing requirements, SVCs, and filters.", - "version": "0.3.0", + "version": "0.4.0", "author": { "name": "reqstool", "url": "https://github.com/reqstool" diff --git a/plugins/reqstool/skills/reqstool-conventions/SKILL.md b/plugins/reqstool/skills/reqstool-conventions/SKILL.md index 494a63f..1c0388f 100644 --- a/plugins/reqstool/skills/reqstool-conventions/SKILL.md +++ b/plugins/reqstool/skills/reqstool-conventions/SKILL.md @@ -15,3 +15,4 @@ convention files from this skill's references/ directory before making changes. - `references/reqstool-conventions.md` — overview of config fields, skill conventions, and pointers to the other docs - `references/reqstool-annotation-conventions.md` — where and how to place `@Requirements` and `@SVCs` annotations (Java, Python, TypeScript) - `references/reqstool-decomposition-conventions.md` — parent-child requirement hierarchies, dot-notation IDs, lifecycle states, prefix strategies +- `references/reqstool-build-config-conventions.md` — build-tool/test-runner config required for reqstool to correctly map JUnit XML results to `@SVCs` methods (e.g. Gradle parameterized test display names) diff --git a/plugins/reqstool/skills/reqstool-conventions/references/reqstool-build-config-conventions.md b/plugins/reqstool/skills/reqstool-conventions/references/reqstool-build-config-conventions.md new file mode 100644 index 0000000..4c51ec5 --- /dev/null +++ b/plugins/reqstool/skills/reqstool-conventions/references/reqstool-build-config-conventions.md @@ -0,0 +1,60 @@ +# reqstool Build & Test Runner Configuration Conventions + +reqstool maps `` entries in JUnit XML test reports to +`@SVCs`-annotated test methods. If a test runner writes a name that doesn't include +the method name, reqstool can't make that link. + +This doc currently covers **Gradle + JUnit 5**. Maven Surefire is unaffected — it +always embeds the method name regardless of display-name settings. + +## Gradle + JUnit 5 Parameterized Tests + +### Symptom + +Gradle's JUnit XML reporter writes parameterized `@Test` case names using the +display name, which defaults to `[N] arguments` — a format that omits the method +name. When reqstool processes the JUnit XML test results (e.g. via +`reqstool status`), this produces warnings like: + +``` +Skipping parameterized test case with display-name-only format (method name not +recoverable): '[1] ACTIVE' in +``` + +and the corresponding `@SVCs` IDs are never marked as verified. + +### Fix + +Configure JUnit 5 to include the method name in the display name by setting the +`junit.jupiter.params.displayname.default` system property on all test tasks +(unit, integration, e2e): + +```kotlin +// Kotlin DSL (build.gradle.kts) +tasks.withType().configureEach { + systemProperty("junit.jupiter.params.displayname.default", "{displayName}[{index}]") +} +``` + +```groovy +// Groovy DSL (build.gradle) +tasks.withType(Test).configureEach { + systemProperty 'junit.jupiter.params.displayname.default', '{displayName}[{index}]' +} +``` + +This produces test case names like `checkStatus(StatusType)[1]` instead of +`[1] ACTIVE`, which reqstool can parse to recover the method name and link the +result to its `@SVCs` annotation. + +> **Explicit `name=` overrides this:** tests using `@ParameterizedTest(name = "{index} ...")` +> still omit the method name, because the explicit `name` overrides the +> `systemProperty` default. Either remove the custom `name` or change it to begin +> with `{displayName}`: `@ParameterizedTest(name = "{displayName}[{index}] ...")`. + +## References + +- [reqstool-java-gradle-plugin PR #63](https://github.com/reqstool/reqstool-java-gradle-plugin/pull/63) + documents this fix (open at time of writing) +- [reqstool-client PR #405](https://github.com/reqstool/reqstool-client/pull/405) — + parser-side handling for Gradle parameterized test names diff --git a/plugins/reqstool/skills/reqstool-conventions/references/reqstool-conventions.md b/plugins/reqstool/skills/reqstool-conventions/references/reqstool-conventions.md index 74f80d9..ad532ac 100644 --- a/plugins/reqstool/skills/reqstool-conventions/references/reqstool-conventions.md +++ b/plugins/reqstool/skills/reqstool-conventions/references/reqstool-conventions.md @@ -13,6 +13,12 @@ When decomposing requirements into parent-child hierarchies, using lifecycle sta or working with dot-notation IDs, follow the conventions in `reqstool-decomposition-conventions.md`. +## Build & Test Runner Configuration + +When configuring build tools or test runners so reqstool can correctly map test +results to `@SVCs` annotations (e.g. parameterized test display names), follow +`reqstool-build-config-conventions.md`. + ## Configuration (`.reqstool-ai.yaml`) All skills read `.reqstool-ai.yaml` from the project root. It defines: