summaryrefslogtreecommitdiff
path: root/std/testing
diff options
context:
space:
mode:
Diffstat (limited to 'std/testing')
-rw-r--r--std/testing/asserts_test.ts2
-rw-r--r--std/testing/bench_test.ts4
-rw-r--r--std/testing/diff_test.ts2
-rw-r--r--std/testing/format_test.ts2
-rw-r--r--std/testing/mod.ts450
-rwxr-xr-xstd/testing/runner.ts7
-rw-r--r--std/testing/runner_test.ts3
-rw-r--r--std/testing/test.ts293
-rw-r--r--std/testing/testing_bench.ts18
9 files changed, 7 insertions, 774 deletions
diff --git a/std/testing/asserts_test.ts b/std/testing/asserts_test.ts
index ede5abbde..3a846417a 100644
--- a/std/testing/asserts_test.ts
+++ b/std/testing/asserts_test.ts
@@ -14,8 +14,8 @@ import {
unimplemented,
unreachable
} from "./asserts.ts";
-import { test } from "./mod.ts";
import { red, green, white, gray, bold } from "../fmt/colors.ts";
+const { test } = Deno;
test(function testingEqual(): void {
assert(equal("world", "world"));
diff --git a/std/testing/bench_test.ts b/std/testing/bench_test.ts
index 8af2f0d6d..b384b21f7 100644
--- a/std/testing/bench_test.ts
+++ b/std/testing/bench_test.ts
@@ -1,4 +1,4 @@
-import { test, runIfMain } from "./mod.ts";
+const { test } = Deno;
import { bench, runBenchmarks } from "./bench.ts";
import "./bench_example.ts";
@@ -56,5 +56,3 @@ test(async function benching(): Promise<void> {
await runBenchmarks({ skip: /throw/ });
});
-
-runIfMain(import.meta);
diff --git a/std/testing/diff_test.ts b/std/testing/diff_test.ts
index d9fbdb956..0e8416274 100644
--- a/std/testing/diff_test.ts
+++ b/std/testing/diff_test.ts
@@ -1,6 +1,6 @@
import diff from "./diff.ts";
import { assertEquals } from "../testing/asserts.ts";
-import { test } from "./mod.ts";
+const { test } = Deno;
test({
name: "empty",
diff --git a/std/testing/format_test.ts b/std/testing/format_test.ts
index e2bb8df23..14f84f3c2 100644
--- a/std/testing/format_test.ts
+++ b/std/testing/format_test.ts
@@ -6,7 +6,7 @@
* LICENSE file in the root directory of this source tree.
*
*/
-import { test } from "./mod.ts";
+const { test } = Deno;
import { assertEquals } from "../testing/asserts.ts";
import { format } from "./format.ts";
diff --git a/std/testing/mod.ts b/std/testing/mod.ts
deleted file mode 100644
index a60e9c93f..000000000
--- a/std/testing/mod.ts
+++ /dev/null
@@ -1,450 +0,0 @@
-// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-
-export * from "./asserts.ts";
-export * from "./bench.ts";
-import diff from "./diff.ts";
-export { diff };
-export * from "./format.ts";
-export * from "./runner.ts";
-
-import {
- bgRed,
- white,
- bold,
- green,
- red,
- gray,
- yellow,
- italic
-} from "../fmt/colors.ts";
-import { assert } from "./asserts.ts";
-export type TestFunction = () => void | Promise<void>;
-
-export interface TestDefinition {
- fn: TestFunction;
- name: string;
-}
-
-// Replacement of the global `console` function to be in silent mode
-const noop = function(): void {};
-
-// Clear the current line of the console.
-// see: http://ascii-table.com/ansi-escape-sequences-vt-100.php
-const CLEAR_LINE = "\x1b[2K\r";
-
-// Save Object of the global `console` in case of silent mode
-type Console = typeof window.console;
-// ref https://console.spec.whatwg.org/#console-namespace
-// For historical web-compatibility reasons, the namespace object for
-// console must have as its [[Prototype]] an empty object, created as if
-// by ObjectCreate(%ObjectPrototype%), instead of %ObjectPrototype%.
-const disabledConsole = Object.create({}) as Console;
-Object.assign(disabledConsole, {
- log: noop,
- debug: noop,
- info: noop,
- dir: noop,
- warn: noop,
- error: noop,
- assert: noop,
- count: noop,
- countReset: noop,
- table: noop,
- time: noop,
- timeLog: noop,
- timeEnd: noop,
- group: noop,
- groupCollapsed: noop,
- groupEnd: noop,
- clear: noop
-});
-
-const originalConsole = window.console;
-
-function enableConsole(): void {
- window.console = originalConsole;
-}
-
-function disableConsole(): void {
- window.console = disabledConsole;
-}
-
-const encoder = new TextEncoder();
-function print(txt: string, newline = true): void {
- if (newline) {
- txt += "\n";
- }
- Deno.stdout.writeSync(encoder.encode(`${txt}`));
-}
-
-declare global {
- interface Window {
- /**
- * A global property to collect all registered test cases.
- *
- * It is required because user's code can import multiple versions
- * of `testing` module.
- *
- * If test cases aren't registered in a globally shared
- * object, then imports from different versions would register test cases
- * to registry from it's respective version of `testing` module.
- */
- __DENO_TEST_REGISTRY: TestDefinition[];
- }
-}
-
-let candidates: TestDefinition[] = [];
-if (window["__DENO_TEST_REGISTRY"]) {
- candidates = window.__DENO_TEST_REGISTRY as TestDefinition[];
-} else {
- window["__DENO_TEST_REGISTRY"] = candidates;
-}
-let filterRegExp: RegExp | null;
-let filtered = 0;
-
-// Must be called before any test() that needs to be filtered.
-export function setFilter(s: string): void {
- filterRegExp = new RegExp(s, "i");
-}
-
-function filter(name: string): boolean {
- if (filterRegExp) {
- return filterRegExp.test(name);
- } else {
- return true;
- }
-}
-
-export function test(t: TestDefinition): void;
-export function test(fn: TestFunction): void;
-export function test(name: string, fn: TestFunction): void;
-export function test(
- t: string | TestDefinition | TestFunction,
- fn?: TestFunction
-): void {
- let name: string;
-
- if (typeof t === "string") {
- if (!fn) {
- throw new Error("Missing test function");
- }
- name = t;
- if (!name) {
- throw new Error("The name of test case can't be empty");
- }
- } else if (typeof t === "function") {
- fn = t;
- name = t.name;
- if (!name) {
- throw new Error("Test function can't be anonymous");
- }
- } else {
- fn = t.fn;
- if (!fn) {
- throw new Error("Missing test function");
- }
- name = t.name;
- if (!name) {
- throw new Error("The name of test case can't be empty");
- }
- }
- assert(!!name, "The name of test case shouldn't be empty");
- assert(!!fn, "Test function shouldn't be empty");
-
- if (filter(name)) {
- candidates.push({ fn, name });
- } else {
- filtered++;
- }
-}
-
-const RED_FAILED = red("FAILED");
-const GREEN_OK = green("OK");
-const RED_BG_FAIL = bgRed(" FAIL ");
-
-interface TestStats {
- filtered: number;
- ignored: number;
- measured: number;
- passed: number;
- failed: number;
-}
-
-interface TestResult {
- timeElapsed?: number;
- name: string;
- error?: Error;
- ok: boolean;
- printed: boolean;
-}
-
-interface TestResults {
- keys: Map<string, number>;
- cases: Map<number, TestResult>;
-}
-
-function createTestResults(tests: TestDefinition[]): TestResults {
- return tests.reduce(
- (acc: TestResults, { name }: TestDefinition, i: number): TestResults => {
- acc.keys.set(name, i);
- acc.cases.set(i, { name, printed: false, ok: false, error: undefined });
- return acc;
- },
- { cases: new Map(), keys: new Map() }
- );
-}
-
-function formatTestTime(time = 0): string {
- return `${time.toFixed(2)}ms`;
-}
-
-function promptTestTime(time = 0, displayWarning = false): string {
- // if time > 5s we display a warning
- // only for test time, not the full runtime
- if (displayWarning && time >= 5000) {
- return bgRed(white(bold(`(${formatTestTime(time)})`)));
- } else {
- return gray(italic(`(${formatTestTime(time)})`));
- }
-}
-
-function report(result: TestResult): void {
- if (result.ok) {
- print(
- `${GREEN_OK} ${result.name} ${promptTestTime(
- result.timeElapsed,
- true
- )}`
- );
- } else if (result.error) {
- print(`${RED_FAILED} ${result.name}\n${result.error.stack}`);
- } else {
- print(`test ${result.name} ... unresolved`);
- }
- result.printed = true;
-}
-
-function printFailedSummary(results: TestResults): void {
- results.cases.forEach((v): void => {
- if (!v.ok) {
- console.error(`${RED_BG_FAIL} ${red(v.name)}`);
- console.error(v.error);
- }
- });
-}
-
-function printResults(
- stats: TestStats,
- results: TestResults,
- flush: boolean,
- exitOnFail: boolean,
- timeElapsed: number
-): void {
- if (flush) {
- for (const result of results.cases.values()) {
- if (!result.printed) {
- report(result);
- if (result.error && exitOnFail) {
- break;
- }
- }
- }
- }
- // Attempting to match the output of Rust's test runner.
- print(
- `\ntest result: ${stats.failed ? RED_BG_FAIL : GREEN_OK} ` +
- `${stats.passed} passed; ${stats.failed} failed; ` +
- `${stats.ignored} ignored; ${stats.measured} measured; ` +
- `${stats.filtered} filtered out ` +
- `${promptTestTime(timeElapsed)}\n`
- );
-}
-
-function previousPrinted(name: string, results: TestResults): boolean {
- const curIndex = results.keys.get(name);
- assert(curIndex != null);
- if (curIndex === 0) {
- return true;
- }
- const prev = results.cases.get(curIndex - 1);
- assert(prev != null);
- return prev.printed;
-}
-
-async function createTestCase(
- stats: TestStats,
- results: TestResults,
- exitOnFail: boolean,
- { fn, name }: TestDefinition
-): Promise<void> {
- const i = results.keys.get(name);
- assert(i != null);
- const result = results.cases.get(i);
- assert(result != null);
- try {
- const start = performance.now();
- await fn();
- const end = performance.now();
- stats.passed++;
- result.ok = true;
- result.timeElapsed = end - start;
- } catch (err) {
- stats.failed++;
- result.error = err;
- if (exitOnFail) {
- throw err;
- }
- }
- if (previousPrinted(name, results)) {
- report(result);
- }
-}
-
-function initTestCases(
- stats: TestStats,
- results: TestResults,
- tests: TestDefinition[],
- exitOnFail: boolean
-): Array<Promise<void>> {
- return tests.map(createTestCase.bind(null, stats, results, exitOnFail));
-}
-
-async function runTestsParallel(
- stats: TestStats,
- results: TestResults,
- tests: TestDefinition[],
- exitOnFail: boolean
-): Promise<void> {
- try {
- await Promise.all(initTestCases(stats, results, tests, exitOnFail));
- } catch (_) {
- // The error was thrown to stop awaiting all promises if exitOnFail === true
- // stats.failed has been incremented and the error stored in results
- }
-}
-
-async function runTestsSerial(
- stats: TestStats,
- results: TestResults,
- tests: TestDefinition[],
- exitOnFail: boolean,
- disableLog: boolean
-): Promise<void> {
- for (const { fn, name } of tests) {
- // Displaying the currently running test if silent mode
- if (disableLog) {
- print(`${yellow("RUNNING")} ${name}`, false);
- }
- try {
- const start = performance.now();
- await fn();
- const end = performance.now();
- if (disableLog) {
- // Rewriting the current prompt line to erase `running ....`
- print(CLEAR_LINE, false);
- }
- stats.passed++;
- print(
- GREEN_OK + " " + name + " " + promptTestTime(end - start, true)
- );
- results.cases.forEach((v): void => {
- if (v.name === name) {
- v.ok = true;
- v.printed = true;
- }
- });
- } catch (err) {
- if (disableLog) {
- print(CLEAR_LINE, false);
- }
- print(`${RED_FAILED} ${name}`);
- print(err.stack);
- stats.failed++;
- results.cases.forEach((v): void => {
- if (v.name === name) {
- v.error = err;
- v.ok = false;
- v.printed = true;
- }
- });
- if (exitOnFail) {
- break;
- }
- }
- }
-}
-
-/** Defines options for controlling execution details of a test suite. */
-export interface RunTestsOptions {
- parallel?: boolean;
- exitOnFail?: boolean;
- only?: RegExp;
- skip?: RegExp;
- disableLog?: boolean;
-}
-
-/**
- * Runs specified test cases.
- * Parallel execution can be enabled via the boolean option; default: serial.
- */
-// TODO: change return type to `Promise<boolean>` - ie. don't
-// exit but return value
-export async function runTests({
- parallel = false,
- exitOnFail = false,
- only = /[^\s]/,
- skip = /^\s*$/,
- disableLog = false
-}: RunTestsOptions = {}): Promise<void> {
- const tests: TestDefinition[] = candidates.filter(
- ({ name }): boolean => only.test(name) && !skip.test(name)
- );
- const stats: TestStats = {
- measured: 0,
- ignored: candidates.length - tests.length,
- filtered: filtered,
- passed: 0,
- failed: 0
- };
- const results: TestResults = createTestResults(tests);
- print(`running ${tests.length} tests`);
- const start = performance.now();
- if (Deno.args.includes("--quiet")) {
- disableLog = true;
- }
- if (disableLog) {
- disableConsole();
- }
- if (parallel) {
- await runTestsParallel(stats, results, tests, exitOnFail);
- } else {
- await runTestsSerial(stats, results, tests, exitOnFail, disableLog);
- }
- const end = performance.now();
- if (disableLog) {
- enableConsole();
- }
- printResults(stats, results, parallel, exitOnFail, end - start);
- if (stats.failed) {
- // Use setTimeout to avoid the error being ignored due to unhandled
- // promise rejections being swallowed.
- setTimeout((): void => {
- console.error(`There were ${stats.failed} test failures.`);
- printFailedSummary(results);
- Deno.exit(1);
- }, 0);
- }
-}
-
-/**
- * Runs specified test cases if the enclosing script is main.
- * Execution mode is toggleable via opts.parallel, defaults to false.
- */
-export async function runIfMain(
- meta: ImportMeta,
- opts?: RunTestsOptions
-): Promise<void> {
- if (meta.main) {
- return runTests(opts);
- }
-}
diff --git a/std/testing/runner.ts b/std/testing/runner.ts
index 17d5942f8..8d6501e02 100755
--- a/std/testing/runner.ts
+++ b/std/testing/runner.ts
@@ -3,7 +3,6 @@
import { parse } from "../flags/mod.ts";
import { ExpandGlobOptions, expandGlob } from "../fs/mod.ts";
import { isWindows, join } from "../path/mod.ts";
-import { RunTestsOptions, runTests } from "./mod.ts";
const { DenoError, ErrorKind, args, cwd, exit } = Deno;
const DIR_GLOBS = [join("**", "?(*_)test.{js,ts}")];
@@ -110,7 +109,7 @@ export async function* findTestModules(
yield* includeUrls.filter(shouldIncludeUrl);
}
-export interface RunTestModulesOptions extends RunTestsOptions {
+export interface RunTestModulesOptions extends Deno.RunTestsOptions {
include?: string[];
exclude?: string[];
allowNone?: boolean;
@@ -168,7 +167,6 @@ export async function runTestModules({
include = ["."],
exclude = [],
allowNone = false,
- parallel = false,
exitOnFail = false,
only = /[^\s]/,
skip = /^\s*$/,
@@ -233,8 +231,7 @@ export async function runTestModules({
console.log(`Found ${moduleCount} matching test modules.`);
}
- await runTests({
- parallel,
+ await Deno.runTests({
exitOnFail,
only,
skip,
diff --git a/std/testing/runner_test.ts b/std/testing/runner_test.ts
index 95f2b49cc..f39e5d326 100644
--- a/std/testing/runner_test.ts
+++ b/std/testing/runner_test.ts
@@ -1,9 +1,8 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { assertEquals } from "../testing/asserts.ts";
import { isWindows } from "../path/mod.ts";
-import { test } from "./mod.ts";
import { findTestModules } from "./runner.ts";
-const { cwd } = Deno;
+const { cwd, test } = Deno;
function urlToFilePath(url: URL): string {
// Since `new URL('file:///C:/a').pathname` is `/C:/a`, remove leading slash.
diff --git a/std/testing/test.ts b/std/testing/test.ts
deleted file mode 100644
index 5379a5199..000000000
--- a/std/testing/test.ts
+++ /dev/null
@@ -1,293 +0,0 @@
-// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-import { test, runIfMain } from "./mod.ts";
-import {
- assert,
- assertEquals,
- assertStrictEq,
- assertThrows,
- assertThrowsAsync
-} from "./asserts.ts";
-
-test(function testingAssertEqualActualUncoercable(): void {
- let didThrow = false;
- const a = Object.create(null);
- try {
- assertEquals(a, "bar");
- } catch (e) {
- didThrow = true;
- }
- assert(didThrow);
-});
-
-test(function testingAssertEqualExpectedUncoercable(): void {
- let didThrow = false;
- const a = Object.create(null);
- try {
- assertStrictEq("bar", a);
- } catch (e) {
- didThrow = true;
- }
- assert(didThrow);
-});
-
-test(function testingAssertStrictEqual(): void {
- const a = {};
- const b = a;
- assertStrictEq(a, b);
-});
-
-test(function testingAssertNotStrictEqual(): void {
- let didThrow = false;
- const a = {};
- const b = {};
- try {
- assertStrictEq(a, b);
- } catch (e) {
- assert(e.message === "actual: [object Object] expected: [object Object]");
- didThrow = true;
- }
- assert(didThrow);
-});
-
-test(function testingDoesThrow(): void {
- let count = 0;
- assertThrows((): void => {
- count++;
- throw new Error();
- });
- assert(count === 1);
-});
-
-test(function testingDoesNotThrow(): void {
- let count = 0;
- let didThrow = false;
- try {
- assertThrows((): void => {
- count++;
- console.log("Hello world");
- });
- } catch (e) {
- assert(e.message === "Expected function to throw.");
- didThrow = true;
- }
- assert(count === 1);
- assert(didThrow);
-});
-
-test(function testingThrowsErrorType(): void {
- let count = 0;
- assertThrows((): void => {
- count++;
- throw new TypeError();
- }, TypeError);
- assert(count === 1);
-});
-
-test(function testingThrowsNotErrorType(): void {
- let count = 0;
- let didThrow = false;
- try {
- assertThrows((): void => {
- count++;
- throw new TypeError();
- }, RangeError);
- } catch (e) {
- assert(e.message === `Expected error to be instance of "RangeError".`);
- didThrow = true;
- }
- assert(count === 1);
- assert(didThrow);
-});
-
-test(function testingThrowsMsgIncludes(): void {
- let count = 0;
- assertThrows(
- (): void => {
- count++;
- throw new TypeError("Hello world!");
- },
- TypeError,
- "world"
- );
- assert(count === 1);
-});
-
-test(function testingThrowsMsgNotIncludes(): void {
- let count = 0;
- let didThrow = false;
- try {
- assertThrows(
- (): void => {
- count++;
- throw new TypeError("Hello world!");
- },
- TypeError,
- "foobar"
- );
- } catch (e) {
- assert(
- e.message ===
- `Expected error message to include "foobar", but got "Hello world!".`
- );
- didThrow = true;
- }
- assert(count === 1);
- assert(didThrow);
-});
-
-test(async function testingDoesThrowAsync(): Promise<void> {
- let count = 0;
- await assertThrowsAsync(
- async (): Promise<void> => {
- count++;
- throw new Error();
- }
- );
- assert(count === 1);
-});
-
-test(async function testingDoesReject(): Promise<void> {
- let count = 0;
- await assertThrowsAsync(
- (): Promise<never> => {
- count++;
- return Promise.reject(new Error());
- }
- );
- assert(count === 1);
-});
-
-test(async function testingDoesNotThrowAsync(): Promise<void> {
- let count = 0;
- let didThrow = false;
- try {
- await assertThrowsAsync(
- async (): Promise<void> => {
- count++;
- console.log("Hello world");
- }
- );
- } catch (e) {
- assert(e.message === "Expected function to throw.");
- didThrow = true;
- }
- assert(count === 1);
- assert(didThrow);
-});
-
-test(async function testingDoesNotRejectAsync(): Promise<void> {
- let count = 0;
- let didThrow = false;
- try {
- await assertThrowsAsync(
- (): Promise<void> => {
- count++;
- console.log("Hello world");
- return Promise.resolve();
- }
- );
- } catch (e) {
- assert(e.message === "Expected function to throw.");
- didThrow = true;
- }
- assert(count === 1);
- assert(didThrow);
-});
-
-test(async function testingThrowsAsyncErrorType(): Promise<void> {
- let count = 0;
- await assertThrowsAsync((): Promise<void> => {
- count++;
- throw new TypeError();
- }, TypeError);
- assert(count === 1);
-});
-
-test(async function testingThrowsAsyncNotErrorType(): Promise<void> {
- let count = 0;
- let didThrow = false;
- try {
- await assertThrowsAsync(async (): Promise<void> => {
- count++;
- throw new TypeError();
- }, RangeError);
- } catch (e) {
- assert(e.message === `Expected error to be instance of "RangeError".`);
- didThrow = true;
- }
- assert(count === 1);
- assert(didThrow);
-});
-
-test(async function testingThrowsAsyncMsgIncludes(): Promise<void> {
- let count = 0;
- await assertThrowsAsync(
- async (): Promise<void> => {
- count++;
- throw new TypeError("Hello world!");
- },
- TypeError,
- "world"
- );
- assert(count === 1);
-});
-
-test(async function testingThrowsAsyncMsgNotIncludes(): Promise<void> {
- let count = 0;
- let didThrow = false;
- try {
- await assertThrowsAsync(
- async (): Promise<void> => {
- count++;
- throw new TypeError("Hello world!");
- },
- TypeError,
- "foobar"
- );
- } catch (e) {
- assert(
- e.message ===
- `Expected error message to include "foobar", but got "Hello world!".`
- );
- didThrow = true;
- }
- assert(count === 1);
- assert(didThrow);
-});
-
-test("test fn overloading", (): void => {
- // just verifying that you can use this test definition syntax
- assert(true);
-});
-
-test("The name of test case can't be empty", () => {
- assertThrows(
- () => {
- test("", () => {});
- },
- Error,
- "The name of test case can't be empty"
- );
- assertThrows(
- () => {
- test({
- name: "",
- fn: () => {}
- });
- },
- Error,
- "The name of test case can't be empty"
- );
-});
-
-test("test function can't be anonymous", () => {
- assertThrows(
- () => {
- test(function() {});
- },
- Error,
- "Test function can't be anonymous"
- );
-});
-
-runIfMain(import.meta);
diff --git a/std/testing/testing_bench.ts b/std/testing/testing_bench.ts
deleted file mode 100644
index 9033e3a72..000000000
--- a/std/testing/testing_bench.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { bench, runIfMain } from "./bench.ts";
-import { runTests } from "./mod.ts";
-
-import "./asserts_test.ts";
-
-bench(async function testingSerial(b): Promise<void> {
- b.start();
- await runTests();
- b.stop();
-});
-
-bench(async function testingParallel(b): Promise<void> {
- b.start();
- await runTests({ parallel: true });
- b.stop();
-});
-
-runIfMain(import.meta);