summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/js/lib.deno.ns.d.ts3
-rw-r--r--cli/js/testing.ts35
-rw-r--r--cli/tests/deno_test_only.ts15
-rw-r--r--cli/tests/deno_test_only.ts.out7
-rw-r--r--cli/tests/integration_tests.rs12
-rw-r--r--cli/tests/unit/test_util.ts9
-rwxr-xr-xcli/tests/unit/unit_test_runner.ts9
7 files changed, 75 insertions, 15 deletions
diff --git a/cli/js/lib.deno.ns.d.ts b/cli/js/lib.deno.ns.d.ts
index c70eca68e..f9438ed9c 100644
--- a/cli/js/lib.deno.ns.d.ts
+++ b/cli/js/lib.deno.ns.d.ts
@@ -38,6 +38,9 @@ declare namespace Deno {
fn: () => void | Promise<void>;
name: string;
ignore?: boolean;
+ /** If at lease one test has `only` set to true, only run tests that have
+ * `only` set to true and fail the test suite. */
+ only?: boolean;
/** Check that the number of async completed ops after the test is the same
* as number of dispatched ops. Defaults to true.*/
sanitizeOps?: boolean;
diff --git a/cli/js/testing.ts b/cli/js/testing.ts
index ffe978888..a6010ed53 100644
--- a/cli/js/testing.ts
+++ b/cli/js/testing.ts
@@ -52,8 +52,8 @@ Before:
After:
- dispatched: ${post.opsDispatchedAsync}
- completed: ${post.opsCompletedAsync}
-
-Make sure to await all promises returned from Deno APIs before
+
+Make sure to await all promises returned from Deno APIs before
finishing test case.`
);
};
@@ -76,7 +76,7 @@ function assertResources(
Before: ${preStr}
After: ${postStr}
-Make sure to close all open resource handles returned from Deno APIs before
+Make sure to close all open resource handles returned from Deno APIs before
finishing test case.`;
assert(preStr === postStr, msg);
};
@@ -86,6 +86,7 @@ export interface TestDefinition {
fn: () => void | Promise<void>;
name: string;
ignore?: boolean;
+ only?: boolean;
sanitizeOps?: boolean;
sanitizeResources?: boolean;
}
@@ -103,6 +104,7 @@ export function test(
let testDef: TestDefinition;
const defaults = {
ignore: false,
+ only: false,
sanitizeOps: true,
sanitizeResources: true,
};
@@ -156,6 +158,7 @@ interface TestMessage {
measured: number;
passed: number;
failed: number;
+ usedOnly: boolean;
duration: number;
results: Array<TestMessage["testEnd"] & {}>;
};
@@ -218,6 +221,10 @@ function reportToConsole(message: TestMessage): void {
`${message.end.filtered} filtered out ` +
`${formatDuration(message.end.duration)}\n`
);
+
+ if (message.end.usedOnly && message.end.failed == 0) {
+ log(`${RED_FAILED} because the "only" option was used\n`);
+ }
}
}
@@ -225,7 +232,7 @@ exposeForTest("reportToConsole", reportToConsole);
// TODO: already implements AsyncGenerator<RunTestsMessage>, but add as "implements to class"
// TODO: implements PromiseLike<RunTestsEndResult>
-class TestApi {
+class TestRunner {
readonly testsToRun: TestDefinition[];
readonly stats = {
filtered: 0,
@@ -234,14 +241,18 @@ class TestApi {
passed: 0,
failed: 0,
};
+ private usedOnly: boolean;
constructor(
- public tests: TestDefinition[],
+ tests: TestDefinition[],
public filterFn: (def: TestDefinition) => boolean,
public failFast: boolean
) {
- this.testsToRun = tests.filter(filterFn);
- this.stats.filtered = tests.length - this.testsToRun.length;
+ const onlyTests = tests.filter(({ only }) => only);
+ this.usedOnly = onlyTests.length > 0;
+ const unfilteredTests = this.usedOnly ? onlyTests : tests;
+ this.testsToRun = unfilteredTests.filter(filterFn);
+ this.stats.filtered = unfilteredTests.length - this.testsToRun.length;
}
async *[Symbol.asyncIterator](): AsyncIterator<TestMessage> {
@@ -280,7 +291,9 @@ class TestApi {
const duration = +new Date() - suiteStart;
- yield { end: { ...this.stats, duration, results } };
+ yield {
+ end: { ...this.stats, usedOnly: this.usedOnly, duration, results },
+ };
}
}
@@ -331,7 +344,7 @@ async function runTests({
onMessage = undefined,
}: RunTestsOptions = {}): Promise<TestMessage["end"] & {}> {
const filterFn = createFilterFn(filter, skip);
- const testApi = new TestApi(TEST_REGISTRY, filterFn, failFast);
+ const testRunner = new TestRunner(TEST_REGISTRY, filterFn, failFast);
const originalConsole = globalThis.console;
@@ -342,7 +355,7 @@ async function runTests({
let endMsg: TestMessage["end"];
- for await (const message of testApi) {
+ for await (const message of testRunner) {
if (onMessage != null) {
await onMessage(message);
}
@@ -358,7 +371,7 @@ async function runTests({
globalThis.console = originalConsole;
}
- if (endMsg!.failed > 0 && exitOnFail) {
+ if ((endMsg!.failed > 0 || endMsg?.usedOnly) && exitOnFail) {
exit(1);
}
diff --git a/cli/tests/deno_test_only.ts b/cli/tests/deno_test_only.ts
new file mode 100644
index 000000000..12425f21f
--- /dev/null
+++ b/cli/tests/deno_test_only.ts
@@ -0,0 +1,15 @@
+Deno.test({
+ name: "abc",
+ fn() {},
+});
+
+Deno.test({
+ only: true,
+ name: "def",
+ fn() {},
+});
+
+Deno.test({
+ name: "ghi",
+ fn() {},
+});
diff --git a/cli/tests/deno_test_only.ts.out b/cli/tests/deno_test_only.ts.out
new file mode 100644
index 000000000..a23f2505c
--- /dev/null
+++ b/cli/tests/deno_test_only.ts.out
@@ -0,0 +1,7 @@
+[WILDCARD]running 1 tests
+test def ... ok ([WILDCARD])
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out ([WILDCARD])
+
+FAILED because the "only" option was used
+
diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs
index 89b46acf3..66308a499 100644
--- a/cli/tests/integration_tests.rs
+++ b/cli/tests/integration_tests.rs
@@ -1272,16 +1272,22 @@ itest!(_026_redirect_javascript {
http_server: true,
});
+itest!(deno_test {
+ args: "test test_runner_test.ts",
+ exit_code: 1,
+ output: "deno_test.out",
+});
+
itest!(deno_test_fail_fast {
args: "test --failfast test_runner_test.ts",
exit_code: 1,
output: "deno_test_fail_fast.out",
});
-itest!(deno_test {
- args: "test test_runner_test.ts",
+itest!(deno_test_only {
+ args: "test deno_test_only.ts",
exit_code: 1,
- output: "deno_test.out",
+ output: "deno_test_only.ts.out",
});
#[test]
diff --git a/cli/tests/unit/test_util.ts b/cli/tests/unit/test_util.ts
index 660e13511..25da7a638 100644
--- a/cli/tests/unit/test_util.ts
+++ b/cli/tests/unit/test_util.ts
@@ -1,6 +1,8 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { assert, assertEquals } from "../../../std/testing/asserts.ts";
+import * as colors from "../../../std/fmt/colors.ts";
+export { colors };
import { resolve } from "../../../std/path/mod.ts";
export {
assert,
@@ -93,7 +95,9 @@ function registerPermCombination(perms: Permissions): void {
export async function registerUnitTests(): Promise<void> {
const processPerms = await getProcessPermissions();
- for (const unitTestDefinition of REGISTERED_UNIT_TESTS) {
+ const onlyTests = REGISTERED_UNIT_TESTS.filter(({ only }) => only);
+ const unitTests = onlyTests.length > 0 ? onlyTests : REGISTERED_UNIT_TESTS;
+ for (const unitTestDefinition of unitTests) {
if (!permissionsMatch(processPerms, unitTestDefinition.perms)) {
continue;
}
@@ -126,11 +130,13 @@ interface UnitTestPermissions {
interface UnitTestOptions {
ignore?: boolean;
+ only?: boolean;
perms?: UnitTestPermissions;
}
interface UnitTestDefinition extends Deno.TestDefinition {
ignore: boolean;
+ only: boolean;
perms: Permissions;
}
@@ -174,6 +180,7 @@ export function unitTest(
name,
fn,
ignore: !!options.ignore,
+ only: !!options.only,
perms: normalizedPerms,
};
diff --git a/cli/tests/unit/unit_test_runner.ts b/cli/tests/unit/unit_test_runner.ts
index e3df358d7..38db545c7 100755
--- a/cli/tests/unit/unit_test_runner.ts
+++ b/cli/tests/unit/unit_test_runner.ts
@@ -2,6 +2,8 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import "./unit_tests.ts";
import {
+ REGISTERED_UNIT_TESTS,
+ colors,
readLines,
permissionCombinations,
Permissions,
@@ -225,6 +227,13 @@ async function masterRunnerMain(
}
console.log("Unit tests passed");
+
+ if (REGISTERED_UNIT_TESTS.find(({ only }) => only)) {
+ console.error(
+ `\n${colors.red("FAILED")} because the "only" option was used`
+ );
+ Deno.exit(1);
+ }
}
const HELP = `Unit test runner