-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
🏗 Use a mock instead of a stub to catch console errors during tests #14432
Conversation
This is incomplete as is, and needs an override for the chai assertion |
@choumx After further debugging, it appears that using a mock will break existing usage of
Will discuss in person to see if there's a way around this with mocks. Edit: Found a way to use mocks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How many tests are being broken by this? If it's not a lot we should change those tests to use this mock behaviour instead of abandoning this approach
I seriously think that throwing an exception from calls to console.error(…)
is the wrong way to go, it breaks the expectations from the API (I think of JavaScript's console.error(…)
in the same way I think of Python 3's print(…, file=sys.stderr)
. It prints to the console, that's all I expect of it to do. Libs I use will use it without my control)
test/_init_tests.js
Outdated
' ⤷ Call "this.consoleMock.expects(\'error\').withArgs' + | ||
'(\'<message>\')" before the code containing the error.\n' + | ||
' ⤷ Call "this.consoleMock.expects(\'error\').never()" ' + | ||
'after the code containing the error.\n'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
I'm not sure if you have add the expectation before the offending call to
console.error(…)
, since mocks are only verified in theafterEach
hook. You can remove the "before the code containing the error" part, replace it with "inside your test". Test writers should be able to decide where they want to write the expectations :) -
Does this
.never()
resetting work as expected? Again, since.verify()
happens at the end, I think you're telling test writers to reset the expectation that they just wrote, before the mock gets verified. I think if you want the test to be very explicit it should be something like:
…
this.consoleMock.expects('error').withArgs('foo', 'bar');
doStuff(); // calls console.error('foo', 'bar');
this.consoleMock.verify();
this.consoleMock.expects('error').never();
…
But this seems a bit too explicit. Maybe instead we can suggest this:
this.consoleMock.expects('error').once().withArgs('foo', 'bar');
(this way, the .verify()
call at the end verifies the .once()
constraint)
<message>
is vague. I suggest adding a link to http://sinonjs.org/releases/v4.5.0/matchers/ (nit: can we dynamically replace the version number to always point to the Sinon version we're using?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on offline discussions and debugging with @danielrozenberg, I retract my comment above re: abandoning the approach that uses mocks. Updated commits coming up. The above comments are moot.
Responding to top level comment re: mocks vs stubs first. There are 541 instances of https://gist.github.com/rsimha/0e2b456f5d41d953692840380f65fbe1 |
A cursory glance over a few of these seems to show that these errors are thrown using |
I believe Edit: Here's where |
build-system/tasks/karma.conf.js
Outdated
@@ -197,7 +197,7 @@ module.exports = { | |||
// Longer timeout on Travis; fail quickly at local. | |||
timeout: process.env.TRAVIS ? 10000 : 2000, | |||
}, | |||
captureConsole: false, | |||
captureConsole: true, // DEBUGGING |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm assuming this is supposed to be gone before merging?
test/_init_tests.js
Outdated
consoleMock.verify(); | ||
} catch (e) { | ||
const helpMessage = | ||
'Your test resulted in an unexpected call to console.error.\n' + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: :%s/unexpected call/uncaught call/g (since you're continuing later to say "if this was expected/not expected, it seems odd to announce from beforehand that the call was unexpected)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the word unexpected
since the error message from the mock says so anyway.
test/_init_tests.js
Outdated
@@ -265,13 +266,40 @@ sinon.sandbox.create = function(config) { | |||
return sandbox; | |||
}; | |||
|
|||
function mockConsoleError() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: the naming of mockConsoleError and forbidConsoleError bother me, since the "forbidding" part is happening inside the function called "mock". Not sure how I would rename them tho...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@danielrozenberg PTAL. Due to the sheer number of tests that need changing, I've changed this to warning mode for now.
During local dev, if a test contains unexpected console errors, a message will be printed immediately after the failure. On Travis, all console errors and the accompanying messages will be printed at the end.
Note that we don't fail tests yet, but plan on doing so in future.
test/_init_tests.js
Outdated
consoleMock.verify(); | ||
} catch (e) { | ||
const helpMessage = | ||
'Your test resulted in an unexpected call to console.error.\n' + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the word unexpected
since the error message from the mock says so anyway.
test/_init_tests.js
Outdated
@@ -265,13 +266,40 @@ sinon.sandbox.create = function(config) { | |||
return sandbox; | |||
}; | |||
|
|||
function mockConsoleError() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
* Fix sanitizer regex * handlbars to indiclate templated hotpatch bar * css fix on example * New test pattern per PR #14432 * fixes per pr comments
* Fix sanitizer regex * handlbars to indiclate templated hotpatch bar * css fix on example * New test pattern per PR #14432 * fixes per pr comments
In #14336, a stub was added for
console.error
that would throw an exception when called from within a test.This PR implements the same check more elegantly by using a mock for
console.error
. It also adds a helper function calledallowConsoleError
that tests can use when they want execute code that may generate an error.For now, given the sheer number of AMP tests that generate console errors, we print a warning after each test (local dev) / after all tests (on Travis) with instructions for how to fix these errors. Once all of them are fixed (or wrapped in an
allowConsoleError
block), we can start failing tests when an error is encountered.Examples:
This test will print a warning...
... and so will this test...
... but this test will pass...
Fixes #7381
Follow up to #14336
Related to #14406