2016-10-18 03:26:54 +02:00
|
|
|
# JavaScript unit tests
|
2016-08-18 22:31:42 +02:00
|
|
|
|
|
|
|
As an alternative to the black-box whole-app testing, you can unit test
|
2016-10-18 03:26:54 +02:00
|
|
|
individual JavaScript files.
|
|
|
|
|
2018-04-16 16:40:50 +02:00
|
|
|
You can run tests as follow:
|
|
|
|
```
|
|
|
|
tools/test-js-with-node
|
|
|
|
```
|
2016-10-18 03:26:54 +02:00
|
|
|
|
|
|
|
The JS unit tests are written to work with node. You can find them
|
|
|
|
in `frontend_tests/node_tests`. Here is an example test from
|
|
|
|
`frontend_tests/node_tests/stream_data.js`:
|
|
|
|
|
|
|
|
```
|
|
|
|
(function test_get_by_id() {
|
|
|
|
stream_data.clear_subscriptions();
|
|
|
|
var id = 42;
|
|
|
|
var sub = {
|
|
|
|
name: 'Denmark',
|
|
|
|
subscribed: true,
|
|
|
|
color: 'red',
|
|
|
|
stream_id: id
|
|
|
|
};
|
|
|
|
stream_data.add_sub('Denmark', sub);
|
|
|
|
sub = stream_data.get_sub('Denmark');
|
|
|
|
assert.equal(sub.color, 'red');
|
|
|
|
sub = stream_data.get_sub_by_id(id);
|
|
|
|
assert.equal(sub.color, 'red');
|
|
|
|
}());
|
|
|
|
```
|
|
|
|
|
|
|
|
The names of the node tests generally align with the names of the
|
|
|
|
modules they test. If you modify a JS module in `static/js` you should
|
|
|
|
see if there are corresponding test in `frontend_tests/node_tests`. If
|
|
|
|
there are, you should strive to follow the patterns of the existing tests
|
|
|
|
and add your own tests.
|
2016-08-18 22:31:42 +02:00
|
|
|
|
|
|
|
## Coverage reports
|
|
|
|
|
|
|
|
You can automatically generate coverage reports for the JavaScript unit
|
|
|
|
tests like this:
|
|
|
|
|
2018-04-16 16:40:50 +02:00
|
|
|
```
|
|
|
|
tools/test-js-with-node --coverage
|
|
|
|
```
|
|
|
|
|
|
|
|
If tests pass, you will get instructions to view coverage reports
|
|
|
|
in your browser.
|
2016-08-18 22:31:42 +02:00
|
|
|
|
2018-04-16 16:40:50 +02:00
|
|
|
Note that modules that
|
2016-08-18 22:31:42 +02:00
|
|
|
we don't test *at all* aren't listed in the report, so this tends to
|
|
|
|
overstate how good our overall coverage is, but it's accurate for
|
|
|
|
individual files. You can also click a filename to see the specific
|
|
|
|
statements and branches not tested. 100% branch coverage isn't
|
|
|
|
necessarily possible, but getting to at least 80% branch coverage is a
|
|
|
|
good goal.
|
|
|
|
|
|
|
|
## Handling dependencies in unit tests
|
|
|
|
|
|
|
|
The following scheme helps avoid tests leaking globals between each
|
|
|
|
other.
|
|
|
|
|
2018-04-16 16:40:50 +02:00
|
|
|
You want to categorize each module as follows:
|
2016-08-18 22:31:42 +02:00
|
|
|
|
|
|
|
- Exercise the module's real code for deeper, more realistic testing?
|
|
|
|
- Stub out the module's interface for more control, speed, and
|
|
|
|
isolation?
|
|
|
|
- Do some combination of the above?
|
|
|
|
|
2017-08-09 18:26:03 +02:00
|
|
|
For all the modules where you want to run actual code, add statements
|
|
|
|
like the following toward the top of your test file:
|
|
|
|
|
|
|
|
> zrequire('util');
|
|
|
|
> zrequire('stream_data');
|
|
|
|
> zrequire('Filter', 'js/filter');
|
|
|
|
|
2016-08-18 22:31:42 +02:00
|
|
|
For modules that you want to completely stub out, please use a pattern
|
|
|
|
like this:
|
|
|
|
|
|
|
|
> set_global('page_params', {
|
|
|
|
> email: 'bob@zulip.com'
|
|
|
|
> });
|
|
|
|
>
|
|
|
|
> // then maybe further down
|
2018-04-16 16:40:50 +02:00
|
|
|
> page_params.email = 'alice@zulip.com';
|
2016-08-18 22:31:42 +02:00
|
|
|
|
|
|
|
Finally, there's the hybrid situation, where you want to borrow some of
|
|
|
|
a module's real functionality but stub out other pieces. Obviously, this
|
|
|
|
is a pretty strong smell that the other module might be lacking in
|
|
|
|
cohesion, but that code might be outside your jurisdiction. The pattern
|
|
|
|
here is this:
|
|
|
|
|
2018-04-16 16:40:50 +02:00
|
|
|
> // Import real code.
|
|
|
|
> zrequire('narrow');
|
2016-08-18 22:31:42 +02:00
|
|
|
>
|
2018-04-16 16:40:50 +02:00
|
|
|
> // And later...
|
|
|
|
> narrow.stream = function () {
|
2016-08-18 22:31:42 +02:00
|
|
|
> return 'office';
|
|
|
|
> };
|
2016-10-18 03:26:54 +02:00
|
|
|
|
|
|
|
## Creating new test modules
|
|
|
|
|
2018-04-16 16:40:50 +02:00
|
|
|
The test runner (`index.js`) automatically runs all .js files in the
|
|
|
|
`frontend_tests/node directory`, so you can simply start editing a file
|
|
|
|
in that directory to create a new test.
|
|
|
|
|
2016-10-18 03:26:54 +02:00
|
|
|
The nodes tests rely on JS files that use the module pattern. For example, to
|
2018-04-16 16:40:50 +02:00
|
|
|
test the `foobar.js` file, you would first ensure that code like below
|
|
|
|
is at the bottom of `foobar.js`:
|
2016-10-18 03:26:54 +02:00
|
|
|
|
|
|
|
> if (typeof module !== 'undefined') {
|
|
|
|
> module.exports = foobar;
|
|
|
|
> }
|
|
|
|
|
2018-04-16 16:40:50 +02:00
|
|
|
This means `foobar.js` follow the CommonJS module pattern, so it can be
|
2016-10-18 03:26:54 +02:00
|
|
|
required in Node.js, which runs our tests.
|
|
|
|
|