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.doesNotThrow, show error message #12167

Closed
wants to merge 1 commit into from

Conversation

krydos
Copy link
Contributor

@krydos krydos commented Apr 2, 2017

As mentioned in #12079 doesNotThrow doesn't show actual error message but shows Got unwanted error which is not really helpful. As @mscdex said it will be better to show actual error message so this is what I have done here. parallel/test-assert.js also was changed a bit.

I hope it will be helpful.

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
Affected core subsystem(s)

assert

@nodejs-github-bot nodejs-github-bot added the assert Issues and PRs related to the assert subsystem. label Apr 2, 2017
@krydos krydos changed the title Better does not throw assert.doesNotThrow, show error message Apr 2, 2017
@vsemozhetbyt
Copy link
Contributor

vsemozhetbyt commented Apr 2, 2017

Commit messages nits (ref):

  • Use lower case imperative verb after subsystem prefix (something like assert: show thrown message in doesNotThrow() or assert: adapt ...).
  • Keep commit title length within 50 characters (currently 59 in the second commit).

@vsemozhetbyt
Copy link
Contributor

@krydos krydos force-pushed the better-does-not-throw branch from 7b667a0 to 36d3cb3 Compare April 2, 2017 19:16
@krydos
Copy link
Contributor Author

krydos commented Apr 2, 2017

@vsemozhetbyt thank you for the feedback. I changed the commit text plus squashed two commits.

@vsemozhetbyt
Copy link
Contributor

@vsemozhetbyt
Copy link
Contributor

vsemozhetbyt commented Apr 2, 2017

Is this semver-major? If so, beware v.8 rc deadline will be closing in 2 days.

@krydos
Copy link
Contributor Author

krydos commented Apr 2, 2017

seems like test/arm tests failed...
the error seems for me like something related to Jenkins - https://gist.github.com/KryDos/927139a77ec9fb2618696b385d6450e2

Could someone please help me to solve it?

@Trott Trott added the semver-major PRs that contain breaking changes and should be released in the next major version. label Apr 3, 2017
@Trott
Copy link
Member

Trott commented Apr 3, 2017

@krydos Given the nature of this change, I think we can ignore the Jenkins issue as unrelated. If someone really wants to, they can re-run CI.

Labeling semver-major out of abundance of caution.

@jasnell
Copy link
Member

jasnell commented Apr 3, 2017

The Got unwanted exception bit is still useful to explain the situation. Not entirely happy with dropping that.

@krydos
Copy link
Contributor Author

krydos commented Apr 3, 2017

@jasnell what if I'll change it to Got unwanted exception (the error message)...? Probably it will be even better.

EDIT:
This was strange suggestion since "the error message" is actually not the message only but also concatenated expected message. (e.g thrown error: expected). So it will look very very strange.

@mscdex
Copy link
Contributor

mscdex commented Apr 3, 2017

Well, I don't think just including the original error message is useful enough. The stack trace is usually more helpful, but if we use the original stack trace that may/may not be confusing with the modified exception message.

Perhaps if we separated with a newline that might be clearer? For example:

err.message = 'Got unwanted exception:\n' + err.message;
throw err;

Doing so would mean we would need to tweak fail()/AssertionError to use the original stack trace.

@krydos
Copy link
Contributor Author

krydos commented Apr 3, 2017

@mscdex excuse me, but I didn't really understand why do we need to change how fail or AssertionError work.

As you and @jasnell noticed, and I agree with, that error.message without Got unwanted exception may be confusing.

I also didn't understand the meaning of original stack trace just because I do not see that stack trace is getting modified somehow during doesNotThrow execution. So as for me stack trace is always original. Could you please help me to understand this? 😊

@gibfahn
Copy link
Member

gibfahn commented Apr 3, 2017

CI 3: https://ci.nodejs.org/job/node-test-commit/8845/ (all green)

@mscdex
Copy link
Contributor

mscdex commented Apr 3, 2017

@krydos Nevermind, I suppose it works fine for this situation because it's synchronous.

@krydos krydos force-pushed the better-does-not-throw branch from 36d3cb3 to 166a4f9 Compare April 4, 2017 08:35
@krydos
Copy link
Contributor Author

krydos commented Apr 4, 2017

In my last commit I returned Got unwanted exception since it is something that can help to understand what just happened. I hope it's ok.

EDIT:
just to help you understand how the output looks like, here is - https://gist.github.com/KryDos/5d528c4bfa12627822926ff99976056f

@@ -406,7 +406,7 @@ assert.doesNotThrow(function() { assert.ifError(); });

assert.throws(() => {
assert.doesNotThrow(makeBlock(thrower, Error), 'user message');
}, /Got unwanted exception: user message/,
}, /Got unwanted exception:\ntest: user message/,
'a.doesNotThrow ignores user message');
Copy link
Member

Choose a reason for hiding this comment

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

The indenting is off here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jasnell a.doesNotThrow ignores... should be aligned with /Got unwanted exception.... Do I understand it correctly?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

...probably not since jslint throws error about it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jasnell unfortunately I didn't really understand where indenting was off :( I hope it was fixed with new commit... but probably not.

lib/assert.js Outdated
fail(actual, expected, 'Got unwanted exception' + message);
fail(actual, expected,
'Got unwanted exception:\n' +
actual.message + message);
Copy link
Member

@joyeecheung joyeecheung Apr 4, 2017

Choose a reason for hiding this comment

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

Why is it 'Got unwanted exception:\n' + actual.message + message instead of 'Got unwanted exception: ' + message + '\n' + actual.message (more similar to what it used to be)? This way it would be:

Got unwanted exception: explain why it is unwanted.
Message of the unwanted exception.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looks really good.
But probably something like that

'Got unwanted exception' + message + '\n' + actual.message

(without : after exception) since message will have it (if message exists). Otherwise message will have just . (dot).

So, if message wasn't passed it will look like:

Got unwanted exception.
Message of the unwanted exception.

I really like your idea.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@joyeecheung just pushed the changes you suggested. Thank you!

@@ -406,7 +406,7 @@ assert.doesNotThrow(function() { assert.ifError(); });

assert.throws(() => {
assert.doesNotThrow(makeBlock(thrower, Error), 'user message');
}, /Got unwanted exception: user message/,
}, /Got unwanted exception:\ntest: user message/,
'a.doesNotThrow ignores user message');
Copy link
Member

Choose a reason for hiding this comment

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

This message is no longer accurate...this test fails if a.doesNotThrow ignores user message or if it ignores the message of the unwanted exception..

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@joyeecheung completely agree with your here. I added another test case that tests unwanted exception message. I hope it is ok.

@krydos krydos force-pushed the better-does-not-throw branch from 166a4f9 to db9d871 Compare April 6, 2017 08:24
@krydos
Copy link
Contributor Author

krydos commented Apr 8, 2017

@jasnell ping.
Could you please take a look and leave your feedback.

assert.throws(() => {
assert.doesNotThrow(makeBlock(thrower, Error), 'user message');
}, /Got unwanted exception: user message\ntest/,
'a.doesNotThrow ignores message of the unwanted exception');
Copy link
Member

Choose a reason for hiding this comment

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

I think what @jasnell mean is that the opening ' should be directly below the opening /. (Or just drop the extra third argument here, I think I would prefer that.)

Copy link
Member

Choose a reason for hiding this comment

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

Thank you @addaleax ... yes, that's what I meant.

(I missed the earlier ping)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I actually tried to align ' with / but I was unable to pass linter in this case. It was saying I have wrong indentation.

Since it is ok to remove third argument this is exactly what I did.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah I've seen that happen before, it wants to align with the function call's opening (.

@krydos krydos force-pushed the better-does-not-throw branch from db9d871 to 61ded4e Compare April 15, 2017 05:18
@@ -409,6 +409,10 @@ assert.throws(() => {
}, /Got unwanted exception: user message/,
'a.doesNotThrow ignores user message');

assert.throws(() => {
assert.doesNotThrow(makeBlock(thrower, Error), 'user message');
}, /Got unwanted exception: user message\ntest/);
Copy link
Member

Choose a reason for hiding this comment

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

Can we add a test to confirm we don't get unhelpful strings (like "undefined") if the user leaves out the optional message argument?

Copy link
Member

@Trott Trott May 10, 2017

Choose a reason for hiding this comment

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

Also, probably a good idea to include a test case for if a primitive is thrown rather than a proper Error. Like, maybe throw "big problem". You'll probably need to disable an eslint rule with a comment because we lint for throw being used with an unexpected type like that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Trott thank you for recommendations. I've added one more test to check if no user message provided.

As for second comment about throw primitive... it really displays undefined as error text. It goes to another branch and do not entering in the if that I touched in PR. It happens probably because util.isError is returning false since string isn't good Error object.
I'm still thinking about good way to fix it...

@krydos krydos force-pushed the better-does-not-throw branch from 61ded4e to 1c9f79b Compare May 11, 2017 19:42
@refack refack self-assigned this May 28, 2017
@refack
Copy link
Contributor

refack commented Jul 9, 2017

Sanity of rebase: https://ci.nodejs.org/job/node-test-commit-linuxone/7173/ 🔴

refack pushed a commit to refack/node that referenced this pull request Jul 9, 2017
assert.doesNotThrow() should show actual error message instead
of "Got unwanted exception" which is not really helpful.

PR-URL: nodejs#12167
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Yuta Hiroto <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Joyee Cheung <[email protected]>
Reviewed-By: Refael Ackermann <[email protected]>
@refack
Copy link
Contributor

refack commented Jul 9, 2017

@krydos Needs a rebase

lib/assert.js Outdated
fail(actual, expected, 'Got unwanted exception' + message);
fail(actual, expected,
'Got unwanted exception' +
message + '\n' + actual.message);
Copy link
Contributor

Choose a reason for hiding this comment

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

needs a 4th argument caller should be either assert.throws or assert.doesNotThrow

@@ -409,6 +409,14 @@ assert.throws(() => {
}, /Got unwanted exception: user message/,
'a.doesNotThrow ignores user message');

assert.throws(() => {
Copy link
Contributor

Choose a reason for hiding this comment

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

IMHO the check should be using try / catch otherwise we get into a weird situation where we use the function to test itself and Alex Turing will get mad, and say 🛑

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@refack thanks for the feedback. throws calls innerThrows internally and doesNotThrow calls innerThrows internally as well. That's why we use function to test itself? Did I understand you correctly? Do we need just usual try / catch instead of assert.throws right?

@refack
Copy link
Contributor

refack commented Jul 9, 2017

While trying to test if I rebased this correctly I got:

not ok 53 parallel/test-assert
  ---
  duration_ms: 0.90
  severity: fail
  stack: |-
    assert.js:544
          throw actual;
          ^
    
    AssertionError [ERR_ASSERTION]: Got unwanted exception: user message
    [object Object]
        at innerThrows (assert.js:549:7)
        at Function.doesNotThrow (assert.js:566:3)
        at assert.throws (/data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/parallel/test-assert.js:472:10)
        at tryBlock (assert.js:514:5)
        at innerThrows (assert.js:533:18)
        at Function.throws (assert.js:562:3)
        at Object.<anonymous> (/data/iojs/build/workspace/node-test-commit-linuxone/nodes/rhel72-s390x/test/parallel/test-assert.js:471:8)
        at Module._compile (module.js:569:30)
        at Object.Module._extensions..js (module.js:580:10)
        at Module.load (module.js:503:32)
  ...

Who throw the exception? The function we are testing, or the function we are using to assert the the result is as expected? 💫

@krydos
Copy link
Contributor Author

krydos commented Jul 11, 2017

I'm currently not sure why actual is [object Object] right now... It was differently before :)
Let me trace it to understand why it's like that and I'll come back with more info

@krydos krydos force-pushed the better-does-not-throw branch from 1c9f79b to d081803 Compare July 15, 2017 06:19
@krydos
Copy link
Contributor Author

krydos commented Jul 15, 2017

Ok,
[object Object] is probably fine, because our error thrower accepts {} now instead of test string as it was previously.
I found some code that test against [object Object] as well. So based on this I made the same check.

I also could avoid using thrower function in my tests and use my own thrower. I think it's not bad... but I tried to keep my tests similar to others. Please update me if "custom thrower" will be better in this case.

p.s.
when I say "custom thrower" I mean the same thrower we have but with string passed into constructor instead of empty object {}.

@joyeecheung
Copy link
Member

joyeecheung commented Jul 15, 2017

I think using the current thrower is fine, we could add a comment for why it's [Object object] for clarity but since this is validated in other tests as well we don't really have to do that ¯\(ツ)

+1 to @refack 's idea of using try-catch instead of throws to test doesNotThrow since we are calling innerThrows in both functions

CI: https://ci.nodejs.org/job/node-test-pull-request/9131/

assert.doesNotThrow() should show actual error message instead
of "Got unwanted exception" which is not really helpful.
@krydos krydos force-pushed the better-does-not-throw branch from d081803 to d023feb Compare July 15, 2017 17:36
@krydos
Copy link
Contributor Author

krydos commented Jul 15, 2017

@joyeecheung @refack thanks for explanation and suggestion to use try / catch instead of assert.throws to test assert.doesNotThrow. I've pushed new changes.

@joyeecheung
Copy link
Member

@refack
Copy link
Contributor

refack commented Jul 19, 2017

Quick CI just for freshness: https://ci.nodejs.org/job/node-test-commit-linuxone/7434/

refack pushed a commit to refack/node that referenced this pull request Jul 19, 2017
assert.doesNotThrow() should show actual error message instead
of "Got unwanted exception" which is not really helpful.

PR-URL: nodejs#12167
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Yuta Hiroto <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Joyee Cheung <[email protected]>
Reviewed-By: Refael Ackermann <[email protected]>
@refack
Copy link
Contributor

refack commented Jul 19, 2017

Landed in c53db1e
🎉🎉🎉

@refack refack closed this Jul 19, 2017
@krydos
Copy link
Contributor Author

krydos commented Jul 20, 2017

Thanks everyone for help and feedback 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
assert Issues and PRs related to the assert subsystem. semver-major PRs that contain breaking changes and should be released in the next major version.
Projects
None yet
Development

Successfully merging this pull request may close these issues.