Skip to content

Migrate TestNG SoftAssert to AssertJ SoftAssertions#1063

Merged
timtebeek merged 1 commit into
openrewrite:mainfrom
juherr:juherr/migrate-testng-softassert-to-assertj
Jul 24, 2026
Merged

Migrate TestNG SoftAssert to AssertJ SoftAssertions#1063
timtebeek merged 1 commit into
openrewrite:mainfrom
juherr:juherr/migrate-testng-softassert-to-assertj

Conversation

@juherr

@juherr juherr commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

What's changed

Adds a TestNgSoftAssertToAssertJ recipe, wired into the existing TestNgToAssertj declarative recipe, to migrate TestNG soft assertions (org.testng.asserts.SoftAssert) to AssertJ soft assertions (org.assertj.core.api.SoftAssertions).

// before
SoftAssert softAssert = new SoftAssert();
softAssert.assertEquals(actual, expected);   // TestNG: actual first, expected second
softAssert.assertTrue(cond, "msg");
softAssert.assertAll();

// after
SoftAssertions softAssert = new SoftAssertions();
softAssert.assertThat(actual).isEqualTo(expected);
softAssert.assertThat(cond).as("msg").isTrue();
softAssert.assertAll();

How it works

The instance assertion calls are rewritten first, keeping the receiver, then a ChangeType step handles the variable type, the constructor, imports, and the identically named assertAll()/fail(...) methods.

The assertion methods (assertEquals, assertTrue, ...) are declared on org.testng.asserts.AssertionSoftAssert only adds assertAll — so the matcher targets Assertion and a receiver-type guard keeps direct Assertion (hard) usage untouched.

Covered methods

  • assertEquals / assertNotEquals — preserving TestNG's (actual, expected) order, plus the message and floating-point delta overloads (isCloseTo(..., within(...)) / isNotCloseTo(...))
  • assertTrue / assertFalse
  • assertNull / assertNotNull
  • assertSame / assertNotSame
  • assertEqualsNoOrdercontainsExactlyInAnyOrder
  • assertAll() and fail(...) keep the same name and are handled by ChangeType

Notes

  • Broadens the assertj-core onlyIfUsing dependency trigger from org.testng.* to org.testng..*, so classes using only org.testng.asserts.SoftAssert still get the dependency added.
  • The lambda form SoftAssertions.assertSoftly(s -> { ... }) is intentionally not emitted; the explicit instance + assertAll() shape is a 1:1 mapping.

Tests added to TestNgToAssertJTest cover the full flow, every overload branch, non-variable receivers (inline new SoftAssert() and fields), the assertEqualsNoOrder mapping, fail(...) passthrough, boxed-Double deltas, and a negative test asserting direct Assertion usage is left unchanged.

@github-project-automation github-project-automation Bot moved this to In Progress in OpenRewrite Jul 23, 2026
@juherr
juherr force-pushed the juherr/migrate-testng-softassert-to-assertj branch 2 times, most recently from fa7c970 to 034ac4a Compare July 23, 2026 20:38
Add the `TestNgSoftAssertToAssertJ` recipe and wire it into the
`TestNgToAssertj` declarative recipe so that TestNG soft assertions
(`org.testng.asserts.SoftAssert`) are converted to AssertJ soft
assertions (`org.assertj.core.api.SoftAssertions`).

The recipe rewrites the instance assertion calls
(`softAssert.assertEquals(actual, expected)` ->
`softAssert.assertThat(actual).isEqualTo(expected)`) while preserving the
receiver, then a `ChangeType` step handles the variable type, the
constructor, imports, and the identically named `assertAll()`/`fail(...)`
methods.

The assertion methods are declared on `org.testng.asserts.Assertion`
(SoftAssert only adds `assertAll`), so the matcher targets that type and a
receiver-type guard keeps direct `Assertion` (hard) usage untouched.

Covered methods: assertEquals/assertNotEquals (actual/expected order,
message, and floating-point delta overloads), assertTrue/assertFalse,
assertNull/assertNotNull, assertSame/assertNotSame, and assertEqualsNoOrder
(-> containsExactlyInAnyOrder).

Also broaden the assertj-core `onlyIfUsing` dependency trigger from
`org.testng.*` to `org.testng..*` so classes using only
`org.testng.asserts.SoftAssert` still get the dependency added.
@juherr
juherr force-pushed the juherr/migrate-testng-softassert-to-assertj branch from 034ac4a to d942deb Compare July 23, 2026 20:57
@timtebeek
timtebeek self-requested a review July 23, 2026 22:36

@timtebeek timtebeek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Perfect, thanks a lot! Good to see this soft assert gap closed as well. We'll likely do a .patch release later today, or the regular release mid next week.

@github-project-automation github-project-automation Bot moved this from In Progress to Ready to Review in OpenRewrite Jul 24, 2026
@timtebeek
timtebeek merged commit d713402 into openrewrite:main Jul 24, 2026
1 check passed
@github-project-automation github-project-automation Bot moved this from Ready to Review to Done in OpenRewrite Jul 24, 2026
@juherr
juherr deleted the juherr/migrate-testng-softassert-to-assertj branch July 24, 2026 16:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants