Skip to content

Instantly share code, notes, and snippets.

@aelyseev
Forked from subfuzion/README.md
Created September 9, 2022 04:10
Show Gist options
  • Save aelyseev/6e33e81c128c7bef1af68651482813a1 to your computer and use it in GitHub Desktop.
Save aelyseev/6e33e81c128c7bef1af68651482813a1 to your computer and use it in GitHub Desktop.

Revisions

  1. @subfuzion subfuzion revised this gist Aug 16, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -228,7 +228,7 @@ describe("test suite", () => {
    });
    ```

    ## Running a subset of tests
    ## 6. Running a subset of tests

    Aside from explicitly running test modules that aren't automatically run by
    matching the naming patterns described previously, you can control which tests
  2. @subfuzion subfuzion revised this gist Aug 16, 2022. 1 changed file with 48 additions and 0 deletions.
    48 changes: 48 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -228,7 +228,55 @@ describe("test suite", () => {
    });
    ```

    ## Running a subset of tests

    Aside from explicitly running test modules that aren't automatically run by
    matching the naming patterns described previously, you can control which tests
    run using the `--test-only` option.

    ```text
    $ node --test-only test/test.js
    ```

    ```javascript
    // Run this test suite
    test("test suite", {only: true}, async t => {

    // Only run tests with the `only` option set.
    t.runOnly(true);

    await t.test("this test is skipped");

    await t.test("this test is also skipped");

    await t.test("nested test suite will run", {only: true}, async t => {

    // Only run tests with the `only` option set.
    t.runOnly(true);

    await t.test("this test is skipped", () => {
    assert(false);
    });

    await t.test("will succeed", {only: true}, () => {
    assert(true);
    });
    });
    });

    test("this test suite is skipped", async t => {
    await t.test("this test is skipped", () => {
    assert(false);
    });
    });
    ```

    Only one test in the example above will be run. See the [--test-only]
    section for more details.


    <!-- references -->

    [--test-only]: https://nodejs.org/api/test.html#only-tests
    [online reference]: https://nodejs.org/api/test.html
    [TAP]: https://testanything.org/
  3. @subfuzion subfuzion revised this gist Aug 15, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    # Node.js 18 Test Runner

    Node.js v18 introduces test runner support. This currently experimental feature
    gives developers the benefits of a structured test harnesses for their package
    gives developers the benefits of a structured test harness for their code
    without having to install a third party test framework, like Mocha or Jest, as a
    dependency. Using the test runner produces [TAP] output.

  4. @subfuzion subfuzion created this gist Aug 15, 2022.
    234 changes: 234 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,234 @@
    # Node.js 18 Test Runner

    Node.js v18 introduces test runner support. This currently experimental feature
    gives developers the benefits of a structured test harnesses for their package
    without having to install a third party test framework, like Mocha or Jest, as a
    dependency. Using the test runner produces [TAP] output.

    The [online reference] provides the most up-to-date, authoritative reference and
    have plenty of good testing examples. However, there are a few points that might
    not be immediately obvious from the reference, so those are highlighted here.

    ## 1. Test any Node module that returns an exit code

    Create an empty test file named `a.js`:

    ```text
    touch a.js
    ```

    Run the following command:

    ```text
    node --test a.js
    ```

    You should see output similar to the following:

    ```text
    $ node --test a.js
    TAP version 13
    # Subtest: /path/to/a.js
    ok 1 - /path/to/a.js
    ---
    duration_ms: 0.042418125
    ...
    1..1
    # tests 1
    # pass 1
    # fail 0
    # cancelled 0
    # skipped 0
    # todo 0
    # duration_ms 0.074304125
    ```

    Now modify `a.js` so that the module exits with a **non-zero** exit code:

    ```javascript
    // Test will fail with any non-zero exit code
    process.exit(1);
    ```

    You should see output similar to the following:

    ```text
    $ node --test a.js
    TAP version 13
    # Subtest: /path/to/a.js
    not ok 1 - /path/to/a.js
    ---
    duration_ms: 0.040703959
    failureType: 'subtestsFailed'
    exitCode: 1
    stdout: ''
    stderr: ''
    error: 'test failed'
    code: 'ERR_TEST_FAILURE'
    ...
    1..1
    # tests 1
    # pass 0
    # fail 1
    # cancelled 0
    # skipped 0
    # todo 0
    # duration_ms 0.0623685
    ```

    You can test multiple modules explicitly. For example, with two separate test
    modules (one that returns a non-zero exit code), you would see output similar to
    this:

    ```text
    $ node --test a.js b.js
    TAP version 13
    # Subtest: /path/to/a.js
    not ok 1 - /path/to/a.js
    ---
    duration_ms: 0.040011959
    failureType: 'subtestsFailed'
    exitCode: 1
    stdout: ''
    stderr: ''
    error: 'test failed'
    code: 'ERR_TEST_FAILURE'
    ...
    # Subtest: /path/to/b.js
    ok 2 - /path/to/b.js
    ---
    duration_ms: 0.038038583
    ...
    1..2
    # tests 2
    # pass 1
    # fail 1
    # cancelled 0
    # skipped 0
    # todo 0
    # duration_ms 0.063258125
    ```

    ## 2. Include tests using naming pattern

    In the previous section, tests were specified explicitly. You can read the
    [online reference] for specifics, but generally `node --test` will find and
    execute tests if any of the following naming patterns are used:

    * Files are named any of:
    * `test.EXT`
    * `test-NAME.EXT`
    * `NAME.test.EXT` | `NAME-test.EXT` | `NAME_test.EXT`
    * Any `NAME.EXT` under a `test` directory, recursively.

    Where `EXT` is one of `js`|`cjs`|`mjs`.


    ## 3. Writing test functions

    Create `test/test.js`:

    ```javascript
    import test from "node:test";
    import {strict as assert} from "node:assert";
    ```

    Add a test function:

    ```javascript
    test("should always be true", () => {
    assert(true);
    });
    ```

    And test:

    ```text
    $ node --test
    TAP version 13
    # Subtest: /path/to/test/test.js
    ok 1 - /path/to/test/test.js
    ---
    duration_ms: 0.048303625
    ...
    1..1
    # tests 1
    # pass 1
    # fail 0
    # cancelled 0
    # skipped 0
    # todo 0
    # duration_ms 0.075651083
    ```

    ## 4. Using the TestContext

    You can use the `TestContext` object supplied to your test callback. One
    potentially useful method is `TestContext.diagnostic`, shown below (presumably
    you would use this to provide more useful information as diagnostic output of
    your test code than would be summarized as part of a custom assert error
    message). The diagnostic messages appear after the stack trace for the
    failed test results.

    ```javascript
    test("should be 5", t => {
    t.diagnostic("***DIAGNOSTIC: about to assign val");
    const val = 2 + 2;
    //t.diagnostic(`***DIAGNOSTIC: val=${val}`);
    assert.equal(5, val);
    });
    ```

    Tests can be nested like this:

    ```javascript
    test("test suite", t => {
    t.test("a", t => {
    });

    t.test("b", t => {
    });

    });
    ```

    ## 5. Simplifying with describe and it

    If you're willing to give up access to the `TestContext` object, you can
    simplify writing test suites using `describe` and `it`. You can still nest
    a `test` under `describe`, if you want to:

    ```javascript

    import test, {describe, it} from "node:test";
    import {strict as assert} from "node:assert";

    describe("test suite", () => {
    it("is always true", () => {
    assert(true);
    });

    it("tests val", {skip: true}, () => {
    const val = 2 + 2;
    assert.equal(5, val);
    });

    it("tests val", {todo: true}, () => {
    const val = 2 + 2;
    assert.equal(5, val);
    });

    test("val is 5", t => {
    t.diagnostic("***DIAGNOSTIC: about to assign val");
    const val = 2 + 2;
    t.diagnostic(`***DIAGNOSTIC: val=${val}`);
    assert.equal(5, val);
    });
    });
    ```

    <!-- references -->

    [online reference]: https://nodejs.org/api/test.html
    [TAP]: https://testanything.org/