Spec-Zone.ru › Deno 2

Testing

Robust testing and benchmarking capabilities to ensure code quality and performance.

Eg Deno.test, Deno.bench


function Deno.bench

Overload 1

bench(b: BenchDefinition): void

Register a benchmark test which will be run when deno bench is used on the command line and the containing module looks like a bench module.

A module "looks like a bench module" when deno bench selects it for execution. When you pass explicit file paths to deno bench, those files are always run. When you run deno bench without paths, it walks the directory looking for files whose name (ignoring the extension) ends with _bench or .bench, or is exactly bench. Examples are foo_bench.ts, foo.bench.js, or bench.ts. Supported extensions are the same as for tests (.ts, .tsx, .js, .jsx, .mjs, .mts, .cjs, .cts).

If the test function (fn) returns a promise or is async, the test runner will await resolution to consider the test complete.

import { assertEquals } from "jsr:@std/assert";

Deno.bench({
  name: "example test",
  fn() {
    assertEquals("world", "world");
  },
});

Deno.bench({
  name: "example ignored test",
  ignore: Deno.build.os === "windows",
  fn() {
    // This test is ignored only on Windows machines
  },
});

Deno.bench({
  name: "example async test",
  async fn() {
    const decoder = new TextDecoder("utf-8");
    const data = await Deno.readFile("hello_world.txt");
    assertEquals(decoder.decode(data), "Hello world");
  }
});

Parameters

b: BenchDefinition

Return Type

void

Overload 2

bench(
name: string,
fn: (b: BenchContext) => void | Promise<void>,
): void

Register a benchmark test which will be run when deno bench is used on the command line and the containing module looks like a bench module.

If the test function (fn) returns a promise or is async, the test runner will await resolution to consider the test complete.

import { assertEquals } from "jsr:@std/assert";

Deno.bench("My test description", () => {
  assertEquals("hello", "hello");
});

Deno.bench("My async test description", async () => {
  const decoder = new TextDecoder("utf-8");
  const data = await Deno.readFile("hello_world.txt");
  assertEquals(decoder.decode(data), "Hello world");
});

Parameters

name: string
fn: (b: BenchContext) => void | Promise<void>

Return Type

void

Overload 3

bench(fn: (b: BenchContext) => void | Promise<void>): void

Register a benchmark test which will be run when deno bench is used on the command line and the containing module looks like a bench module.

If the test function (fn) returns a promise or is async, the test runner will await resolution to consider the test complete.

import { assertEquals } from "jsr:@std/assert";

Deno.bench(function myTestName() {
  assertEquals("hello", "hello");
});

Deno.bench(async function myOtherTestName() {
  const decoder = new TextDecoder("utf-8");
  const data = await Deno.readFile("hello_world.txt");
  assertEquals(decoder.decode(data), "Hello world");
});

Parameters

fn: (b: BenchContext) => void | Promise<void>

Return Type

void

Overload 4

bench(
name: string,
options: Omit<BenchDefinition, "fn" | "name">,
fn: (b: BenchContext) => void | Promise<void>,
): void

Register a benchmark test which will be run when deno bench is used on the command line and the containing module looks like a bench module.

If the test function (fn) returns a promise or is async, the test runner will await resolution to consider the test complete.

import { assertEquals } from "jsr:@std/assert";

Deno.bench(
  "My test description",
  { permissions: { read: true } },
  () => {
   assertEquals("hello", "hello");
  }
);

Deno.bench(
  "My async test description",
  { permissions: { read: false } },
  async () => {
    const decoder = new TextDecoder("utf-8");
    const data = await Deno.readFile("hello_world.txt");
    assertEquals(decoder.decode(data), "Hello world");
  }
);

Parameters

name: string
options: Omit<BenchDefinition, "fn" | "name">
fn: (b: BenchContext) => void | Promise<void>

Return Type

void

Overload 5

bench(
options: Omit<BenchDefinition, "fn">,
fn: (b: BenchContext) => void | Promise<void>,
): void

Register a benchmark test which will be run when deno bench is used on the command line and the containing module looks like a bench module.

If the test function (fn) returns a promise or is async, the test runner will await resolution to consider the test complete.

import { assertEquals } from "jsr:@std/assert";

Deno.bench(
  { name: "My test description", permissions: { read: true } },
  () => {
    assertEquals("hello", "hello");
  }
);

Deno.bench(
  { name: "My async test description", permissions: { read: false } },
  async () => {
    const decoder = new TextDecoder("utf-8");
    const data = await Deno.readFile("hello_world.txt");
    assertEquals(decoder.decode(data), "Hello world");
  }
);

Parameters

options: Omit<BenchDefinition, "fn">
fn: (b: BenchContext) => void | Promise<void>

Return Type

void

Overload 6

bench(
options: Omit<BenchDefinition, "fn" | "name">,
fn: (b: BenchContext) => void | Promise<void>,
): void

Register a benchmark test which will be run when deno bench is used on the command line and the containing module looks like a bench module.

If the test function (fn) returns a promise or is async, the test runner will await resolution to consider the test complete.

import { assertEquals } from "jsr:@std/assert";

Deno.bench(
  { permissions: { read: true } },
  function myTestName() {
    assertEquals("hello", "hello");
  }
);

Deno.bench(
  { permissions: { read: false } },
  async function myOtherTestName() {
    const decoder = new TextDecoder("utf-8");
    const data = await Deno.readFile("hello_world.txt");
    assertEquals(decoder.decode(data), "Hello world");
  }
);

Parameters

options: Omit<BenchDefinition, "fn" | "name">
fn: (b: BenchContext) => void | Promise<void>

Return Type

void

interface Deno.BenchContext

Context that is passed to a benchmarked function. The instance is shared between iterations of the benchmark. Its methods can be used for example to override of the measured portion of the function.

Properties

name: string

The current benchmark name.

origin: string

The string URL of the current benchmark.

Methods

start(): void

Restarts the timer for the bench measurement. This should be called after doing setup work which should not be measured.

Warning: This method should not be used for benchmarks averaging less than 10μs per iteration. In such cases it will be disabled but the call will still have noticeable overhead, resulting in a warning.

Deno.bench("foo", async (t) => {
  const data = await Deno.readFile("data.txt");
  t.start();
  // some operation on `data`...
});
end(): void

End the timer early for the bench measurement. This should be called before doing teardown work which should not be measured.

Warning: This method should not be used for benchmarks averaging less than 10μs per iteration. In such cases it will be disabled but the call will still have noticeable overhead, resulting in a warning.

Deno.bench("foo", async (t) => {
  using file = await Deno.open("data.txt");
  t.start();
  // some operation on `file`...
  t.end();
});

interface Deno.BenchDefinition

The interface for defining a benchmark test using Deno.bench.

Properties

fn: (b: BenchContext) => void | Promise<void>

The test function which will be benchmarked.

name: string

The name of the test, which will be used in displaying the results.

ignore: boolean
optional

If truthy, the benchmark test will be ignored/skipped.

group: string
optional

Group name for the benchmark.

Grouped benchmarks produce a group time summary, where the difference in performance between each test of the group is compared.

baseline: boolean
optional

Benchmark should be used as the baseline for other benchmarks.

If there are multiple baselines in a group, the first one is used as the baseline.

only: boolean
optional

If at least one bench has only set to true, only run benches that have only set to true and fail the bench suite.

n: number
optional

Number of iterations to perform.

warmup: number
optional

Number of warmups to do before running the benchmark.

sanitizeExit: boolean = true
optional

Ensure the bench case does not prematurely cause the process to exit, for example via a call to Deno.exit.

permissions: PermissionOptions = "inherit"
optional

Specifies the permissions that should be used to run the bench.

Set this to "inherit" to keep the calling thread's permissions.

Set this to "none" to revoke all permissions.


interface Deno.DenoTest

Call Signatures

(t: TestDefinition): void

Register a test which will be run when deno test is used on the command line and the containing module looks like a test module.

fn can be async if required.

import { assertEquals } from "jsr:@std/assert";

Deno.test({
  name: "example test",
  fn() {
    assertEquals("world", "world");
  },
});

Deno.test({
  name: "example ignored test",
  ignore: Deno.build.os === "windows",
  fn() {
    // This test is ignored only on Windows machines
  },
});

Deno.test({
  name: "example async test",
  async fn() {
    const decoder = new TextDecoder("utf-8");
    const data = await Deno.readFile("hello_world.txt");
    assertEquals(decoder.decode(data), "Hello world");
  }
});
(
name: string,
fn: (t: TestContext) => void | Promise<void>,
): void

Register a test which will be run when deno test is used on the command line and the containing module looks like a test module.

fn can be async if required.

import { assertEquals } from "jsr:@std/assert";

Deno.test("My test description", () => {
  assertEquals("hello", "hello");
});

Deno.test("My async test description", async () => {
  const decoder = new TextDecoder("utf-8");
  const data = await Deno.readFile("hello_world.txt");
  assertEquals(decoder.decode(data), "Hello world");
});
(fn: (t: TestContext) => void | Promise<void>): void

Register a test which will be run when deno test is used on the command line and the containing module looks like a test module.

fn can be async if required. Declared function must have a name.

import { assertEquals } from "jsr:@std/assert";

Deno.test(function myTestName() {
  assertEquals("hello", "hello");
});

Deno.test(async function myOtherTestName() {
  const decoder = new TextDecoder("utf-8");
  const data = await Deno.readFile("hello_world.txt");
  assertEquals(decoder.decode(data), "Hello world");
});
(
name: string,
options: Omit<TestDefinition, "fn" | "name">,
fn: (t: TestContext) => void | Promise<void>,
): void

Register a test which will be run when deno test is used on the command line and the containing module looks like a test module.

fn can be async if required.

import { assert, fail, assertEquals } from "jsr:@std/assert";

Deno.test("My test description", { permissions: { read: true } }, (): void => {
  assertEquals("hello", "hello");
});

Deno.test("My async test description", { permissions: { read: false } }, async (): Promise<void> => {
  const decoder = new TextDecoder("utf-8");
  const data = await Deno.readFile("hello_world.txt");
  assertEquals(decoder.decode(data), "Hello world");
});
(
options: Omit<TestDefinition, "fn" | "name">,
fn: (t: TestContext) => void | Promise<void>,
): void

Register a test which will be run when deno test is used on the command line and the containing module looks like a test module.

fn can be async if required.

import { assertEquals } from "jsr:@std/assert";

Deno.test(
  {
    name: "My test description",
    permissions: { read: true },
  },
  () => {
    assertEquals("hello", "hello");
  },
);

Deno.test(
  {
    name: "My async test description",
    permissions: { read: false },
  },
  async () => {
    const decoder = new TextDecoder("utf-8");
    const data = await Deno.readFile("hello_world.txt");
    assertEquals(decoder.decode(data), "Hello world");
  },
);
(
options: Omit<TestDefinition, "fn">,
fn: (t: TestContext) => void | Promise<void>,
): void

Register a test which will be run when deno test is used on the command line and the containing module looks like a test module.

fn can be async if required. Declared function must have a name.

import { assertEquals } from "jsr:@std/assert";

Deno.test(
  { permissions: { read: true } },
  function myTestName() {
    assertEquals("hello", "hello");
  },
);

Deno.test(
  { permissions: { read: false } },
  async function myOtherTestName() {
    const decoder = new TextDecoder("utf-8");
    const data = await Deno.readFile("hello_world.txt");
    assertEquals(decoder.decode(data), "Hello world");
  },
);

Properties

each: TestEach

Register a parameterized group of tests, one per case in cases.

Returns a function that takes a name template and a test function. For each case the name template is interpolated and the test function is called with the case's value(s) followed by the TestContext.

Array cases are spread as positional arguments; object (or primitive) cases are passed as a single argument.

The name template supports printf-style tokens that consume the case's values in order (%s, %d/%i, %f, %j, %o/%O), %# for the zero-based case index, and %% for a literal %. For object cases, $key (and $key.nested) interpolates the corresponding property.

import { assertEquals } from "jsr:@std/assert";

Deno.test.each([
  [1, 1, 2],
  [1, 2, 3],
  [2, 1, 3],
])("add(%i, %i) = %i", (a, b, expected) => {
  assertEquals(a + b, expected);
});

Deno.test.each([
  { a: 1, b: 1, sum: 2 },
  { a: 1, b: 2, sum: 3 },
])("$a + $b = $sum", ({ a, b, sum }) => {
  assertEquals(a + b, sum);
});
ignore: TestIgnore

Shorthand property for ignoring a particular test case.

only: TestOnly

Shorthand property for focusing a particular test case.

Methods

beforeAll(fn: () => void | Promise<void>): void

Register a function to be called before all tests in the current scope.

These functions are run in FIFO order (first in, first out).

If an exception is raised during execution of this hook, the remaining beforeAll hooks will not be run.

Deno.test.beforeAll(() => {
  // Setup code that runs once before all tests
  console.log("Setting up test suite");
});
beforeEach(fn: () => void | Promise<void>): void

Register a function to be called before each test in the current scope.

These functions are run in FIFO order (first in, first out).

If an exception is raised during execution of this hook, the remaining hooks will not be run and the currently running test case will be marked as failed.

Deno.test.beforeEach(() => {
  // Setup code that runs before each test
  console.log("Setting up test");
});
afterEach(fn: () => void | Promise<void>): void

Register a function to be called after each test in the current scope.

These functions are run in LIFO order (last in, first out).

If an exception is raised during execution of this hook, the remaining hooks will not be run and the currently running test case will be marked as failed.

Deno.test.afterEach(() => {
  // Cleanup code that runs after each test
  console.log("Cleaning up test");
});
afterAll(fn: () => void | Promise<void>): void

Register a function to be called after all tests in the current scope have finished running.

These functions are run in the LIFO order (last in, first out).

If an exception is raised during execution of this hook, the remaining afterAll hooks will not be run.

Deno.test.afterAll(() => {
  // Cleanup code that runs once after all tests
  console.log("Cleaning up test suite");
});
sanitizer(options: { ops?: boolean; resources?: boolean; }): void

Configure sanitizers at the module level. This overrides CLI flags and config file settings, but can still be overridden per-test via sanitizeOps / sanitizeResources in test options.

Should be called at the top of the module, before any Deno.test() registrations — each call sets the defaults that subsequently registered tests inherit, so tests registered before the call use the previous defaults.

// Enable both sanitizers for all tests in this file
Deno.test.sanitizer({ ops: true, resources: true });

Deno.test("my test", () => {
  // This test will have ops and resources sanitizers enabled
});

Deno.test({
  name: "override per-test",
  sanitizeOps: false,
  fn() {
    // This test opts out of ops sanitizer
  },
});

interface Deno.TestContext

Context that is passed to a testing function, which can be used to either gain information about the current test, or register additional test steps within the current test.

Properties

name: string

The current test name.

origin: string

The string URL of the current test.

parent: TestContext
optional

If the current test is a step of another test, the parent test context will be set here.

Methods

step(definition: TestStepDefinition): Promise<boolean>

Run a sub step of the parent test or step. Returns a promise that resolves to a boolean signifying if the step completed successfully.

The returned promise never rejects unless the arguments are invalid.

If the test was ignored the promise returns false.

Deno.test({
  name: "a parent test",
  async fn(t) {
    console.log("before the step");
    await t.step({
      name: "step 1",
      fn(t) {
        console.log("current step:", t.name);
      }
    });
    console.log("after the step");
  }
});
step(
name: string,
fn: (t: TestContext) => void | Promise<void>,
): Promise<boolean>

Run a sub step of the parent test or step. Returns a promise that resolves to a boolean signifying if the step completed successfully.

The returned promise never rejects unless the arguments are invalid.

If the test was ignored the promise returns false.

Deno.test(
  "a parent test",
  async (t) => {
    console.log("before the step");
    await t.step(
      "step 1",
      (t) => {
        console.log("current step:", t.name);
      }
    );
    console.log("after the step");
  }
);
step(fn: (t: TestContext) => void | Promise<void>): Promise<boolean>

Run a sub step of the parent test or step. Returns a promise that resolves to a boolean signifying if the step completed successfully.

The returned promise never rejects unless the arguments are invalid.

If the test was ignored the promise returns false.

Deno.test(async function aParentTest(t) {
  console.log("before the step");
  await t.step(function step1(t) {
    console.log("current step:", t.name);
  });
  console.log("after the step");
});
assertSnapshot<T>(
actual: T,
options?: TestSnapshotOptions<T>,
): Promise<void>

Assert that actual matches a snapshot stored in a snapshot file.

The snapshot is stored in __snapshots__/<test file name>.snap next to the test file, under a key derived from the test (and step) name. On the first run, create the snapshot file by running the tests with the --update-snapshots flag; commit it alongside the test. On subsequent runs the assertion fails if the serialized value no longer matches the stored snapshot. To intentionally change snapshots, run the tests with --update-snapshots again.

No read or write permissions are needed for snapshot files in the default location; a custom dir or path requires them.

The snapshot file format is compatible with assertSnapshot from @std/testing/snapshot.

Deno.test("matches snapshot", async (t) => {
  await t.assertSnapshot({ hello: "world", example: 123 });
});
assertSnapshot<T>(
actual: T,
message?: string,
): Promise<void>

Assert that actual matches a snapshot stored in a snapshot file, using message as the failure message if it does not.

Deno.test("matches snapshot", async (t) => {
  await t.assertSnapshot(2 + 3, "should be five");
});

interface Deno.TestDefinition

Properties

fn: (t: TestContext) => void | Promise<void>
name: string

The name of the test.

ignore: boolean
optional

If truthy the current test step will be ignored.

It is a quick way to skip over a step, but also can be used for conditional logic, like determining if an environment feature is present.

only: boolean
optional

If at least one test has only set to true, only run tests that have only set to true and fail the test suite.

sanitizeOps: boolean = false
optional

Check that the number of async completed operations after the test step is the same as number of dispatched operations. This ensures that the code tested does not start async operations which it then does not await. This helps in preventing logic errors and memory leaks in the application code.

Can also be enabled globally with the --sanitize-ops CLI flag, the DENO_TEST_SANITIZE_OPS=1 environment variable, or the test.sanitizeOps option in deno.json. Can be set per-module with Deno.test.sanitizer.

sanitizeResources: boolean = false
optional

Ensure the test step does not "leak" resources - like open files or network connections - by ensuring the open resources at the start of the test match the open resources at the end of the test.

Can also be enabled globally with the --sanitize-resources CLI flag, the DENO_TEST_SANITIZE_RESOURCES=1 environment variable, or the test.sanitizeResources option in deno.json. Can be set per-module with Deno.test.sanitizer.

sanitizeExit: boolean = true
optional

Ensure the test case does not prematurely cause the process to exit, for example via a call to Deno.exit.

permissions: PermissionOptions = "inherit"
optional

Specifies the permissions that should be used to run the test.

Set this to "inherit" to keep the calling runtime permissions, set this to "none" to revoke all permissions, or set a more specific set of permissions using a PermissionOptionsObject.

timeout: number
optional

Maximum duration in milliseconds that the test is allowed to run before being marked as a failed test. Both asynchronous hangs and synchronous hot loops are caught.

If unset or 0, the test runs without a deadline.

retry: number = 0
optional

Number of times to re-run the test if it fails. The test is considered to have passed if any attempt passes. Useful for tolerating flaky tests.

When set, this takes precedence over the --retry flag, including an explicit 0 which opts the test out of a flag-provided default.

repeats: number = 0
optional

Number of additional times to run the test. Every repetition must pass for the test to pass. Useful for surfacing flaky tests. When combined with TestDefinition.retry, each repetition may itself be retried.

When set, this takes precedence over the --repeats flag, including an explicit 0 which opts the test out of a flag-provided default.


interface Deno.TestEach

Register a parameterized group of tests. See DenoTest.each.

The first overload handles array cases (their values are spread as positional arguments); the second handles object or primitive cases (each passed as a single argument followed by the TestContext).

The TestContext is also passed as the final argument to array case functions at runtime, but is not reflected in their parameter types so that the case values stay correctly typed.

Call Signatures

<T extends readonly unknown[]>(cases: readonly T[]): { (
name: string,
fn: (...args: [...T]) => void | Promise<void>,
): void; (
name: string,
options: Omit<TestDefinition, "fn" | "name">,
fn: (...args: [...T]) => void | Promise<void>,
): void; }
<T>(cases: readonly T[]): { (
name: string,
fn: (
value: T,
t: TestContext,
) => void | Promise<void>
,
): void; (
name: string,
options: Omit<TestDefinition, "fn" | "name">,
fn: (
value: T,
t: TestContext,
) => void | Promise<void>
,
): void; }

interface Deno.TestIgnore

Shorthand property for ignoring a particular test case. See DenoTest.ignore.

Call Signatures

(t: Omit<TestDefinition, "ignore">): void
(
name: string,
fn: (t: TestContext) => void | Promise<void>,
): void
(fn: (t: TestContext) => void | Promise<void>): void
(
name: string,
options: Omit<TestDefinition,
"fn"
| "name"
| "ignore"
>
,
fn: (t: TestContext) => void | Promise<void>,
): void
(
options: Omit<TestDefinition,
"fn"
| "name"
| "ignore"
>
,
fn: (t: TestContext) => void | Promise<void>,
): void
(
options: Omit<TestDefinition, "fn" | "ignore">,
fn: (t: TestContext) => void | Promise<void>,
): void

Properties

each: TestEach

Register a parameterized group of ignored tests. See DenoTest.each.


interface Deno.TestOnly

Shorthand property for focusing a particular test case. See DenoTest.only.

Call Signatures

(t: Omit<TestDefinition, "only">): void
(
name: string,
fn: (t: TestContext) => void | Promise<void>,
): void
(fn: (t: TestContext) => void | Promise<void>): void
(
name: string,
options: Omit<TestDefinition,
"fn"
| "name"
| "only"
>
,
fn: (t: TestContext) => void | Promise<void>,
): void
(
options: Omit<TestDefinition,
"fn"
| "name"
| "only"
>
,
fn: (t: TestContext) => void | Promise<void>,
): void
(
options: Omit<TestDefinition, "fn" | "only">,
fn: (t: TestContext) => void | Promise<void>,
): void

Properties

each: TestEach

Register a parameterized group of focused tests. See DenoTest.each.


interface Deno.TestSnapshotOptions

Options which can be set when calling Deno.TestContext.assertSnapshot.

Type Parameters

T = unknown

Properties

dir: string
optional

Snapshot output directory, relative to the directory of the test file (or absolute). Snapshot files are written to this directory instead of the default __snapshots__ directory. Requires read (and, with --update-snapshots, write) permission for the directory.

If both dir and path are specified, dir is ignored.

path: string
optional

Snapshot output path, relative to the directory of the test file (or absolute). The snapshot is stored in this file instead of the default __snapshots__/<test file name>.snap file. Requires read (and, with --update-snapshots, write) permission for the file.

If both dir and path are specified, dir is ignored.

name: string
optional

Name of the snapshot to use in the snapshot file instead of the name derived from the test and step names.

msg: string
optional

Failure message to use when the assertion fails, instead of the generated diff message.

serializer: (actual: T) => string
optional

Function used to serialize the value to a string before comparing it with the stored snapshot. Defaults to a Deno.inspect()-based serializer.


interface Deno.TestStepDefinition

Properties

fn: (t: TestContext) => void | Promise<void>

The test function that will be tested when this step is executed. The function can take an argument which will provide information about the current step's context.

name: string

The name of the step.

ignore: boolean
optional

If truthy the current test step will be ignored.

This is a quick way to skip over a step, but also can be used for conditional logic, like determining if an environment feature is present.

sanitizeOps: boolean
optional

Check that the number of async completed operations after the test step is the same as number of dispatched operations. This ensures that the code tested does not start async operations which it then does not await. This helps in preventing logic errors and memory leaks in the application code.

Defaults to the parent test or step's value.

sanitizeResources: boolean
optional

Ensure the test step does not "leak" resources - like open files or network connections - by ensuring the open resources at the start of the step match the open resources at the end of the step.

Defaults to the parent test or step's value.

sanitizeExit: boolean
optional

Ensure the test step does not prematurely cause the process to exit, for example via a call to Deno.exit.

Defaults to the parent test or step's value.


variable Deno.test

Register a test which will be run when deno test is used on the command line and the containing module looks like a test module.

fn can be async if required.

Tests are discovered before they are executed, so registrations must happen at module load time. Nested Deno.test() calls are not supported. Use t.step() for nested tests.

import { assertEquals } from "jsr:@std/assert";

Deno.test({
  name: "example test",
  fn() {
    assertEquals("world", "world");
  },
});

Deno.test({
  name: "example ignored test",
  ignore: Deno.build.os === "windows",
  fn() {
    // This test is ignored only on Windows machines
  },
});

Deno.test({
  name: "example async test",
  async fn() {
    const decoder = new TextDecoder("utf-8");
    const data = await Deno.readFile("hello_world.txt");
    assertEquals(decoder.decode(data), "Hello world");
  }
});

Type

DenoTest

© 2018–2025 the Deno authors
Licensed under the MIT License.
https://docs.deno.com/api/deno/testing

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API