2020-05-09 21:09:42 -04:00
|
|
|
# Testing
|
|
|
|
|
|
|
|
Deno has a built-in test runner that you can use for testing JavaScript or
|
|
|
|
TypeScript code.
|
|
|
|
|
|
|
|
## Writing tests
|
|
|
|
|
|
|
|
To define a test you need to call `Deno.test` with a name and function to be
|
2020-06-18 06:13:56 -04:00
|
|
|
tested. There are two styles you can use.
|
2020-05-09 21:09:42 -04:00
|
|
|
|
|
|
|
```ts
|
2020-06-18 06:13:56 -04:00
|
|
|
// Simple name and function, compact form, but not configurable
|
|
|
|
Deno.test("hello world #1", () => {
|
2020-05-09 21:09:42 -04:00
|
|
|
const x = 1 + 2;
|
2020-06-18 06:13:56 -04:00
|
|
|
assertEquals(x, 3);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Fully fledged test definition, longer form, but configurable (see below)
|
|
|
|
Deno.test({
|
|
|
|
name: "hello world #2",
|
2020-06-25 12:35:34 -04:00
|
|
|
fn: () => {
|
2020-06-18 06:13:56 -04:00
|
|
|
const x = 1 + 2;
|
|
|
|
assertEquals(x, 3);
|
2020-06-25 12:35:34 -04:00
|
|
|
},
|
2020-05-09 21:09:42 -04:00
|
|
|
});
|
|
|
|
```
|
|
|
|
|
2020-06-18 06:13:56 -04:00
|
|
|
## Assertions
|
|
|
|
|
2020-07-31 05:12:20 -04:00
|
|
|
There are some useful assertion utilities at
|
|
|
|
https://deno.land/std@$STD_VERSION/testing#usage to make testing easier:
|
2020-05-09 21:09:42 -04:00
|
|
|
|
|
|
|
```ts
|
2020-06-18 06:13:56 -04:00
|
|
|
import {
|
|
|
|
assertEquals,
|
|
|
|
assertArrayContains,
|
2020-07-31 05:12:20 -04:00
|
|
|
} from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
2020-05-09 21:09:42 -04:00
|
|
|
|
|
|
|
Deno.test("hello world", () => {
|
|
|
|
const x = 1 + 2;
|
|
|
|
assertEquals(x, 3);
|
2020-06-18 06:13:56 -04:00
|
|
|
assertArrayContains([1, 2, 3, 4, 5, 6], [3], "Expected 3 to be in the array");
|
2020-05-09 21:09:42 -04:00
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
### Async functions
|
|
|
|
|
|
|
|
You can also test asynchronous code by passing a test function that returns a
|
|
|
|
promise. For this you can use the `async` keyword when defining a function:
|
|
|
|
|
|
|
|
```ts
|
2020-07-31 05:12:20 -04:00
|
|
|
import { delay } from "https://deno.land/std@$STD_VERSION/async/delay.ts";
|
2020-05-25 09:12:45 -04:00
|
|
|
|
2020-05-09 21:09:42 -04:00
|
|
|
Deno.test("async hello world", async () => {
|
|
|
|
const x = 1 + 2;
|
|
|
|
|
|
|
|
// await some async task
|
|
|
|
await delay(100);
|
|
|
|
|
|
|
|
if (x !== 3) {
|
|
|
|
throw Error("x should be equal to 3");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
### Resource and async op sanitizers
|
|
|
|
|
|
|
|
Certain actions in Deno create resources in the resource table
|
|
|
|
([learn more here](./contributing/architecture.md)). These resources should be
|
|
|
|
closed after you are done using them.
|
|
|
|
|
2020-06-18 06:13:56 -04:00
|
|
|
For each test definition, the test runner checks that all resources created in
|
2020-05-09 21:09:42 -04:00
|
|
|
this test have been closed. This is to prevent resource 'leaks'. This is enabled
|
|
|
|
by default for all tests, but can be disabled by setting the `sanitizeResources`
|
|
|
|
boolean to false in the test definition.
|
|
|
|
|
|
|
|
The same is true for async operation like interacting with the filesystem. The
|
|
|
|
test runner checks that each operation you start in the test is completed before
|
|
|
|
the end of the test. This is enabled by default for all tests, but can be
|
|
|
|
disabled by setting the `sanitizeOps` boolean to false in the test definition.
|
|
|
|
|
|
|
|
```ts
|
|
|
|
Deno.test({
|
|
|
|
name: "leaky test",
|
|
|
|
fn() {
|
|
|
|
Deno.open("hello.txt");
|
|
|
|
},
|
|
|
|
sanitizeResources: false,
|
|
|
|
sanitizeOps: false,
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
2020-06-18 06:13:56 -04:00
|
|
|
## Running tests
|
|
|
|
|
|
|
|
To run the test, call `deno test` with the file that contains your test
|
|
|
|
function. You can also omit the file name, in which case all tests in the
|
|
|
|
current directory (recursively) that match the glob
|
|
|
|
`{*_,*.,}test.{js,mjs,ts,jsx,tsx}` will be run. If you pass a directory, all
|
|
|
|
files in the directory that match this glob will be run.
|
|
|
|
|
|
|
|
```shell
|
2020-08-24 12:36:56 -04:00
|
|
|
# Run all tests in the current directory and all sub-directories
|
2020-06-18 06:13:56 -04:00
|
|
|
deno test
|
|
|
|
|
|
|
|
# Run all tests in the util directory
|
|
|
|
deno test util/
|
|
|
|
|
|
|
|
# Run just my_test.ts
|
|
|
|
deno test my_test.ts
|
|
|
|
```
|
|
|
|
|
|
|
|
`deno test` uses the same permission model as `deno run` and therefore will
|
|
|
|
require, for example, `--allow-write` to write to the file system during
|
|
|
|
testing.
|
|
|
|
|
|
|
|
To see all runtime options with `deno test`, you can reference the command line
|
|
|
|
help:
|
|
|
|
|
|
|
|
```shell
|
|
|
|
deno help test
|
|
|
|
```
|
|
|
|
|
|
|
|
## Filtering
|
|
|
|
|
|
|
|
There are a number of options to filter the tests you are running.
|
|
|
|
|
|
|
|
### Command line filtering
|
|
|
|
|
|
|
|
Tests can be run individually or in groups using the command line `--filter`
|
|
|
|
option.
|
|
|
|
|
2020-07-07 09:13:38 -04:00
|
|
|
The filter flags accept a string or a pattern as value.
|
|
|
|
|
|
|
|
Assuming the following tests:
|
|
|
|
|
|
|
|
```ts
|
|
|
|
Deno.test({ name: "my-test", fn: myTest });
|
|
|
|
Deno.test({ name: "test-1", fn: test1 });
|
|
|
|
Deno.test({ name: "test2", fn: test2 });
|
|
|
|
```
|
|
|
|
|
|
|
|
This command will run all of these tests because they all contain the word
|
|
|
|
"test".
|
|
|
|
|
2020-06-18 06:13:56 -04:00
|
|
|
```shell
|
2020-07-07 09:13:38 -04:00
|
|
|
deno test --filter "test" tests/
|
2020-06-18 06:13:56 -04:00
|
|
|
```
|
|
|
|
|
2020-07-07 09:13:38 -04:00
|
|
|
On the flip side, the following command uses a pattern and will run the second
|
|
|
|
and third tests.
|
|
|
|
|
|
|
|
```shell
|
|
|
|
deno test --filter "/test-*\d/" tests/
|
|
|
|
```
|
|
|
|
|
|
|
|
_To let Deno know that you want to use a pattern, wrap your filter with
|
|
|
|
forward-slashes like the JavaScript syntactic sugar for a REGEX._
|
|
|
|
|
2020-06-18 06:13:56 -04:00
|
|
|
### Test definition filtering
|
|
|
|
|
|
|
|
Within the tests themselves, you have two options for filtering.
|
|
|
|
|
|
|
|
#### Filtering out (Ignoring these tests)
|
2020-05-09 21:09:42 -04:00
|
|
|
|
|
|
|
Sometimes you want to ignore tests based on some sort of condition (for example
|
|
|
|
you only want a test to run on Windows). For this you can use the `ignore`
|
|
|
|
boolean in the test definition. If it is set to true the test will be skipped.
|
|
|
|
|
|
|
|
```ts
|
|
|
|
Deno.test({
|
|
|
|
name: "do macOS feature",
|
|
|
|
ignore: Deno.build.os !== "darwin",
|
|
|
|
fn() {
|
|
|
|
doMacOSFeature();
|
|
|
|
},
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
2020-06-18 06:13:56 -04:00
|
|
|
#### Filtering in (Only run these tests)
|
2020-05-09 21:09:42 -04:00
|
|
|
|
2020-06-18 06:13:56 -04:00
|
|
|
Sometimes you may be in the middle of a problem within a large test class and
|
|
|
|
you would like to focus on just that test and ignore the rest for now. For this
|
|
|
|
you can use the `only` option to tell the test framework to only run tests with
|
|
|
|
this set to true. Multiple tests can set this option. While the test run will
|
|
|
|
report on the success or failure of each test, the overall test run will always
|
|
|
|
fail if any test is flagged with `only`, as this is a temporary measure only
|
|
|
|
which disables nearly all of your tests.
|
2020-05-09 21:09:42 -04:00
|
|
|
|
2020-06-18 06:13:56 -04:00
|
|
|
```ts
|
|
|
|
Deno.test({
|
|
|
|
name: "Focus on this test only",
|
|
|
|
only: true,
|
|
|
|
fn() {
|
|
|
|
testComplicatedStuff();
|
|
|
|
},
|
|
|
|
});
|
2020-05-09 21:09:42 -04:00
|
|
|
```
|
|
|
|
|
2020-06-18 06:13:56 -04:00
|
|
|
## Failing fast
|
2020-06-16 17:17:00 -04:00
|
|
|
|
2020-06-18 06:13:56 -04:00
|
|
|
If you have a long running test suite and wish for it to stop on the first
|
|
|
|
failure, you can specify the `--failfast` flag when running the suite.
|
2020-06-16 17:17:00 -04:00
|
|
|
|
|
|
|
```shell
|
2020-06-18 06:13:56 -04:00
|
|
|
deno test --failfast
|
2020-06-16 17:17:00 -04:00
|
|
|
```
|