2019-01-06 14:19:15 -05:00
|
|
|
# Testing
|
2019-01-03 14:16:15 -05:00
|
|
|
|
2019-10-09 17:22:22 -04:00
|
|
|
This module provides a few basic utilities to make testing easier and consistent
|
|
|
|
in Deno.
|
2019-01-15 21:57:40 -05:00
|
|
|
|
2019-01-03 14:16:15 -05:00
|
|
|
## Usage
|
|
|
|
|
2020-02-11 15:50:20 -05:00
|
|
|
`testing/asserts.ts` module provides range of assertion helpers. If the
|
|
|
|
assertion is false an `AssertionError` will be thrown which will result in
|
|
|
|
pretty-printed diff of failing assertion.
|
2019-01-15 21:57:40 -05:00
|
|
|
|
2019-06-24 09:08:14 -04:00
|
|
|
- `equal()` - Deep comparison function, where `actual` and `expected` are
|
2019-03-06 16:39:50 -05:00
|
|
|
compared deeply, and if they vary, `equal` returns `false`.
|
2019-01-15 21:57:40 -05:00
|
|
|
- `assert()` - Expects a boolean value, throws if the value is `false`.
|
2019-03-06 19:42:24 -05:00
|
|
|
- `assertEquals()` - Uses the `equal` comparison and throws if the `actual` and
|
2019-01-15 21:57:40 -05:00
|
|
|
`expected` are not equal.
|
2019-10-09 17:22:22 -04:00
|
|
|
- `assertNotEquals()` - Uses the `equal` comparison and throws if the `actual`
|
|
|
|
and `expected` are equal.
|
2020-06-16 17:22:54 -04:00
|
|
|
- `assertStrictEquals()` - Compares `actual` and `expected` strictly, therefore
|
|
|
|
for non-primitives the values must reference the same instance.
|
|
|
|
- `assertStringContains()` - Make an assertion that `actual` contains
|
|
|
|
`expected`.
|
2019-03-18 11:08:01 -04:00
|
|
|
- `assertMatch()` - Make an assertion that `actual` match RegExp `expected`.
|
2020-08-27 05:03:15 -04:00
|
|
|
- `assertNotMatch()` - Make an assertion that `actual` not match RegExp
|
|
|
|
`expected`.
|
2019-10-09 17:22:22 -04:00
|
|
|
- `assertArrayContains()` - Make an assertion that `actual` array contains the
|
|
|
|
`expected` values.
|
2019-03-06 16:39:50 -05:00
|
|
|
- `assertThrows()` - Expects the passed `fn` to throw. If `fn` does not throw,
|
2019-01-15 21:57:40 -05:00
|
|
|
this function does. Also compares any errors thrown to an optional expected
|
|
|
|
`Error` class and checks that the error `.message` includes an optional
|
|
|
|
string.
|
2019-03-06 16:39:50 -05:00
|
|
|
- `assertThrowsAsync()` - Expects the passed `fn` to be async and throw (or
|
2019-01-22 01:15:25 -05:00
|
|
|
return a `Promise` that rejects). If the `fn` does not throw or reject, this
|
|
|
|
function will throw asynchronously. Also compares any errors thrown to an
|
|
|
|
optional expected `Error` class and checks that the error `.message` includes
|
|
|
|
an optional string.
|
2020-10-03 16:19:11 -04:00
|
|
|
- `unimplemented()` - Use this to stub out methods that will throw when invoked.
|
|
|
|
- `unreachable()` - Used to assert unreachable code.
|
2019-01-15 21:57:40 -05:00
|
|
|
|
|
|
|
Basic usage:
|
|
|
|
|
2019-01-03 14:16:15 -05:00
|
|
|
```ts
|
2020-10-04 08:18:36 -04:00
|
|
|
import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
2019-01-03 14:16:15 -05:00
|
|
|
|
2020-02-11 15:50:20 -05:00
|
|
|
Deno.test({
|
2019-01-06 14:19:15 -05:00
|
|
|
name: "testing example",
|
2019-04-24 07:41:23 -04:00
|
|
|
fn(): void {
|
2019-04-05 07:19:13 -04:00
|
|
|
assertEquals("world", "world");
|
|
|
|
assertEquals({ hello: "world" }, { hello: "world" });
|
2020-03-28 13:03:49 -04:00
|
|
|
},
|
2019-01-03 14:16:15 -05:00
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
Short syntax (named function instead of object):
|
2019-01-06 14:19:15 -05:00
|
|
|
|
2019-01-03 14:16:15 -05:00
|
|
|
```ts
|
2020-04-28 06:33:09 -04:00
|
|
|
Deno.test("example", function (): void {
|
2019-04-05 07:19:13 -04:00
|
|
|
assertEquals("world", "world");
|
|
|
|
assertEquals({ hello: "world" }, { hello: "world" });
|
2019-01-15 21:57:40 -05:00
|
|
|
});
|
|
|
|
```
|
|
|
|
|
2020-06-16 17:22:54 -04:00
|
|
|
Using `assertStrictEquals()`:
|
2019-01-15 21:57:40 -05:00
|
|
|
|
|
|
|
```ts
|
2020-04-28 06:33:09 -04:00
|
|
|
Deno.test("isStrictlyEqual", function (): void {
|
2019-01-15 21:57:40 -05:00
|
|
|
const a = {};
|
|
|
|
const b = a;
|
2020-06-16 17:22:54 -04:00
|
|
|
assertStrictEquals(a, b);
|
2019-01-15 21:57:40 -05:00
|
|
|
});
|
|
|
|
|
|
|
|
// This test fails
|
2020-04-28 06:33:09 -04:00
|
|
|
Deno.test("isNotStrictlyEqual", function (): void {
|
2019-01-15 21:57:40 -05:00
|
|
|
const a = {};
|
|
|
|
const b = {};
|
2020-06-16 17:22:54 -04:00
|
|
|
assertStrictEquals(a, b);
|
2019-01-15 21:57:40 -05:00
|
|
|
});
|
|
|
|
```
|
|
|
|
|
2019-03-06 16:39:50 -05:00
|
|
|
Using `assertThrows()`:
|
2019-01-15 21:57:40 -05:00
|
|
|
|
|
|
|
```ts
|
2020-04-28 06:33:09 -04:00
|
|
|
Deno.test("doesThrow", function (): void {
|
2019-11-13 13:42:34 -05:00
|
|
|
assertThrows((): void => {
|
|
|
|
throw new TypeError("hello world!");
|
|
|
|
});
|
2019-04-24 07:41:23 -04:00
|
|
|
assertThrows((): void => {
|
2019-01-15 21:57:40 -05:00
|
|
|
throw new TypeError("hello world!");
|
|
|
|
}, TypeError);
|
2019-03-06 16:39:50 -05:00
|
|
|
assertThrows(
|
2019-04-24 07:41:23 -04:00
|
|
|
(): void => {
|
2019-01-15 21:57:40 -05:00
|
|
|
throw new TypeError("hello world!");
|
|
|
|
},
|
|
|
|
TypeError,
|
2020-07-14 15:24:17 -04:00
|
|
|
"hello",
|
2019-01-15 21:57:40 -05:00
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2020-10-03 16:19:11 -04:00
|
|
|
// This test will not pass.
|
2020-04-28 06:33:09 -04:00
|
|
|
Deno.test("fails", function (): void {
|
2019-11-13 13:42:34 -05:00
|
|
|
assertThrows((): void => {
|
|
|
|
console.log("Hello world");
|
|
|
|
});
|
2019-01-03 14:16:15 -05:00
|
|
|
});
|
2019-01-04 05:09:42 -05:00
|
|
|
```
|
2019-01-22 01:15:25 -05:00
|
|
|
|
2019-03-06 16:39:50 -05:00
|
|
|
Using `assertThrowsAsync()`:
|
2019-01-22 01:15:25 -05:00
|
|
|
|
|
|
|
```ts
|
2020-04-28 06:33:09 -04:00
|
|
|
Deno.test("doesThrow", async function (): Promise<void> {
|
2019-04-24 07:41:23 -04:00
|
|
|
await assertThrowsAsync(
|
|
|
|
async (): Promise<void> => {
|
|
|
|
throw new TypeError("hello world!");
|
2020-07-14 15:24:17 -04:00
|
|
|
},
|
2019-04-24 07:41:23 -04:00
|
|
|
);
|
|
|
|
await assertThrowsAsync(async (): Promise<void> => {
|
2019-01-22 01:15:25 -05:00
|
|
|
throw new TypeError("hello world!");
|
|
|
|
}, TypeError);
|
2019-03-19 13:22:33 -04:00
|
|
|
await assertThrowsAsync(
|
2019-04-24 07:41:23 -04:00
|
|
|
async (): Promise<void> => {
|
2019-01-22 01:15:25 -05:00
|
|
|
throw new TypeError("hello world!");
|
|
|
|
},
|
|
|
|
TypeError,
|
2020-07-14 15:24:17 -04:00
|
|
|
"hello",
|
2019-01-22 01:15:25 -05:00
|
|
|
);
|
2019-04-24 07:41:23 -04:00
|
|
|
await assertThrowsAsync(
|
|
|
|
async (): Promise<void> => {
|
|
|
|
return Promise.reject(new Error());
|
2020-07-14 15:24:17 -04:00
|
|
|
},
|
2019-04-24 07:41:23 -04:00
|
|
|
);
|
2019-01-22 01:15:25 -05:00
|
|
|
});
|
|
|
|
|
2020-10-03 16:19:11 -04:00
|
|
|
// This test will not pass.
|
2020-04-28 06:33:09 -04:00
|
|
|
Deno.test("fails", async function (): Promise<void> {
|
2019-04-24 07:41:23 -04:00
|
|
|
await assertThrowsAsync(
|
|
|
|
async (): Promise<void> => {
|
|
|
|
console.log("Hello world");
|
2020-07-14 15:24:17 -04:00
|
|
|
},
|
2019-04-24 07:41:23 -04:00
|
|
|
);
|
2019-01-22 01:15:25 -05:00
|
|
|
});
|
|
|
|
```
|
2019-03-11 14:21:13 -04:00
|
|
|
|
2020-06-03 13:44:37 -04:00
|
|
|
## Benching
|
2019-03-11 14:21:13 -04:00
|
|
|
|
2020-06-03 13:44:37 -04:00
|
|
|
With this module you can benchmark your code and get information on how is it
|
|
|
|
performing.
|
|
|
|
|
|
|
|
### Basic usage:
|
|
|
|
|
|
|
|
Benchmarks can be registered using the `bench` function, where you can define a
|
|
|
|
code, that should be benchmarked. `b.start()` has to be called at the start of
|
|
|
|
the part you want to benchmark and `b.stop()` at the end of it, otherwise an
|
|
|
|
error will be thrown.
|
|
|
|
|
|
|
|
After that simply calling `runBenchmarks()` will benchmark all registered
|
|
|
|
benchmarks and log the results in the commandline.
|
2019-03-11 14:21:13 -04:00
|
|
|
|
|
|
|
```ts
|
2020-10-04 08:18:36 -04:00
|
|
|
import {
|
|
|
|
bench,
|
|
|
|
runBenchmarks,
|
|
|
|
} from "https://deno.land/std@$STD_VERSION/testing/bench.ts";
|
2019-03-11 14:21:13 -04:00
|
|
|
|
2019-04-24 07:41:23 -04:00
|
|
|
bench(function forIncrementX1e9(b): void {
|
2019-03-11 14:21:13 -04:00
|
|
|
b.start();
|
|
|
|
for (let i = 0; i < 1e9; i++);
|
|
|
|
b.stop();
|
|
|
|
});
|
|
|
|
|
|
|
|
runBenchmarks();
|
|
|
|
```
|
|
|
|
|
|
|
|
Averaging execution time over multiple runs:
|
|
|
|
|
|
|
|
```ts
|
|
|
|
bench({
|
|
|
|
name: "runs100ForIncrementX1e6",
|
|
|
|
runs: 100,
|
2019-04-24 07:41:23 -04:00
|
|
|
func(b): void {
|
2019-03-11 14:21:13 -04:00
|
|
|
b.start();
|
|
|
|
for (let i = 0; i < 1e6; i++);
|
|
|
|
b.stop();
|
2020-03-28 13:03:49 -04:00
|
|
|
},
|
2019-03-11 14:21:13 -04:00
|
|
|
});
|
|
|
|
```
|
|
|
|
|
2020-06-03 13:44:37 -04:00
|
|
|
Running specific benchmarks using regular expressions:
|
|
|
|
|
|
|
|
```ts
|
|
|
|
runBenchmarks({ only: /desired/, skip: /exceptions/ });
|
|
|
|
```
|
|
|
|
|
|
|
|
### Processing benchmark results
|
|
|
|
|
|
|
|
`runBenchmarks()` returns a `Promise<BenchmarkRunResult>`, so you can process
|
|
|
|
the benchmarking results yourself. It contains detailed results of each
|
|
|
|
benchmark's run as `BenchmarkResult` s.
|
|
|
|
|
|
|
|
```ts
|
|
|
|
runBenchmarks()
|
|
|
|
.then((results: BenchmarkRunResult) => {
|
|
|
|
console.log(results);
|
|
|
|
})
|
|
|
|
.catch((error: Error) => {
|
2020-10-03 16:19:11 -04:00
|
|
|
// ... errors if benchmark was badly constructed.
|
2020-06-03 13:44:37 -04:00
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
### Processing benchmarking progress
|
|
|
|
|
|
|
|
`runBenchmarks()` accepts an optional progress handler callback function, so you
|
|
|
|
can get information on the progress of the running benchmarking.
|
|
|
|
|
|
|
|
Using `{ silent: true }` means you wont see the default progression logs in the
|
|
|
|
commandline.
|
|
|
|
|
|
|
|
```ts
|
|
|
|
runBenchmarks({ silent: true }, (p: BenchmarkRunProgress) => {
|
2020-10-03 16:19:11 -04:00
|
|
|
// initial progress data.
|
2020-06-03 13:44:37 -04:00
|
|
|
if (p.state === ProgressState.BenchmarkingStart) {
|
|
|
|
console.log(
|
2020-07-14 15:24:17 -04:00
|
|
|
`Starting benchmarking. Queued: ${p.queued.length}, filtered: ${p.filtered}`,
|
2020-06-03 13:44:37 -04:00
|
|
|
);
|
|
|
|
}
|
|
|
|
// ...
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
2019-03-11 14:21:13 -04:00
|
|
|
#### Benching API
|
|
|
|
|
|
|
|
##### `bench(benchmark: BenchmarkDefinition | BenchmarkFunction): void`
|
|
|
|
|
|
|
|
Registers a benchmark that will be run once `runBenchmarks` is called.
|
|
|
|
|
2020-06-09 11:19:06 -04:00
|
|
|
##### `runBenchmarks(opts?: BenchmarkRunOptions, progressCb?: (p: BenchmarkRunProgress) => void | Promise<void>): Promise<BenchmarkRunResult>`
|
2019-03-11 14:21:13 -04:00
|
|
|
|
|
|
|
Runs all registered benchmarks serially. Filtering can be applied by setting
|
2019-10-09 17:22:22 -04:00
|
|
|
`BenchmarkRunOptions.only` and/or `BenchmarkRunOptions.skip` to regular
|
2020-06-03 13:44:37 -04:00
|
|
|
expressions matching benchmark names. Default progression logs can be turned off
|
|
|
|
with the `BenchmarkRunOptions.silent` flag.
|
2019-03-11 14:21:13 -04:00
|
|
|
|
2020-06-03 13:44:37 -04:00
|
|
|
##### `clearBenchmarks(opts?: BenchmarkClearOptions): void`
|
2019-03-11 14:21:13 -04:00
|
|
|
|
2020-06-03 13:44:37 -04:00
|
|
|
Clears all registered benchmarks, so calling `runBenchmarks()` after it wont run
|
|
|
|
them. Filtering can be applied by setting `BenchmarkRunOptions.only` and/or
|
|
|
|
`BenchmarkRunOptions.skip` to regular expressions matching benchmark names.
|