★ wanayoo — archive 1999 https://github.com/nodejs/node/pull/27781Nouvelle recherche | Portail wanayoo
Skip to content
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

assert: improve assertion errors #27781

Closed
wants to merge 4 commits into from

Conversation

BridgeAR
Copy link
Member

@BridgeAR BridgeAR commented May 20, 2019

Please have a look at the commit messages for details.

This makes error messages in case of an error are improved while using assert.throws() and assert.rejects(). It also improves the error message for simple assertions when used in combination with new Function and adds a deprecation warning for validation functions that return anything besides true.

This should IMO be semver-minor, since it'll only impact code that fails the assertion (e.g., while writing new code). No passing assertion call is impacted by this.

@nodejs/assert PTAL

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines

@nodejs-github-bot

This comment has been hidden.

lib/assert.js Outdated Show resolved Hide resolved
@BridgeAR
Copy link
Member Author

@BridgeAR BridgeAR commented May 29, 2019

@nodejs/assert @nodejs/testing PTAL. This is actually quite a decent improvement for some cases.

doc/api/deprecations.md Outdated Show resolved Hide resolved
doc/api/assert.md Outdated Show resolved Hide resolved
@Trott
Copy link
Member

@Trott Trott commented May 29, 2019

Introduction of any runtime deprecation is semver major and I don't know that this should be an exception?

@jasnell
Copy link
Member

@jasnell jasnell commented May 29, 2019

I agree with @Trott on semver-major. We should be consistent with the policy

@Trott
Copy link
Member

@Trott Trott commented May 29, 2019

I'm not sure I agree with this. If the validation function returns false, then the error should be re-thrown (or an AssertionError thrown). I don't think we want to change that. I think that's the right result. Validation functions should return true or false (and we should probably accept truthy/falsy values too, but I'm less opinionated about that). If the validation function returns false, then the behavior I would expect is an AssertionError to be thrown or the error would be re-thrown. Anything else is surprising and non-ergonomic in my opinion.

It's more than possible that I either haven't thought about this with sufficient care or else am simply missing the way this change improves things for the average user. But the idea that a validation function shouldn't return false is surprising and not very ergonomic IMO. The benefit of enforcing that needs to be enormous.

@cjihrig
Copy link
Contributor

@cjihrig cjihrig commented May 29, 2019

a584c57 seems like an unrelated change that shouldn't be part of the larger PR, and I disagree with it in general because I think it decreases visibility into our tests.

I also agree with @Trott's #27781 (comment). I don't think that's a change we should make.

BridgeAR added 3 commits Jun 5, 2019
This makes sure `assert.throws()` and `assert.rejects()` result in
an easy to understand error message instead of rethrowing the actual
error. This should significantly improve the debugging experience in
case people use an regular expression to validate their errors.

This also adds support for primitive errors that would have caused
runtime errors using the mentioned functions. The input is now
stringified before it's passed to the RegExp to circumvent that.

As drive-by change this also adds some further comments and renames
a variable for clarity.
This makes sure using `assert.ok()` in `new Function()` statements
visualizes the actual call site in the error message.
Using `assert.throws()` or `assert.rejects()` in combination with
validation function can be very powerful. Using them by returning
any value besides `true` makes debugging very difficult though
because there's no context or reason why the error validation failed.
Thus, it is recommended to throw an error in such cases instead of
returning anything besides `true`.
@BridgeAR BridgeAR force-pushed the improve-assertion-errors branch from 9a85f07 to 6dd4ba5 Compare Jun 5, 2019
@BridgeAR
Copy link
Member Author

@BridgeAR BridgeAR commented Jun 5, 2019

I just updated the PR and incorporated the feedback. I removed the deprecation completely and I'll open a separate PR that changes the behavior directly to an actually more desirable one (throwing an AssertionError that the user returned other than true to give a better context) instead of having a deprecation in this case.

@cjihrig I also removed the commit that you mentioned. I just added it, since without it we receive a cryptic error message. I guess you would prefer to just throw a more meaningful error in that case instead of just logging it?

@nodejs/assert PTAL

@BridgeAR BridgeAR requested review from Trott, targos and cjihrig Jun 6, 2019
doc/api/assert.md Outdated Show resolved Hide resolved
@Trott
Copy link
Member

@Trott Trott commented Jun 6, 2019

Not opposed to this, but I'm still not sure that re-throwing the error is all that undesirable? Pondering some more...

@BridgeAR
Copy link
Member Author

@BridgeAR BridgeAR commented Jun 11, 2019

@Trott right now the user loses pretty much all context why this error occurred and there is no reference to any assertion going on at all. This struck me multiple times in tests and it takes more time to figure out what actually happened. By throwing inside of the validation function in case a specific validation fails, that's not a problem at all. That's why I definitely believe we should recommend this.

Trott
Trott approved these changes Jun 12, 2019
@BridgeAR
Copy link
Member Author

@BridgeAR BridgeAR commented Jun 12, 2019 •

Trott added a commit to Trott/io.js that referenced this issue Jun 13, 2019
This makes sure `assert.throws()` and `assert.rejects()` result in
an easy to understand error message instead of rethrowing the actual
error. This should significantly improve the debugging experience in
case people use an regular expression to validate their errors.

This also adds support for primitive errors that would have caused
runtime errors using the mentioned functions. The input is now
stringified before it's passed to the RegExp to circumvent that.

As drive-by change this also adds some further comments and renames
a variable for clarity.

PR-URL: nodejs#27781
Reviewed-By: Rich Trott <rtrott@gmail.com>
Trott added a commit to Trott/io.js that referenced this issue Jun 13, 2019
This makes sure using `assert.ok()` in `new Function()` statements
visualizes the actual call site in the error message.

PR-URL: nodejs#27781
Reviewed-By: Rich Trott <rtrott@gmail.com>
Trott added a commit to Trott/io.js that referenced this issue Jun 13, 2019
Using `assert.throws()` or `assert.rejects()` in combination with
validation function can be very powerful. Using them by returning
any value besides `true` makes debugging very difficult though
because there's no context or reason why the error validation failed.
Thus, it is recommended to throw an error in such cases instead of
returning anything besides `true`.

PR-URL: nodejs#27781
Reviewed-By: Rich Trott <rtrott@gmail.com>
@Trott
Copy link
Member

@Trott Trott commented Jun 13, 2019

Landed in 8149656...0f90040

@Trott Trott closed this Jun 13, 2019
BridgeAR added a commit that referenced this issue Jun 17, 2019
This makes sure `assert.throws()` and `assert.rejects()` result in
an easy to understand error message instead of rethrowing the actual
error. This should significantly improve the debugging experience in
case people use an regular expression to validate their errors.

This also adds support for primitive errors that would have caused
runtime errors using the mentioned functions. The input is now
stringified before it's passed to the RegExp to circumvent that.

As drive-by change this also adds some further comments and renames
a variable for clarity.

PR-URL: #27781
Reviewed-By: Rich Trott <rtrott@gmail.com>
BridgeAR added a commit that referenced this issue Jun 17, 2019
This makes sure using `assert.ok()` in `new Function()` statements
visualizes the actual call site in the error message.

PR-URL: #27781
Reviewed-By: Rich Trott <rtrott@gmail.com>
BridgeAR added a commit that referenced this issue Jun 17, 2019
Using `assert.throws()` or `assert.rejects()` in combination with
validation function can be very powerful. Using them by returning
any value besides `true` makes debugging very difficult though
because there's no context or reason why the error validation failed.
Thus, it is recommended to throw an error in such cases instead of
returning anything besides `true`.

PR-URL: #27781
Reviewed-By: Rich Trott <rtrott@gmail.com>
@BridgeAR BridgeAR mentioned this pull request Jun 17, 2019
@BethGriggs
Copy link
Member

@BethGriggs BethGriggs commented Sep 3, 2019

@BridgeAR, should this land on v10.x? Please add the lts-watch label if so

@BridgeAR BridgeAR deleted the improve-assertion-errors branch Jan 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

7 participants