Replace mocha with a custom test runner

This commit is contained in:
Laurențiu Nicola 2021-12-02 08:20:10 +02:00
parent 4691a0647b
commit 76b3d437d3
5 changed files with 185 additions and 1175 deletions

File diff suppressed because it is too large Load Diff

View File

@ -43,8 +43,6 @@
"d3-graphviz": "^4.0.0" "d3-graphviz": "^4.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/glob": "^7.1.4",
"@types/mocha": "^8.2.3",
"@types/node": "~14.17.5", "@types/node": "~14.17.5",
"@types/node-fetch": "^2.5.11", "@types/node-fetch": "^2.5.11",
"@types/vscode": "^1.57.0", "@types/vscode": "^1.57.0",
@ -52,8 +50,6 @@
"@typescript-eslint/parser": "^4.28.2", "@typescript-eslint/parser": "^4.28.2",
"esbuild": "^0.12.19", "esbuild": "^0.12.19",
"eslint": "^7.30.0", "eslint": "^7.30.0",
"glob": "^7.1.6",
"mocha": "^9.0.2",
"tslib": "^2.3.0", "tslib": "^2.3.0",
"typescript": "^4.3.5", "typescript": "^4.3.5",
"typescript-formatter": "^7.2.2", "typescript-formatter": "^7.2.2",

View File

@ -1,38 +1,80 @@
import * as path from 'path'; import * as path from 'path';
import * as Mocha from 'mocha';
import * as glob from 'glob';
export function run(): Promise<void> { class Test {
// Create the mocha test readonly name: string;
const mocha = new Mocha({ readonly promise: Promise<void>;
ui: 'tdd',
color: true
});
const testsRoot = __dirname; constructor(name: string, promise: Promise<void>) {
this.name = name;
return new Promise((resolve, reject) => { this.promise = promise;
glob('**/**.test.js', { cwd: testsRoot }, (err, files) => { }
if (err) { }
return reject(err);
} class Suite {
tests: Test[];
// Add files to the test suite
files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); constructor() {
this.tests = [];
try { }
// Run the mocha test
mocha.timeout(100000); public addTest(name: string, f: () => Promise<void>): void {
mocha.run(failures => { const test = new Test(name, f());
if (failures > 0) { this.tests.push(test);
reject(new Error(`${failures} tests failed.`)); }
} else {
resolve(); public async run(): Promise<void> {
} let failed = 0;
}); for (const test of this.tests) {
} catch (err) { try {
reject(err); await test.promise;
} ok(`${test.name}`);
}); } catch (e) {
}); error(` ✖︎ ${test.name}\n ${e.stack}`);
failed += 1;
}
}
if (failed) {
const plural = failed > 1 ? "s" : "";
throw new Error(`${failed} failed test${plural}`);
}
}
}
export class Context {
public async suite(name: string, f: (ctx: Suite) => void): Promise<void> {
const ctx = new Suite();
f(ctx);
try {
ok(`⌛︎ ${name}`);
await ctx.run();
ok(`${name}`);
} catch (e) {
error(`✖︎ ${name}\n ${e.stack}`);
throw e;
}
}
}
export async function run(): Promise<void> {
const context = new Context();
const testFiles = ["launch_config.test.js", "runnable_env.test.js"];
for (const testFile of testFiles) {
try {
const testModule = require(path.resolve(__dirname, testFile));
await testModule.getTests(context);
} catch (e) {
error(`${e}`);
throw e;
}
}
}
function ok(message: string): void {
// eslint-disable-next-line no-console
console.log(`\x1b[32m${message}\x1b[0m`);
}
function error(message: string): void {
// eslint-disable-next-line no-console
console.error(`\x1b[31m${message}\x1b[0m`);
} }

View File

@ -1,24 +1,24 @@
import * as assert from 'assert'; import * as assert from 'assert';
import { Cargo } from '../../src/toolchain'; import { Cargo } from '../../src/toolchain';
import { Context } from '.';
suite('Launch configuration', () => { export async function getTests(ctx: Context) {
await ctx.suite('Launch configuration/Lens', suite => {
suite('Lens', () => { suite.addTest('A binary', async () => {
test('A binary', async () => {
const args = Cargo.artifactSpec(["build", "--package", "pkg_name", "--bin", "pkg_name"]); const args = Cargo.artifactSpec(["build", "--package", "pkg_name", "--bin", "pkg_name"]);
assert.deepStrictEqual(args.cargoArgs, ["build", "--package", "pkg_name", "--bin", "pkg_name", "--message-format=json"]); assert.deepStrictEqual(args.cargoArgs, ["build", "--package", "pkg_name", "--bin", "pkg_name", "--message-format=json"]);
assert.deepStrictEqual(args.filter, undefined); assert.deepStrictEqual(args.filter, undefined);
}); });
test('One of Multiple Binaries', async () => { suite.addTest('One of Multiple Binaries', async () => {
const args = Cargo.artifactSpec(["build", "--package", "pkg_name", "--bin", "bin1"]); const args = Cargo.artifactSpec(["build", "--package", "pkg_name", "--bin", "bin1"]);
assert.deepStrictEqual(args.cargoArgs, ["build", "--package", "pkg_name", "--bin", "bin1", "--message-format=json"]); assert.deepStrictEqual(args.cargoArgs, ["build", "--package", "pkg_name", "--bin", "bin1", "--message-format=json"]);
assert.deepStrictEqual(args.filter, undefined); assert.deepStrictEqual(args.filter, undefined);
}); });
test('A test', async () => { suite.addTest('A test', async () => {
const args = Cargo.artifactSpec(["test", "--package", "pkg_name", "--lib", "--no-run"]); const args = Cargo.artifactSpec(["test", "--package", "pkg_name", "--lib", "--no-run"]);
assert.deepStrictEqual(args.cargoArgs, ["test", "--package", "pkg_name", "--lib", "--no-run", "--message-format=json"]); assert.deepStrictEqual(args.cargoArgs, ["test", "--package", "pkg_name", "--lib", "--no-run", "--message-format=json"]);
@ -26,8 +26,8 @@ suite('Launch configuration', () => {
}); });
}); });
suite('QuickPick', () => { await ctx.suite('Launch configuration/QuickPick', suite => {
test('A binary', async () => { suite.addTest('A binary', async () => {
const args = Cargo.artifactSpec(["run", "--package", "pkg_name", "--bin", "pkg_name"]); const args = Cargo.artifactSpec(["run", "--package", "pkg_name", "--bin", "pkg_name"]);
assert.deepStrictEqual(args.cargoArgs, ["build", "--package", "pkg_name", "--bin", "pkg_name", "--message-format=json"]); assert.deepStrictEqual(args.cargoArgs, ["build", "--package", "pkg_name", "--bin", "pkg_name", "--message-format=json"]);
@ -35,18 +35,18 @@ suite('Launch configuration', () => {
}); });
test('One of Multiple Binaries', async () => { suite.addTest('One of Multiple Binaries', async () => {
const args = Cargo.artifactSpec(["run", "--package", "pkg_name", "--bin", "bin2"]); const args = Cargo.artifactSpec(["run", "--package", "pkg_name", "--bin", "bin2"]);
assert.deepStrictEqual(args.cargoArgs, ["build", "--package", "pkg_name", "--bin", "bin2", "--message-format=json"]); assert.deepStrictEqual(args.cargoArgs, ["build", "--package", "pkg_name", "--bin", "bin2", "--message-format=json"]);
assert.deepStrictEqual(args.filter, undefined); assert.deepStrictEqual(args.filter, undefined);
}); });
test('A test', async () => { suite.addTest('A test', async () => {
const args = Cargo.artifactSpec(["test", "--package", "pkg_name", "--lib"]); const args = Cargo.artifactSpec(["test", "--package", "pkg_name", "--lib"]);
assert.deepStrictEqual(args.cargoArgs, ["test", "--package", "pkg_name", "--lib", "--message-format=json", "--no-run"]); assert.deepStrictEqual(args.cargoArgs, ["test", "--package", "pkg_name", "--lib", "--message-format=json", "--no-run"]);
assert.notDeepStrictEqual(args.filter, undefined); assert.notDeepStrictEqual(args.filter, undefined);
}); });
}); });
}); }

View File

@ -1,6 +1,7 @@
import * as assert from 'assert'; import * as assert from 'assert';
import { prepareEnv } from '../../src/run'; import { prepareEnv } from '../../src/run';
import { RunnableEnvCfg } from '../../src/config'; import { RunnableEnvCfg } from '../../src/config';
import { Context } from '.';
import * as ra from '../../src/lsp_ext'; import * as ra from '../../src/lsp_ext';
function makeRunnable(label: string): ra.Runnable { function makeRunnable(label: string): ra.Runnable {
@ -20,100 +21,101 @@ function fakePrepareEnv(runnableName: string, config: RunnableEnvCfg): Record<st
return prepareEnv(runnable, config); return prepareEnv(runnable, config);
} }
suite('Runnable env', () => { export async function getTests(ctx: Context) {
test('Global config works', () => { await ctx.suite('Runnable env', suite => {
const binEnv = fakePrepareEnv("run project_name", { "GLOBAL": "g" }); suite.addTest('Global config works', async () => {
assert.strictEqual(binEnv["GLOBAL"], "g"); const binEnv = fakePrepareEnv("run project_name", { "GLOBAL": "g" });
assert.strictEqual(binEnv["GLOBAL"], "g");
const testEnv = fakePrepareEnv("test some::mod::test_name", { "GLOBAL": "g" }); const testEnv = fakePrepareEnv("test some::mod::test_name", { "GLOBAL": "g" });
assert.strictEqual(testEnv["GLOBAL"], "g"); assert.strictEqual(testEnv["GLOBAL"], "g");
});
suite.addTest('null mask works', async () => {
const config = [
{
env: { DATA: "data" }
}
];
const binEnv = fakePrepareEnv("run project_name", config);
assert.strictEqual(binEnv["DATA"], "data");
const testEnv = fakePrepareEnv("test some::mod::test_name", config);
assert.strictEqual(testEnv["DATA"], "data");
});
suite.addTest('order works', async () => {
const config = [
{
env: { DATA: "data" }
},
{
env: { DATA: "newdata" }
}
];
const binEnv = fakePrepareEnv("run project_name", config);
assert.strictEqual(binEnv["DATA"], "newdata");
const testEnv = fakePrepareEnv("test some::mod::test_name", config);
assert.strictEqual(testEnv["DATA"], "newdata");
});
suite.addTest('mask works', async () => {
const config = [
{
env: { DATA: "data" }
},
{
mask: "^run",
env: { DATA: "rundata" }
},
{
mask: "special_test$",
env: { DATA: "special_test" }
}
];
const binEnv = fakePrepareEnv("run project_name", config);
assert.strictEqual(binEnv["DATA"], "rundata");
const testEnv = fakePrepareEnv("test some::mod::test_name", config);
assert.strictEqual(testEnv["DATA"], "data");
const specialTestEnv = fakePrepareEnv("test some::mod::special_test", config);
assert.strictEqual(specialTestEnv["DATA"], "special_test");
});
suite.addTest('exact test name works', async () => {
const config = [
{
env: { DATA: "data" }
},
{
mask: "some::mod::test_name",
env: { DATA: "test special" }
}
];
const testEnv = fakePrepareEnv("test some::mod::test_name", config);
assert.strictEqual(testEnv["DATA"], "test special");
const specialTestEnv = fakePrepareEnv("test some::mod::another_test", config);
assert.strictEqual(specialTestEnv["DATA"], "data");
});
suite.addTest('test mod name works', async () => {
const config = [
{
env: { DATA: "data" }
},
{
mask: "some::mod",
env: { DATA: "mod special" }
}
];
const testEnv = fakePrepareEnv("test some::mod::test_name", config);
assert.strictEqual(testEnv["DATA"], "mod special");
const specialTestEnv = fakePrepareEnv("test some::mod::another_test", config);
assert.strictEqual(specialTestEnv["DATA"], "mod special");
});
}); });
}
test('null mask works', () => {
const config = [
{
env: { DATA: "data" }
}
];
const binEnv = fakePrepareEnv("run project_name", config);
assert.strictEqual(binEnv["DATA"], "data");
const testEnv = fakePrepareEnv("test some::mod::test_name", config);
assert.strictEqual(testEnv["DATA"], "data");
});
test('order works', () => {
const config = [
{
env: { DATA: "data" }
},
{
env: { DATA: "newdata" }
}
];
const binEnv = fakePrepareEnv("run project_name", config);
assert.strictEqual(binEnv["DATA"], "newdata");
const testEnv = fakePrepareEnv("test some::mod::test_name", config);
assert.strictEqual(testEnv["DATA"], "newdata");
});
test('mask works', () => {
const config = [
{
env: { DATA: "data" }
},
{
mask: "^run",
env: { DATA: "rundata" }
},
{
mask: "special_test$",
env: { DATA: "special_test" }
}
];
const binEnv = fakePrepareEnv("run project_name", config);
assert.strictEqual(binEnv["DATA"], "rundata");
const testEnv = fakePrepareEnv("test some::mod::test_name", config);
assert.strictEqual(testEnv["DATA"], "data");
const specialTestEnv = fakePrepareEnv("test some::mod::special_test", config);
assert.strictEqual(specialTestEnv["DATA"], "special_test");
});
test('exact test name works', () => {
const config = [
{
env: { DATA: "data" }
},
{
mask: "some::mod::test_name",
env: { DATA: "test special" }
}
];
const testEnv = fakePrepareEnv("test some::mod::test_name", config);
assert.strictEqual(testEnv["DATA"], "test special");
const specialTestEnv = fakePrepareEnv("test some::mod::another_test", config);
assert.strictEqual(specialTestEnv["DATA"], "data");
});
test('test mod name works', () => {
const config = [
{
env: { DATA: "data" }
},
{
mask: "some::mod",
env: { DATA: "mod special" }
}
];
const testEnv = fakePrepareEnv("test some::mod::test_name", config);
assert.strictEqual(testEnv["DATA"], "mod special");
const specialTestEnv = fakePrepareEnv("test some::mod::another_test", config);
assert.strictEqual(specialTestEnv["DATA"], "mod special");
});
});