Skip to content

Add AddMissingTestAnnotation recipe to flag (or add) missing @Test annotations - #1183

Open
Vinu2111 wants to merge 1 commit into
openrewrite:mainfrom
Vinu2111:feat/add-missing-test-annotation-772
Open

Vinu2111 wants to merge 1 commit into
openrewrite:mainfrom
Vinu2111:feat/add-missing-test-annotation-772

Conversation

@Vinu2111

@Vinu2111 Vinu2111 commented Oct 11, 2026 •

Copy link
Copy Markdown

What's changed?

Adds AddMissingTestAnnotation, which finds forgotten tests: methods in an existing test class that are void, non-private, non-static, take no parameters, have a name starting with test, and contain at least one assertion (JUnit 4/5, AssertJ, Hamcrest, Mockito verify).

  • Default: flag only. Matching methods get a search-result marker and nothing is modified.
  • Opt-in addAnnotation=true adds @Test, matching the framework the class already uses (JUnit 4 or 5).
  • Classes with both JUnit 4 and 5 @Test methods, or with no @Test method, are left untouched.
  • Methods that already carry a test or lifecycle annotation are skipped.

What's your motivation?

Tests that lose their @Test annotation silently stop running. Following the discussion in #772, @timtebeek was hesitant about annotating automatically (for example a deliberately disabled database test), so the default only flags.

Anything in particular you'd like reviewers to focus on?

  • The heuristic requires both a test name prefix and an assertion. This avoids turning helpers like testDataSetup() into tests, but misses real tests without the prefix, or ones asserting through custom helpers.
  • Leaving classes that mix JUnit 4 and 5 untouched.

Have you considered any alternatives or workarounds?

"Name OR assertion" catches more tests, but it would annotate helpers, which RemoveTestPrefix could then rename.

Any additional context

  • 24 tests in AddMissingTestAnnotationTest: positive and negative cases, JUnit 4 and 5, mixed classes, AssertJ/Hamcrest/Mockito, lifecycle annotations, the default (null) option, abstract methods and nested classes.
  • recipes.csv contains only the new entry. I ran the test class and recipeCsvGenerate locally, but not a full ./gradlew build, so I'm relying on CI for that. My local dependency setup changed other rows' counts when regenerating, so I did not commit those.
  • Known limitation: a package-private helper named test... that asserts would still be annotated in opt-in mode.
  • Questions: is cleanup the right package, and should the recipe be added to a composite recipe (for example in cleanup.yml)? I left that out for now.

Checklist

Add `AddMissingTestAnnotation`, which finds methods in an existing test
class that look like forgotten tests: void, non-private, non-static, no
parameters, a name starting with `test`, and a body containing at least
one assertion (JUnit 4/5, AssertJ, Hamcrest, Mockito verify).

By default the recipe only flags such methods with a search result.
Setting `addAnnotation` to `true` adds `@Test`, matching the framework
the class already uses (JUnit 4 or JUnit 5). Classes that mix both
frameworks, or have no `@Test` method at all, are left untouched.

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

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

Recipe to add missing @Test annotations

1 participant