-
Notifications
You must be signed in to change notification settings - Fork 7
Assertions
Assert that the subject is identical (===
, same value and type) to another value.
assert.that(3).is("3")(); // FAIL, 3 === "3" is false since they are of different types
assert.that(3).is(3)(); // PASS
For comparing the members of objects (including Arrays, Dates, etc), the equals
assertion usually more appropriate. For example,
assert.that([1, 2, 3]).is([1, 2, 3])(); // FAIL, they are not the same object
assert.that([1, 2, 3]).equals([1, 2, 3])(); // PASS, each of their members have the same value.
There is one special case for equality checking in Javascript, and that is when comparing to NaN
. Nothing at all is equal to NaN
... not even itself! It is important to know that Tyrtle normalises this behaviour.
var x = NaN;
console.log(x === NaN); // false
console.log(x === x); // false!
assert.that(x).is(NaN)(); // PASS
Remember that is
is the default assertion, and so specifying it by name in any assertion is entirely optional, even when you're using it as a function itself:
// these are equivalent
assert(x).is(3)();
assert(x)(3)();
Assert that two values are not identical. Uses strict equality checking: !==
.
assert(3).is.not('3')(); // PASS
This assertion normalises the behaviour of NaN
in the same way as is()
var x = NaN;
assert(x).not(NaN)(); // FAIL
You can also use .not
as a modifier for any other assertion, even custom assertions.
assert('tyrtle').not.startsWith('t')(); // FAIL
assert('tyrtle').not.startsWith('m')(); // PASS
Assert that two objects have the same values (deep equality).
This assertion should be used when you want to compare two objects to see that they contain the same values. If you are asserting with primitives such as strings or numbers, then it is faster to use .is
.
assert.that({a : 'bar', b : 'baz'})
.equals({b : 'baz', a : 'bar'})(); // PASS, same keys and values.
assert.that(3).equals(3)(); // PASS, but not as efficient
This will recursively search through nested objects.
Assert that the subject variable is truthy. That is, it will pass if the condition subject == true
is true. This will be the case for every value except: 0
, false
, ''
, null
& undefined
.
assert(5).is.ok()(); // PASS
assert([]).is.ok()(); // PASS, even empty arrays are ok
assert({}).is.ok()(); // PASS, even empty objects are ok
assert(false).is.ok()(); // FAIL
Assert the type of a variable (using the typeof
operator).
Allows some types additional to the built-in native types to simplify tests:
- 'array'
- 'date'
- 'regexp'
assert.that(/foo/).is.ofType('regexp')();
assert.that(new Date()).is.ofType('date')();
assert.that([]).is.ofType('array')();
It is important to note, however, that asserting type 'object' will pass for all of these types, since strictly speaking, they are still objects.
var arr = [],
obj = {};
assert.that(arr).is.ofType('object')(); // PASS
assert.that(arr).is.ofType('array')(); // PASS
assert.that(obj).is.ofType('array')(); // FAIL
Assert that a string matches a given regular expression.
assert.that("The cow jumped over the moon").matches(/cow.+moon/)();
Assert that a string starts or ends with a given substring.
assert.that("abcde").endsWith("de")();
assert.that("abcde").startsWith("abc")();
Assert that a String or Array contains a substring or element.
assert(['a', 'b', 'c']).contains('b')(); // uses strict equality checking (===)
assert('foobarbaz').contains('bar')();
The test is performed using the .indexOf
method of the subject, so it can actually apply to any object which implements this method with the same signature and return style as String.indexOf
(-1
to indicate "not found").
var myObject = {
indexOf : function (needle) {
return needle === "what I'm looking for" ? -1 : 0;
}
};
assert.that(myObject).contains("what I'm looking for")(); // FAIL, bad luck, Bono.
assert.that(myObject).contains("something else")(); // PASS
Assert that a function will throw an error when executed. Additionally, a specific type of error or error message can be expected. If this is specified and an error is thrown which does not match the expectation, the assertion will fail.
Though the expected error type/message is optional, it is highly recommended to use it, otherwise if your function is failing in a way which you did not expect, that error will be swallowed and your tests will still pass.
The expectedError
argument can be a string or a regex (in which case these are compared against the error's .message
property), or a constructor (in which case, the thrown error should be an instance of this function).
The subject function will be executed with no arguments or context. If you require arguments, then a closure should be used. This assertion only be applied to subjects of type function
.
assert.that(function () {
(0)();
}).willThrow(TypeError)(); // PASS, error is an instanceof TypeError
assert.that(function () {
throw "abc";
}).willThrow("abc")(); // PASS, the thrown error exactly matches the expected string
assert.that(function () {
throw new Error("Holy Cow!");
}).willThrow(/cow/i)(); // PASS, the message of the error matches the expected regex
Assert that a function will not throw any errors when executed.
The subject function will be executed with no arguments or context. If you require arguments, then a closure should be used. This assertion only be applied to subjects of type function
.
// create closure variables
var x = 3,
self = this
;
assert(function () {
return x + self.y;
}).wontThrow()();
Using this assertion requires use of the Myrtle mocking framework.
Assert that a function which has been spied upon by Myrtle has been called a certain number of times. This assertion takes two forms:
-
.called(Number)
asserts that the function has been called exactly this many times. -
.called()
asserts that the function has been called at least once
// obtain a Myrtle handle
var handle = Myrtle.spy(myObj, 'myFunction');
doSomething();
assert.that(handle).called(3)();
However, when making assertions with Myrtle handles, unless you are cleaning up them in an after
helper, you should use the .and
function of Myrtle. This is because a failed assertion will immediately halt the execution of the test.
Myrtle.spy(myObject, 'myFunction').and(function () {
doSomething();
assert.that(this).called()("It should have been called at least once");
});
This is a special type of assertion, in that it is not part of the assert
object. The test itself (which is accessible as this
inside the test body) has a method called expect
which takes a single number as a value. This should be the number of assertions that you expect the test to execute. Use this to avoid the situation whereby a logic error in the test itself causes some assertions to not be executed, therefore it appears that the test is successful (since no assertions have actually failed!).
this.test("my test", function (assert) {
this.expect(2);
assert(3)(3).since("three is three");
assert(3)(4); // <-- didn't actually execute the assertion
});
Without the call to expect
, the test above would have passed, which clearly was not the intention.
If you are writing asynchronous tests, the expectation is still defined in the test body, not the assertion function.
this.test("my async test", function (done) {
this.expect(2);
// do something asynchronously and then...
done();
}, function (assert) {
assert(3)(3)();
assert('foo')('foo')();
});