Skip to content

Commit

Permalink
feat: test runner (denoland#516)
Browse files Browse the repository at this point in the history
  • Loading branch information
bartlomieju authored and ry committed Aug 15, 2019
1 parent bd146e0 commit c44e536
Show file tree
Hide file tree
Showing 19 changed files with 164 additions and 132 deletions.
32 changes: 32 additions & 0 deletions .ci/check_source_file_changes.ts
@@ -0,0 +1,32 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { xrun } from "../prettier/util.ts";
import { red, green } from "../colors/mod.ts";

/**
* Checks whether any source file is changed since the given start time.
* If some files are changed, this function exits with 1.
*/
async function main(startTime: number): Promise<void> {
console.log("test checkSourceFileChanges ...");
const changed = new TextDecoder()
.decode(await xrun({ args: ["git", "ls-files"], stdout: "piped" }).output())
.trim()
.split("\n")
.filter(file => {
const stat = Deno.lstatSync(file);
if (stat != null) {
return (stat as any).modified * 1000 > startTime;
}
});
if (changed.length > 0) {
console.log(red("FAILED"));
console.log(
`Error: Some source files are modified during test: ${changed.join(", ")}`
);
Deno.exit(1);
} else {
console.log(green("ok"));
}
}

main(parseInt(Deno.args[1]));
4 changes: 3 additions & 1 deletion .ci/template.common.yml
Expand Up @@ -3,4 +3,6 @@ parameters:

steps:
- bash: deno${{ parameters.exe_suffix }} run --allow-run --allow-write --allow-read --allow-env ./format.ts --check
- bash: deno${{ parameters.exe_suffix }} run --allow-run --allow-net --allow-write --allow-read --allow-env --config=tsconfig.test.json ./test.ts
- bash: export START_TIME=$(date +%s)
- bash: deno${{ parameters.exe_suffix }} run --allow-run --allow-net --allow-write --allow-read --allow-env --config=tsconfig.test.json ./testing/runner.ts --exclude node_modules
- bash: deno${{ parameters.exe_suffix }} run --allow-run --allow-read .ci/check_source_file_changes.ts $START_TIME
4 changes: 0 additions & 4 deletions encoding/test.ts

This file was deleted.

14 changes: 0 additions & 14 deletions flags/test.ts

This file was deleted.

19 changes: 0 additions & 19 deletions fs/test.ts

This file was deleted.

5 changes: 0 additions & 5 deletions http/test.ts

This file was deleted.

6 changes: 0 additions & 6 deletions io/test.ts

This file was deleted.

3 changes: 0 additions & 3 deletions log/test.ts
Expand Up @@ -4,9 +4,6 @@ import { assertEquals } from "../testing/asserts.ts";
import * as log from "./mod.ts";
import { LogLevel } from "./levels.ts";

import "./handlers_test.ts";
import "./logger_test.ts";

class TestHandler extends log.handlers.BaseHandler {
public messages: string[] = [];

Expand Down
2 changes: 0 additions & 2 deletions mime/test.ts

This file was deleted.

2 changes: 0 additions & 2 deletions multipart/test.ts

This file was deleted.

1 change: 0 additions & 1 deletion prettier/test.ts

This file was deleted.

2 changes: 0 additions & 2 deletions strings/test.ts

This file was deleted.

65 changes: 0 additions & 65 deletions test.ts

This file was deleted.

2 changes: 2 additions & 0 deletions testing/mod.ts
Expand Up @@ -315,6 +315,8 @@ export interface RunOptions {
* 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,
Expand Down
127 changes: 127 additions & 0 deletions testing/runner.ts
@@ -0,0 +1,127 @@
#!/usr/bin/env deno -A
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { parse } from "../flags/mod.ts";
import { glob, isGlob, walk } from "../fs/mod.ts";
import { runTests } from "./mod.ts";
const { args, cwd } = Deno;

const DEFAULT_GLOBS = [
"**/*_test.ts",
"**/*_test.js",
"**/test.ts",
"**/test.js"
];

/* eslint-disable max-len */
function showHelp(): void {
console.log(`Deno test runner
USAGE:
deno -A https://deno.land/std/testing/runner.ts [OPTIONS] [FILES...]
OPTIONS:
-q, --quiet Don't show output from test cases
-f, --failfast Stop test suite on first error
-e, --exclude <FILES...> List of file names to exclude from run. If this options is
used files to match must be specified after "--".
ARGS:
[FILES...] List of file names to run. Defaults to: ${DEFAULT_GLOBS.join(
","
)}
`);
}
/* eslint-enable max-len */

function filePathToRegExp(str: string): RegExp {
if (isGlob(str)) {
return glob(str);
}

return RegExp(str);
}

/**
* This function runs matching test files in `root` directory.
*
* File matching and excluding supports glob syntax, ie. if encountered arg is
* a glob it will be expanded using `glob` method from `fs` module.
*
* Note that your shell may expand globs for you:
* $ deno -A ./runner.ts **\/*_test.ts **\/test.ts
*
* Expanding using `fs.glob`:
* $ deno -A ./runner.ts \*\*\/\*_test.ts \*\*\/test.ts
*
* `**\/*_test.ts` and `**\/test.ts"` are arguments that will be parsed and
* expanded as: [glob("**\/*_test.ts"), glob("**\/test.ts")]
*/
// TODO: change return type to `Promise<void>` once, `runTests` is updated
// to return boolean instead of exiting
export async function main(root: string = cwd()): Promise<void> {
const parsedArgs = parse(args.slice(1), {
boolean: ["quiet", "failfast", "help"],
string: ["exclude"],
alias: {
help: ["h"],
quiet: ["q"],
failfast: ["f"],
exclude: ["e"]
}
});

if (parsedArgs.help) {
return showHelp();
}

let includeFiles: string[];
let excludeFiles: string[];

if (parsedArgs._.length) {
includeFiles = (parsedArgs._ as string[])
.map(
(fileGlob: string): string[] => {
return fileGlob.split(",");
}
)
.flat();
} else {
includeFiles = DEFAULT_GLOBS;
}

if (parsedArgs.exclude) {
excludeFiles = (parsedArgs.exclude as string).split(",");
} else {
excludeFiles = [];
}

const filesIterator = walk(root, {
match: includeFiles.map((f: string): RegExp => filePathToRegExp(f)),
skip: excludeFiles.map((f: string): RegExp => filePathToRegExp(f))
});

const foundTestFiles: string[] = [];
for await (const { filename } of filesIterator) {
foundTestFiles.push(filename);
}

if (foundTestFiles.length === 0) {
console.error("No matching test files found.");
return;
}

console.log(`Found ${foundTestFiles.length} matching test files.`);

for (const filename of foundTestFiles) {
await import(filename);
}

await runTests({
exitOnFail: !!parsedArgs.failfast,
disableLog: !!parsedArgs.quiet
});
}

if (import.meta.main) {
main();
}
4 changes: 0 additions & 4 deletions testing/test.ts
Expand Up @@ -7,10 +7,6 @@ import {
assertThrows,
assertThrowsAsync
} from "./asserts.ts";
import "./format_test.ts";
import "./diff_test.ts";
import "./asserts_test.ts";
import "./bench_test.ts";

test(function testingAssertEqualActualUncoercable(): void {
let didThrow = false;
Expand Down
1 change: 0 additions & 1 deletion textproto/test.ts
Expand Up @@ -6,7 +6,6 @@
import { append } from "./mod.ts";
import { assertEquals } from "../testing/asserts.ts";
import { test } from "../testing/mod.ts";
import "./reader_test.ts";

test(async function textprotoAppend(): Promise<void> {
const enc = new TextEncoder();
Expand Down
2 changes: 0 additions & 2 deletions util/test.ts

This file was deleted.

1 change: 0 additions & 1 deletion ws/test.ts
@@ -1,5 +1,4 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import "./sha1_test.ts";
import { BufReader } from "../io/bufio.ts";
import { assert, assertEquals } from "../testing/asserts.ts";
import { runIfMain, test } from "../testing/mod.ts";
Expand Down

0 comments on commit c44e536

Please sign in to comment.