上QQ阅读APP看书,第一时间看更新
Testing the solution automatically
Running tests by hand is no good; it gets tiresome, boring, and that leads, after time, to not running the tests any longer. Let's do better, and write some automatic tests with Jasmine. Following the instructions over at https://jasmine.github.io/pages/getting_started.html, I set up a standalone runner:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Jasmine Spec Runner v2.6.1</title>
<link rel="shortcut icon" type="image/png"
href="lib/jasmine-2.6.1/jasmine_favicon.png">
<link rel="stylesheet" href="lib/jasmine-2.6.1/jasmine.css">
<script src="lib/jasmine-2.6.1/jasmine.js"></script>
<script src="lib/jasmine-2.6.1/jasmine-html.js"></script>
<script src="lib/jasmine-2.6.1/boot.js"></script>
<script src="src/once.js"></script>
<script src="tests/once.test.1.js"></script>
</head>
<body>
</body>
</html>
The src/once.js file has the once() definition that we just saw, and tests/once.test.js has the actual suite of tests:
describe("once", () => {
beforeEach(() => {
window.myFn = () => {};
spyOn(window, "myFn");
});
it("without 'once', a function always runs", () => {
myFn();
myFn();
myFn();
expect(myFn).toHaveBeenCalledTimes(3);
});
it("with 'once', a function runs one time", () => {
window.onceFn = once(window.myFn);
spyOn(window, "onceFn").and.callThrough();
onceFn();
onceFn();
onceFn();
expect(onceFn).toHaveBeenCalledTimes(3);
expect(myFn).toHaveBeenCalledTimes(1);
});
});
There are several points to note here:
- In order to spy on a function, it must be associated with an object. (Alternatively, you can also directly create a spy using Jasmine's .createSpy() method.) Global functions are associated with the window object, so window.fn is a way of saying that fn is actually global.
- When you spy on a function, Jasmine intercepts your calls and registers that the function was called, with what arguments, and how many times it was called. So, for all we care, window.fn could simply be null, because it will never be executed.
- The first test only checks that if we call the function several times, it gets called that number of times. This is trivial, but if that didn't happen, we'd be doing something really wrong!
- In the second group of tests, we want to see that the once()-ed function (window.onceFn()) gets called, but only once. So, we tell Jasmine to spy on onceFn, but let calls pass through. Any calls to fn() will also get counted. In our case, as expected, despite calling onceFn() three times, fn() gets called only once.
We can see the results in Figure 2.3:
Figure 2.3 - Running automatic tests on our function, with Jasmine