Skip to content

feat: add soft assertions feature #1836

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 29, 2025

Conversation

JustasMonkev
Copy link
Contributor

This pull request introduces a new "soft assertions" feature to the WebdriverIO testing framework, allowing tests to continue execution even when some assertions fail. It includes updates to the documentation, core library, and new utility classes for managing and integrating soft assertions.

New Feature: Soft Assertions

Documentation Updates:

  • Added a new section in docs/API.md explaining the concept of soft assertions, usage examples, and API methods (expect.soft, expect.getSoftFailures, expect.assertSoftFailures, expect.clearSoftFailures). Also included integration details with WebdriverIO's test runner.

Core Library Enhancements:

  • Updated src/index.ts to extend the expect object with soft assertion methods (soft, getSoftFailures, assertSoftFailures, clearSoftFailures) and exported the new soft assertion services. [1] [2] [3]

Soft Assertion Utilities:

  • Introduced SoftAssertService in src/softAssert.ts to manage soft assertion failures per test, including methods to add, retrieve, clear, and assert failures. It uses a singleton pattern for centralized failure tracking.
  • Added SoftAssertionService in src/softAssertService.ts for WebdriverIO integration, hooking into test and step lifecycle events to automatically handle soft assertion failures.

Soft Assertion API:

  • Created createSoftExpect in src/softExpect.ts, which generates soft assertion matchers using proxies. It ensures that failures are recorded without stopping test execution.

Closes #227

Copy link

linux-foundation-easycla bot commented May 23, 2025

CLA Signed

The committers listed above are authorized under a signed CLA.

Copy link
Member

@christian-bromann christian-bromann left a comment

Choose a reason for hiding this comment

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

Great contribution 👏 some comments here

@christian-bromann
Copy link
Member

@darkartswizard @PipulPant @DivyangRaval @circa1741 and @alfonso-presa curious about your feedback here 🤔

@darkartswizard
Copy link

darkartswizard commented May 26, 2025 via email

@alfonso-presa
Copy link
Member

Hi! From a test developer's perspective, I'm not entirely sure that best the way to implement soft assertions is to generate a new syntax for expect... Assertions are sometimes (a lot of the times to be honest) implicit, e.g. if the element I'm looking for isn't on the page... I'm more inclined to wrap the section of code where you want assertion failures to be catched and kept for later so that the test continues to the end and then failure is reported as a soft assertion indicating the step were it happened.

In this example

await expect.soft(await $('h1').getText()).toEqual('Basketball Shoes')

If no h1 is on the page, I guess the failure would make the test stop. I'd rather have something like:

await expect.soft(() => $('h1').getText()).toEqual('Basketball Shoes')

Or IMHO, more flexible, but more verbose:

await soft(async () => {
   expect(await $('h1').getText()).toEqual('Basketball Shoes'))
});

I know for an h1 is not clear the use case, but there are situations where the page structure changes depending on the circumstances (for example, in a bank application if a expense has no category), so I think soft assertions should cover also the implicit use cases.

Cheers!

@JustasMonkev
Copy link
Contributor Author

Hi! From a test developer's perspective, I'm not entirely sure that best the way to implement soft assertions is to generate a new syntax for expect... Assertions are sometimes (a lot of the times to be honest) implicit, e.g. if the element I'm looking for isn't on the page... I'm more inclined to wrap the section of code where you want assertion failures to be catched and kept for later so that the test continues to the end and then failure is reported as a soft assertion indicating the step were it happened.

In this example

await expect.soft(await $('h1').getText()).toEqual('Basketball Shoes')

If no h1 is on the page, I guess the failure would make the test stop. I'd rather have something like:

await expect.soft(() => $('h1').getText()).toEqual('Basketball Shoes')

Or IMHO, more flexible, but more verbose:

await soft(async () => {
   expect(await $('h1').getText()).toEqual('Basketball Shoes'))
});

I know for an h1 is not clear the use case, but there are situations where the page structure changes depending on the circumstances (for example, in a bank application if a expense has no category), so I think soft assertions should cover also the implicit use cases.

Cheers!

Hey! You make a good point about implicit failures.

My expect.soft() approach follows Playwright's pattern, which developers already know. Your wrapper idea would definitely catch more edge cases like when elements don't exist.

Let's try this - if people suggest use cases like yours, we can update the implementation to handle them. For now, I'd suggest keeping it as currently implemented with expect.soft() since it covers the main scenarios and matches what developers expect from other frameworks.

Copy link
Member

@christian-bromann christian-bromann left a comment

Choose a reason for hiding this comment

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

Awesome 👍

Copy link
Member

@christian-bromann christian-bromann left a comment

Choose a reason for hiding this comment

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

Fixing the build

@christian-bromann
Copy link
Member

@JustasMonkev mind taking a look at the build? Once test pass I am happy to merge this!

@JustasMonkev
Copy link
Contributor Author

@JustasMonkev mind taking a look at the build? Once test pass I am happy to merge this!

Yes, on it checking

@JustasMonkev
Copy link
Contributor Author

@christian-bromann I checked and it looks like soft assertion tests are passing, but the failures are the same as in main. Should I fix it here or open a new PR?

@christian-bromann
Copy link
Member

Should I fix it here or open a new PR?

Oh, yeah that would be great!

@JustasMonkev
Copy link
Contributor Author

image

@JustasMonkev
Copy link
Contributor Author

@christian-bromann could you rerun the tests here?

@JustasMonkev
Copy link
Contributor Author

@christian-bromann
Copy link
Member

@JustasMonkev oh damn, let's adjust the coverage treshold, I think this PR has sufficient tests.

@JustasMonkev
Copy link
Contributor Author

@JustasMonkev oh damn, let's adjust the coverage treshold, I think this PR has sufficient tests.

@christian-bromann done

Copy link
Member

@christian-bromann christian-bromann left a comment

Choose a reason for hiding this comment

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

Awesome, LGTM 👍

@christian-bromann christian-bromann merged commit eb8b9b6 into webdriverio:main May 29, 2025
3 checks passed
@wdio-bot
Copy link
Contributor

Hey JustasMonkev 👋

Thank you for your contribution to WebdriverIO! Your pull request has been marked as an "Expensable" contribution.

We've sent you an email with further instructions on how to claim your expenses from our development fund.
Please make sure to check your spam folder as well. If you have any questions, feel free to reach out to us at expense@webdriver.io or in the contributing channel on Discord.

We are looking forward to more contributions from you in the future 🙌

Have a nice day,
The WebdriverIO Team 🤖

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

Successfully merging this pull request may close these issues.

Add soft assert support
5 participants