Skip to content

Commit d937d17

Browse files
committed
chore(cli): refactor internal config of compas test
1 parent d9967a2 commit d937d17

File tree

13 files changed

+332
-319
lines changed

13 files changed

+332
-319
lines changed

packages/cli/src/compas/commands/test.js

Lines changed: 22 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
11
import { url } from "inspector";
2-
import { cpus } from "os";
32
import { isMainThread, Worker } from "worker_threads";
4-
import { isNil, refreshEnvironmentCache, spawn } from "@compas/stdlib";
5-
import { loadTestConfig } from "../../testing/config.js";
3+
import { isNil, spawn } from "@compas/stdlib";
4+
import { testingLoadConfig } from "../../testing/config.js";
65
import { printTestResultsFromWorkers } from "../../testing/printer.js";
6+
import { testLogger } from "../../testing/state.js";
77
import {
8-
setAreTestRunning,
9-
setTestLogger,
10-
testLogger,
11-
} from "../../testing/state.js";
12-
import {
13-
listTestFiles,
148
runTestsInProcess,
9+
testingListFiles,
1510
workerFile,
1611
} from "../../testing/worker-internal.js";
1712

@@ -96,13 +91,6 @@ export async function cliExecutor(logger, state) {
9691
};
9792
}
9893

99-
if (state.flags.coverage && !isNil(state.flags.randomizeRounds)) {
100-
logger.error("Can't run '--coverage' with '--randomize-rounds'.");
101-
return {
102-
exitStatus: "failed",
103-
};
104-
}
105-
10694
if (state.flags.serial && !isNil(state.flags.parallelCount)) {
10795
logger.error("Can't specify both '--serial' and '--parallel-count'.");
10896
return {
@@ -117,61 +105,46 @@ export async function cliExecutor(logger, state) {
117105
};
118106
}
119107

120-
/** @type {number} */
121-
// @ts-ignore
122-
const parallelCount = state.flags.serial
123-
? 1
124-
: state.flags.parallelCount ?? Math.min(4, cpus().length - 1);
108+
// @ts-expect-error
109+
const testConfig = await testingLoadConfig(logger, state.flags);
125110

126-
if (state.flags.coverage) {
111+
if (testConfig.coverage) {
127112
const { exitCode } = await spawn(`npx`, [
128113
"c8",
129114
"node",
130115
process.argv[1],
131116
"test",
132117
"--parallel-count",
133-
`${parallelCount}`,
118+
String(testConfig.parallelCount),
119+
"--randomize-rounds",
120+
String(testConfig.randomizeRounds),
121+
"--with-logs",
122+
String(testConfig.withLogs),
123+
"--bail",
124+
String(testConfig.bail),
134125
]);
135126

136127
return {
137128
exitStatus: exitCode === 0 ? "passed" : "failed",
138129
};
139130
}
140131

141-
state.flags.randomizeRounds = state.flags.randomizeRounds ?? 1;
142-
143-
state.flags.withLogs = state.flags.withLogs ?? false;
144-
145-
process.env._COMPAS_TEST_WITH_LOGS = String(state.flags.withLogs);
146-
process.env.__COMPAS_TEST_PARALLEL_COUNT = String(parallelCount);
147-
process.env.__COMPAS_TEST_RANDOMIZE_ROUNDS = String(
148-
state.flags.randomizeRounds,
149-
);
150-
refreshEnvironmentCache();
151-
152-
// Make sure to set tests running, so `mainTestFn` is 'disabled'.
153-
setAreTestRunning(true);
154-
setTestLogger(logger);
155-
156-
if (parallelCount === 1 && state.flags.randomizeRounds === 1) {
132+
if (testConfig.parallelCount === 1 && testConfig.randomizeRounds === 1) {
157133
// Run serial tests in the same process
158-
const exitCode = await runTestsInProcess({
159-
bail: !!state.flags.bail,
160-
});
134+
const exitCode = await runTestsInProcess(testConfig);
161135

162136
return {
163137
exitStatus: exitCode === 0 ? "passed" : "failed",
164138
};
165139
}
166140

167-
await loadTestConfig();
168-
const files = await listTestFiles();
141+
const files = await testingListFiles(testConfig);
169142

170143
// Almost does the same things as `mainTestFn`, however since tests are run by workers
171144
// instead of directly. We dispatch them, and then print the results.
172145
const results = [];
173146

174-
for (let i = 0; i < Number(state.flags.randomizeRounds); ++i) {
147+
for (let i = 0; i < Number(testConfig.randomizeRounds); ++i) {
175148
if (i !== 0) {
176149
// Shuffle files in place
177150
// From: https://stackoverflow.com/a/6274381
@@ -181,8 +154,8 @@ export async function cliExecutor(logger, state) {
181154
}
182155
}
183156

184-
const workers = initializeWorkers(parallelCount);
185-
const testResult = await runTests(workers, files);
157+
const workers = initializeWorkers(testConfig.parallelCount);
158+
const testResult = await runTests(testConfig, workers, files);
186159

187160
// Early exit on test failure
188161
const hasFailure = testResult.find((it) => it.isFailed);
@@ -213,11 +186,11 @@ export async function cliExecutor(logger, state) {
213186
* Run tests on a worker pull-basis.
214187
* Once all files are done or in process, we request results.
215188
*
189+
* @param {import("../../testing/config.js").TestConfig} testConfig
216190
* @param {Worker[]} workers
217191
* @param {string[]} files
218192
*/
219-
async function runTests(workers, files) {
220-
const isDebugging = !!url();
193+
async function runTests(testConfig, workers, files) {
221194
let idx = 0;
222195
const results = [];
223196

@@ -256,9 +229,6 @@ async function runTests(workers, files) {
256229
worker.postMessage({
257230
type: "provide_file",
258231
file,
259-
options: {
260-
isDebugging,
261-
},
262232
});
263233
}
264234
} else if (message.type === "provide_result") {
Lines changed: 76 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,80 @@
11
/**
2-
* Config loader if available.
3-
* Loads the following:
4-
* - timeout, used as timeout per test case
5-
* - ignored directories
6-
* - setup, function called once before tests run
7-
* - teardown, function called once after all tests run
2+
* @typedef {object} TestConfig
3+
* @property {number} timeout Sub test timeout.
4+
* @property {boolean} bail Stop running tests when a failure / failed assertion is
5+
* encountered
6+
* @property {boolean} isDebugging Disable hard test timeouts when the debugger is
7+
* attached
8+
* @property {() => (Promise<void>|void)} setup Global process setup function
9+
* @property {() => (Promise<void>|void)} teardown Global process setup function
10+
* @property {boolean} withLogs Don't disable all info-logs
11+
* @property {number} randomizeRounds Randomizes the test file order after the first
12+
* round
13+
* @property {number} parallelCount The number of test files to process in parallel
14+
* @property {string[]} ignoreDirectories Subdirectories to skip, when looking for all
15+
* test files
16+
* @property {boolean} coverage Run the test while collecting coverage results.
17+
* @property {boolean} singleFileMode Should be set when only a single test should run via 'mainTestFn'
18+
*/
19+
/**
20+
* Load the test config & parse the flags
821
*
9-
* @returns {Promise<void>}
22+
* @param {import("@compas/stdlib").Logger} [logger]
23+
* @param {Record<string, string|number|boolean>} [flags]
24+
* @returns {Promise<TestConfig>}
1025
*/
11-
export function loadTestConfig(): Promise<void>;
26+
export function testingLoadConfig(
27+
logger?: import("@compas/stdlib/src/logger.js").Logger | undefined,
28+
flags?: Record<string, string | number | boolean> | undefined,
29+
): Promise<TestConfig>;
30+
export type TestConfig = {
31+
/**
32+
* Sub test timeout.
33+
*/
34+
timeout: number;
35+
/**
36+
* Stop running tests when a failure / failed assertion is
37+
* encountered
38+
*/
39+
bail: boolean;
40+
/**
41+
* Disable hard test timeouts when the debugger is
42+
* attached
43+
*/
44+
isDebugging: boolean;
45+
/**
46+
* Global process setup function
47+
*/
48+
setup: () => Promise<void> | void;
49+
/**
50+
* Global process setup function
51+
*/
52+
teardown: () => Promise<void> | void;
53+
/**
54+
* Don't disable all info-logs
55+
*/
56+
withLogs: boolean;
57+
/**
58+
* Randomizes the test file order after the first
59+
* round
60+
*/
61+
randomizeRounds: number;
62+
/**
63+
* The number of test files to process in parallel
64+
*/
65+
parallelCount: number;
66+
/**
67+
* Subdirectories to skip, when looking for all
68+
* test files
69+
*/
70+
ignoreDirectories: string[];
71+
/**
72+
* Run the test while collecting coverage results.
73+
*/
74+
coverage: boolean;
75+
/**
76+
* Should be set when only a single test should run via 'mainTestFn'
77+
*/
78+
singleFileMode: boolean;
79+
};
1280
//# sourceMappingURL=config.d.ts.map

0 commit comments

Comments
 (0)