summaryrefslogtreecommitdiff
path: root/cli/js/testing.ts
diff options
context:
space:
mode:
authorNayeem Rahman <muhammed.9939@gmail.com>2020-03-15 09:34:24 +0000
committerGitHub <noreply@github.com>2020-03-15 10:34:24 +0100
commit64a35acd64f4a9aedfb52f6b364c229c6f7e4090 (patch)
treea2d3d68b3a072490c3d8e20333b07e165d3ab94b /cli/js/testing.ts
parenta159165fe5f9fe53c3593af707888a7efc859d14 (diff)
feat(cli/js/testing): Add TestDefinition::skip (#4351)
Diffstat (limited to 'cli/js/testing.ts')
-rw-r--r--cli/js/testing.ts131
1 files changed, 63 insertions, 68 deletions
diff --git a/cli/js/testing.ts b/cli/js/testing.ts
index a2944aff4..a4523d2b7 100644
--- a/cli/js/testing.ts
+++ b/cli/js/testing.ts
@@ -1,10 +1,11 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-import { red, green, bgRed, gray, italic } from "./colors.ts";
+import { bgRed, gray, green, italic, red, yellow } from "./colors.ts";
import { exit } from "./ops/os.ts";
import { Console } from "./web/console.ts";
const RED_FAILED = red("FAILED");
const GREEN_OK = green("OK");
+const YELLOW_SKIPPED = yellow("SKIPPED");
const RED_BG_FAIL = bgRed(" FAIL ");
const disabledConsole = new Console((_x: string, _isErr?: boolean): void => {});
@@ -18,6 +19,7 @@ export type TestFunction = () => void | Promise<void>;
export interface TestDefinition {
fn: TestFunction;
name: string;
+ skip?: boolean;
}
const TEST_REGISTRY: TestDefinition[] = [];
@@ -31,34 +33,32 @@ export function test(
t: string | TestDefinition | TestFunction,
fn?: TestFunction
): void {
- let name: string;
+ let testDef: TestDefinition;
if (typeof t === "string") {
- if (!fn) {
- throw new Error("Missing test function");
+ if (!fn || typeof fn != "function") {
+ throw new TypeError("Missing test function");
}
- name = t;
- if (!name) {
- throw new Error("The name of test case can't be empty");
+ if (!t) {
+ throw new TypeError("The test name can't be empty");
}
+ testDef = { fn: fn as TestFunction, name: t, skip: false };
} else if (typeof t === "function") {
- fn = t;
- name = t.name;
- if (!name) {
- throw new Error("Test function can't be anonymous");
+ if (!t.name) {
+ throw new TypeError("The test function can't be anonymous");
}
+ testDef = { fn: t, name: t.name, skip: false };
} else {
- fn = t.fn;
- if (!fn) {
- throw new Error("Missing test function");
+ if (!t.fn) {
+ throw new TypeError("Missing test function");
}
- name = t.name;
- if (!name) {
- throw new Error("The name of test case can't be empty");
+ if (!t.name) {
+ throw new TypeError("The test name can't be empty");
}
+ testDef = { fn: t.fn, name: t.name, skip: Boolean(t.skip) };
}
- TEST_REGISTRY.push({ fn, name });
+ TEST_REGISTRY.push(testDef);
}
interface TestStats {
@@ -78,20 +78,19 @@ export interface RunTestsOptions {
reporter?: TestReporter;
}
+enum TestStatus {
+ Passed = "passed",
+ Failed = "failed",
+ Skipped = "skipped"
+}
+
interface TestResult {
- passed: boolean;
name: string;
- skipped: boolean;
- hasRun: boolean;
- duration: number;
+ status: TestStatus;
+ duration?: number;
error?: Error;
}
-interface TestCase {
- result: TestResult;
- fn: TestFunction;
-}
-
export enum TestEvent {
Start = "start",
Result = "result",
@@ -115,24 +114,10 @@ interface TestEventEnd {
results: TestResult[];
}
-function testDefinitionToTestCase(def: TestDefinition): TestCase {
- return {
- fn: def.fn,
- result: {
- name: def.name,
- passed: false,
- skipped: false,
- hasRun: false,
- duration: 0
- }
- };
-}
-
// TODO: already implements AsyncGenerator<RunTestsMessage>, but add as "implements to class"
// TODO: implements PromiseLike<TestsResult>
class TestApi {
readonly testsToRun: TestDefinition[];
- readonly testCases: TestCase[];
readonly stats: TestStats = {
filtered: 0,
ignored: 0,
@@ -148,7 +133,6 @@ class TestApi {
) {
this.testsToRun = tests.filter(filterFn);
this.stats.filtered = tests.length - this.testsToRun.length;
- this.testCases = this.testsToRun.map(testDefinitionToTestCase);
}
async *[Symbol.asyncIterator](): AsyncIterator<
@@ -159,32 +143,35 @@ class TestApi {
tests: this.testsToRun.length
};
+ const results: TestResult[] = [];
const suiteStart = +new Date();
- for (const testCase of this.testCases) {
- const { fn, result } = testCase;
- let shouldBreak = false;
- try {
+ for (const { name, fn, skip } of this.testsToRun) {
+ const result: Partial<TestResult> = { name };
+ if (skip) {
+ result.status = TestStatus.Skipped;
+ this.stats.ignored++;
+ } else {
const start = +new Date();
- await fn();
- result.duration = +new Date() - start;
- result.passed = true;
- this.stats.passed++;
- } catch (err) {
- result.passed = false;
- result.error = err;
- this.stats.failed++;
- shouldBreak = this.failFast;
- } finally {
- result.hasRun = true;
- yield { kind: TestEvent.Result, result };
- if (shouldBreak) {
- break;
+ try {
+ await fn();
+ result.duration = +new Date() - start;
+ result.status = TestStatus.Passed;
+ this.stats.passed++;
+ } catch (err) {
+ result.duration = +new Date() - start;
+ result.status = TestStatus.Failed;
+ result.error = err;
+ this.stats.failed++;
}
}
+ yield { kind: TestEvent.Result, result: result as TestResult };
+ results.push(result as TestResult);
+ if (this.failFast && result.error != null) {
+ break;
+ }
}
const duration = +new Date() - suiteStart;
- const results = this.testCases.map(r => r.result);
yield {
kind: TestEvent.End,
@@ -241,13 +228,21 @@ export class ConsoleTestReporter implements TestReporter {
async result(event: TestEventResult): Promise<void> {
const { result } = event;
- if (result.passed) {
- this.console.log(
- `${GREEN_OK} ${result.name} ${formatDuration(result.duration)}`
- );
- } else {
- this.console.log(`${RED_FAILED} ${result.name}`);
- this.console.log(result.error!);
+ switch (result.status) {
+ case TestStatus.Passed:
+ this.console.log(
+ `${GREEN_OK} ${result.name} ${formatDuration(result.duration!)}`
+ );
+ break;
+ case TestStatus.Failed:
+ this.console.log(
+ `${RED_FAILED} ${result.name} ${formatDuration(result.duration!)}`
+ );
+ this.console.log(result.error!);
+ break;
+ case TestStatus.Skipped:
+ this.console.log(`${YELLOW_SKIPPED} ${result.name}`);
+ break;
}
}