-
-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Calling done(undefined)
passes a test
#2600
Comments
I haven't checked the docs, but I would be 99% certain that Mocha does a falsy/truthy check on the first argument passed to done. Imagine you have a child process, if the cp exits with 0, it is successful, if it exits with 1 or greater, it's usually not. 0 is of course, falsy. it('tests child process', function(done){
const cp = require('child_process');
const child = cp.fork('foo.js');
child.on('exit',done);
}); Mocha is not checking for the amount of arguments passed to done, Mocha is checking whether the first argument passed to done is truthy. If it's truthy, then the test fails. That is the expected behavior, TMK. |
I just did a quick check and the actual code is in fact using truthiness/falsiness. Good investigation there, @ORESoftware; thanks! I don't know that mere falsiness is really the intended criteria though -- it seems like anything other than However, I could see Speaking more practically, I could see it being potentially useful to write tests where So, my inclination is to say we should change the truthiness check to I could be missing something though; @adityavm could you elaborate on your use case? |
@ScottFreeCode sure. The actual piece of code is this : send: (obj) => {
if (obj.error) done(obj.response.message);
...
} This test kept passing for a while, even though error was true, until I figured out that the But doing |
@ScottFreeCode Just thinking aloud (I may be wrong here)
Taking a look at the code of done() method
Wouldn't adding a |
@ScottFreeCode a quick bit of code reveals: I think using |
The docs should be changed to be more clear about this. It's a "node-style" callback (or "errback"); typically these simply evaluate the first parameter for truthiness. Thus, passing any non-truthy value to |
Send PR to site repo |
TL;DR: Documentation would be good, but I think -- because false passes in testing are serious -- being stricter than convention would better, although it may have to wait for 4.x.
Currently, these pass: (Although it appears that we'd also need to look at the logic for the
Hmm, yeah, that would probably get Mocha's "throw an Error instead" warning (still a test failure) if And, come to think of it, in my hypothetical "using a variable that may be set to an error or may be left unset" example, if So I guess I am leaning toward checking While @boneskull has a point about consistency with Node patterns, and we should definitely make the docs clearer about it in any case, I think a test runner is one place where being more strict than usual can be warranted. After all, anything that makes tests always pass even if they should be failing is automatically a severe issue, since it can hide other issues of any severity. And, since they're apparently passing, it's not even easy to tell how widespread this problem is. (Although I would hope that most failures either will be thrown or will be coming in from a similar error parameter and passed to done directly instead of anything that could be undefined, I don't know how we'd know if this is a widespread issue until it impacts something major -- or until we make Another consideration: either this needs to go behind a flag (but we've got a lot of flags already and have at least one major tweak to the commandline processing going already) or this would need to be a semver "major" change. |
IMO the best thing to do would be to always log the first argument passed
to the error-first callback, if arguments.length > 0, in the test results.
That is the only change (besides the docs) that I see necessary. The
pattern of truthy/falsy is so widespread in Node, it would be far more
surprising to deviate from that than anything else.
in Node.js, we have this everywhere:
if(err){
cb(err);
}
else {
it's a truthy/falsy check, and IMO Mocha should stay with that
…On Sun, Nov 27, 2016 at 11:51 PM, Scott Santucci ***@***.***> wrote:
TL;DR: Documentation would be good, but I think -- because false passes in
testing are serious -- being stricter than convention would better,
although it may have to wait for 4.x.
@vivganes <https://github.com/vivganes>
Wouldn't adding a err == undefined check affect any invocations that are
called without any argument? If I just call done() wouldn't that lead to
err being undefined. Correct me if i am wrong.
Currently, these pass: undefined, null, 0, ''/"", false.
My thought was that only these should pass: undefined, maybe null.
Changing !err to err !== undefined or err != undefined -- not err ==
undefined -- would accomplish that as far as I can tell.
(Although it appears that we'd also need to look at the logic for the fn
called at the end there; that done function itself appears to mainly deal
with timeout logic before passing the result on to fn. And see below...)
@adityavm <https://github.com/adityavm>
send: (obj) => {
if (obj.error) done(obj.response.message);
...
}
Hmm, yeah, that would probably get Mocha's "throw an Error instead"
warning (still a test failure) if response.message weren't undefined (is
there a reason it's not using done(obj.error)?), but now that I see it,
it's pretty obviously a case where Mocha treating falsey values as passes
masks a mistake in the test design -- only, since it's undefined
(assuming it is undefined and not an empty string, which is also falsey),
even my proposed compromise of keeping undefined passing wouldn't improve
it.
And, come to think of it, in my hypothetical "using a variable that may be
set to an error or may be left unset" example, if undefined was still
treated as an error you'd just have to branch on whether the variable's set
to determine whether to call done with or without it instead of just
calling done with the variable; so while calling done(maybeError) may
seem much simpler than maybeError ? done(maybeError) : done(), the latter
is entirely doable and this probably shouldn't win out over safety.
So I guess I am leaning toward checking arguments.length after all.
While @boneskull <https://github.com/boneskull> has a point about
consistency with Node patterns, and we should definitely make the docs
clearer about it in any case, I think a test runner is one place where
being more strict than usual can be warranted. After all, anything that
makes tests always pass even if they should be failing is automatically a
severe issue, since it can hide other issues of any severity. And, since
they're apparently passing, it's not even easy to tell how widespread this
problem is. (Although I would hope that most failures either will be thrown
or will be coming in from a similar error parameter and passed to done
directly instead of anything that could be undefined, I don't know how we'd
know if this is a widespread issue until it impacts something major -- or
until we make done strict enough to turn them all into errors.)
Another consideration: either this needs to go behind a flag (but we've
got a lot of flags already and have at least one major tweak to the
commandline processing going already) or this would need to be a semver
"major" change.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2600 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AKn56JZFHHtpkYMpuKnGmzkRfBOYF7Caks5rCogbgaJpZM4K80Wi>
.
--
Alexander Mills
ORESoftware (inc.)
|
That's still going to pass CI, and if only a fraction of tests for a given project are getting Mocha already goes out of its way to suggest following the convention of only passing an Or on the other hand, when it comes to how bad of a problem it is to break the convention: in that particular example, substituting |
Yes, because |
Ah, I had completely misread that! That might only make the case stronger, though -- if it's simply not expected to be |
@ScottFreeCode Correct, it's never supposed to be |
Uhh. Tbh, that you get an unexpected behavior from But I guess it can't be helped, since a lot of people might be doing something like: someTask(function (err, result) {
done(err)
}) Logging the value passed to |
With respects to issue #3134, does that solve this issue. Or is this more to do with the library itself, rather than a documentation misunderstanding? |
Facing similar issue when used mocha + cypress facing similar issue |
@sandeepEverest, open a new issue and repost, this time including the relevant portion of your test. |
This is a documentation issue. Someone should update the documentation to reflect the fact that calling |
It is documented... |
great! |
When using
done()
in an async test, if it's called with an argument whose value isundefined
, the test is successfully passed.Simple example:
This feels like incorrect behaviour because
done
was explicitly called with an argument, which happened to not have a value. A test should only pass ifdone
is called without arguments (as per docs).The text was updated successfully, but these errors were encountered: