UNPKG

7.45 kBMarkdownView Raw
1assertive
2=========
3
4A terse, yet expressive assertion library
5
6Is Assertive different from other assertion libraries?
7----------------------------------------------------------------------
8
9Assertive aims to make the exact cause of breakage and intent of tests
10as fast and easy to spot as possible, with much attention paid to both
11the colour and alignment of expected and actual data, so you should be
12able to glean what you need immediately.
13
14It also tries to pre-empt false negative tests from ever happening, by
15rigorously testing for correct assertion invocation and by avoiding to
16pick names for assertions with a track record of being misinterpreted,
17not just by people reading the code, but also by programmers _writing_
18them, which can make even 100%-test-coverage code fail on behalf of it
19testing for the wrong thing.
20
21Semantic Versioning
22----------------------------------------------------------------------
23
24Assertive uses [semver](http://semver.org/) version numbers, though we
25should point out that we may tighten assertion checks in minor version
26number updates, making code that previously silently passed, now fail.
27
28Case in point: before v1.3.0, code using an assertion to verify that a
29string included the empty string, would do just that. In other words -
30nothing, since that assertion does not test anything. Now, such a test
31is flagged as a bug in your test suite that you should fix, as that is
32not asserting something about your code, but about strings in general.
33
34In Assertive, breaking changes implying a major version bump, would be
35things like argument order changes. If you really do not want improved
36coverage against this type of error with a random minor version update
37you should pin a version you like in your `package.json` rather than a
38version range.
39
40Usage
41----------------------------------------------------------------------
42
43Each assertion lets you state a condition and an optional help message
44about what semantics your test asserts, which gets presented first, if
45the assertion fails. (This is generally much more useful than messages
46along the lines of "expected true to be false", especially when it may
47be hard to tell later what the intended purpose of a test really was.)
48
49Besides failing when what each assertion guards against, they also all
50fail if you pass too few, too many or otherwise illegal parameters, as
51when a tired programmer expects "expect" to compare the two parameters
52he passed in some way and trip when they mismatch, though all it would
53ever test is that the first was truthy. To not get test suites full of
54almost-no-op tests like that, Assertive fails straight away like this:
55
56```
57Expected: true
58Actually: 10
59```
60
61There have been test suites full of no-op tests similar to this, which
62have gone undetected for months or years, giving a false sense of what
63regressions you are guarded against.
64
65You may pass any of the functions an item to be tested as a promise,
66and it will be tested after the promise is resolved. In this case, the
67test will return a promise which will be resolved or rejected as appropriate.
68A promise-aware test runner (e.g. [Mocha](https://mochajs.org/)
69version >= 1.18.0) is highly recommended.
70
71These docs show a typical invocation, and what you see when it failed:
72
73
74### `expect`
75```javascript
76// fail if bool != true
77assert.expect(bool);
78```
79
80```javascript
81expect('2 > 1', 2 > 1);
82// Assertion failed: 2 > 1
83```
84
85
86### `truthy`
87
88**Note**: Using `truthy` in your tests is a code smell.
89More often than not there is another, more precise test.
90Only use `truthy` when there is no way of knowing what the actual value will be.
91If `bool` is the result of a boolean operation, use `expect`.
92If `bool` is an unknown value, use `match` or `include` to narrow it down.
93
94```javascript
95// fail if !bool
96assert.truthy(bool);
97assert.truthy(explanation, bool);
98```
99
100```javascript
101truthy('something was populated in the email field', form.email.value);
102
103// Assertion failed: something was populated in the email field
104// expected undefined to be truthy
105```
106
107
108### `equal`
109```javascript
110// fail unless actual === expected
111assert.equal(expected, actual);
112assert.equal(explanation, expected, actual);
113
114// Assertion failed: decode the Epoch to 0s after Jan 1st, 1970
115// Expected 86400000 to be
116// equal to 0
117```
118
119### `deepEqual`
120```javascript
121// fail unless _.isEqual(expected, actual)
122assert.deepEqual(expected, actual);
123assert.deepEqual(explanation, expected, actual);
124
125/*
126Assertion failed: ensure that all methods we tested were handled, and in the right order
127Actual: - Expected: +
128 {
129 "methods": [
130 "GET",
131- "GET",
132+ "POST",
133+ "PUT",
134+ "DELETE"
135 ]
136 }
137*/
138```
139
140### `include`
141```javascript
142// fail unless haystack has a substring needle, or _.include haystack, needle
143assert.include(needle, haystack);
144assert.include(explanation, needle, haystack);
145
146// Assertion failed: only accept supported, case-normalized method names
147// expected ["GET","POST","PUT","DELETE"]
148// to include "get"
149```
150
151### `match`
152```javascript
153// fail unless regexp matches the given string, or regexp.test string
154assert.match(regexp, string);
155assert.match(explanation, regexp, needle);
156
157// Assertion failed: only affirmative pirate answers accepted
158// Expected: /aye|yar+/
159// to match: "nay"
160```
161
162### `throws`
163```javascript
164// fail unless the provided functionThatThrows() calls throw
165// (on non-failures the return value is whatever was thrown)
166const err = assert.throws(functionThatThrows);
167const err = assert.throws(explanation, functionThatThrows);
168
169// Assertion failed: ensure that bad inputs throw an error
170// didn't throw an exception as expected to
171```
172
173### `hasType`
174```javascript
175// fail unless _.isType(value) is true for given Type, or the
176// same test for a more specific type (listed above) was true
177assert.hasType(<type>, value);
178assert.hasType(explanation, <type>, value);
179assert.hasType(null, value)
180assert.hasType(Date, value)
181assert.hasType(Array, value)
182assert.hasType(String, value)
183assert.hasType(RegExp, value)
184assert.hasType(Boolean, value)
185assert.hasType(Function, value)
186assert.hasType(Object, value)
187assert.hasType(NaN, value)
188assert.hasType(Number, value)
189assert.hasType(undefined, value)
190```
191
192### `resolves`
193```javascript
194// Wait for promise to resolve, then resolve if successful, reject otherwise
195// Always returns a promise, unless called with non-promise (not allowed)
196const samePromise = assert.resolves(promise)
197const samePromise = assert.resolves(explanation, promise)
198
199// Assertion failed: should resolve to good stuff
200// Promise was rejected despite resolves assertion:
201// Timeout in 10000ms
202```
203
204### `rejects`
205```javascript
206// Wait for promise to reject, resolve with error if it does, reject otherwise
207// Basically inverse of resolves(), but resolves with the error for more testing
208// Always returns a promise, unless called with non-promise (not allowed)
209const promiseForErr = assert.rejects(promise)
210const promiseForErr = assert.rejects(explanation, promise)
211
212// Assertion failed: should reject after Timeout
213// Promise wasn't rejected as expected to
214```
215
216### `falsey`, `notEqual`, `notDeepEqual`, `notInclude`, `notMatch`, `notThrows`, `notHasType`
217Versions of the above functions taking the same arguments, but asserting
218the opposite outcome. The assertion failure messages are just as helpful.
219
220License
221----------------------------------------------------------------------
222
223[BSD 3-Clause open source license](LICENSE)