Jasmine has a rich set of matchers included. There is also the ability to write custom matchers for when a project’s domain calls for specific assertions that are not included below.
Expectations
Similar to describe
and it
, Jasmine features another built-in function called expect
. Expectations are the code equivalent of the phrase in your it
statement.
Let's think back to the video player example. You think a video should play automatically when a page loads? That's your expectation. It's what you expect to happen!
We saw that describe takes two arguments: a string and a function. it
also takes two arguments: a string and a function.
expect
only takes one argument: the actual. The actual is the value you're testing. It could be a variable, a numerical value, a boolean, an array, etc.
Using the previously seen video player example, the expectation is that the video is playing, right? That's what you want to be happening!
Here's how you'd write that as an expect
statement (see lines 4 and 9):
describe("Video player", function() {
describe("when the page loads", function() {
it("should automatically play the video", function() {
expect(videoPlaying).toBe(true);
};
});
describe("when user clicks the play button", function() {
it("should play the video", function() {
expect(videoPlaying).toBe(true);
};
});
});
What's that sneaky toBe()
on the end?
Good question! Let's look at the important complement to expectations: matchers.
Matchers
A matcher compares the actual value with an expected value.
Here's a concrete metaphor: you're taking a test in school. ✏️ The teacher grading your test will compare your actual answer to the expected answer; if your actual answer was A, and the expected answer was A, you've passed that question! If your actual answer was A, and the expected answer was B, you failed that question.
The same is true when testing your code. You compare two values according to a set criteria that defines the right or wrong answer.
One great thing about Jasmine is that it comes with built-in matchers. Using matchers, you can test if:
two things are equal (or not).
if something is true (or not).
if something is defined (or not).
if something is greater than a value (or less than).
if an error is thrown (or not).
and more!
Obviously matchers are super useful while testing your code. They let you compare two values to see if what you want to happen is truly happening!
Matcher syntax
Jasmine comes with the following predefined matchers. Check out some of the following, and try to understand what they might do:
expect(fn).toThrow(e);
expect(instance).toBe(instance);
expect(mixed).toBeDefined();
expect(mixed).toBeFalsy();
expect(number).toBeGreaterThan(number);
expect(number).toBeLessThan(number);
expect(mixed).toBeNull();
expect(mixed).toBeTruthy();
expect(mixed).toBeUndefined();
expect(array).toContain(member);
expect(string).toContain(substring);
expect(mixed).toEqual(mixed);
expect(mixed).toMatch(pattern);
The matchers read rather nicely from left to right. For example, expect(5).toBeLessThan(6);
is exactly how you'd convey the same idea in real (non code) language! You'd say, "I expect 5 to be less than 6."
You can also test the opposite outcome of one of these matchers. To test a negative case, you would write expect(6).not.toBeLessThan(6);
. Just chain a not
in there before calling the matcher.
Like you saw in the last chapter on suites and specs, choosing expectations becomes easier if you already did a good job defining the behaviors you expect during your BDD process.
Bowling example
Let's get back to our awesome bowling example. Open your BowlingGameSpec.js
file if you haven't already. Here's where we left off in the last chapter:
describe("Bowling game", function() {
it("should properly calculate a gutter game", function() {
// test
});
it("should properly calculate a strike", function () {
// test
});
it("should properly calculate a spare", function () {
// test
});
});
We previously set up specs that will contain the actual code tests. Now, let's set up expectations.
Rolling expectations
A bowling player rolls twice in one turn, right, and they have 20 turns in one game? Let's say that, every single turn, they hit zero pins.
This is an easy scenario to test! I'll add it to the first spec:
it("should properly calculate a gutter game", function() {
game.roll(20, 0);
expect(game.score()).toEqual(0);
});
Where did that all come from (game.roll
, game.score
, etc)?
I made it up! Nothing in the test actually exists in code yet.
Now, from filling out the test -- even if we don't have equivalent code yet -- we can consider the code we need to write to make the test pass.
Let's see how to do that in the next chapter!