我正在尝试使用节点创建一个工具,该工具将根据我发送的配置信息通过 karma 多次运行 Jasmine。
我从调用一次 karma 开始,我在服务器上遇到了问题
Promise
即使我使用 singleRun: true
运行,也无法在测试运行的情况下解决问题。
如果我要在最终用户视为“单个”操作中多次调用 Jasmine,我需要编译
function doneCallback(exitCode)
行中的所有返回值,以查看是否有非 0。
也就是说,当使用
singleRun: true
时,我认为没有机会像 文档演示那样设置事件侦听器:
runner.run({port: 9876}).on('progress', function(data) { process.stdout.write(data) })
我不是创建一个跑步者并运行它。我只是执行
server.start
并观察它在配置中运行一次测试,我需要获取结果。相反,当读取配置并且服务器启动时,所有 Promise
都会返回。当“隐式”运行器在 singleRun 期间完成时,没有 Promise
返回到调用上下文。 [关于监听事件] 就是一劳永逸。
这是我的代码的修改版本:
function startKarma(karmaConfig) {
var karmaPromise = karma.config
.parseConfig(
null,
karmaConfig,
// http://karma-runner.github.io/6.3/dev/public-api.html
{ promiseConfig: true, throwErrors: true }
)
.then(
(parsedKarmaConfig) => {
// http://karma-runner.github.io/6.4/dev/public-api.html
const server = new karma.Server(parsedKarmaConfig, function doneCallback(
exitCode
) {
console.log("Karma has exited with " + exitCode); // <<<<<<< happens last. exitCode is defined.
return exitCode;
});
var serverPromise = server.start();
return serverPromise.then(function (x) {
console.log("server promise", x); // <<<<<<<<<<<< happens first, x === undefined
return x;
});
},
(rejectReason) => {
console.log("Error", rejectReason);
throw rejectReason;
}
);
return karmaPromise;
}
我这样开始代码:
// leaving out config creation
startKarma(config).then(function (after) {
console.log("after", after); // <<<<<<<<<<<< happens second, after === undefined
});
这是我的“基本配置”,它在代码中的其他地方覆盖了
files
、preprocessors
和 basePath
。
var baseConfig = {
files: [{ pattern: "**/*.js" }],
preprocessors: {
"**/!(*test).js": ["coverage"],
},
basePath: "./",
frameworks: ["jasmine"],
exclude: ["**/node_modules/**/"],
reporters: ["coverage", "mocha"],
coverageReporter: {
reporters: [
{ type: "text-summary" },
{ type: "html", dir: "../coverage/" },
{ type: "text", dir: "coverage/", file: "coverage.txt" },
],
},
port: 9876,
colors: true,
logLevel: karma.config.LOG_DEBUG,
autoWatch: true,
browsers: ["Chrome"],
singleRun: true,
concurrency: Infinity,
};
我可以解释我想要做的事情的最好方法是,“我想在 singleRun Server.start 中获取运行程序的句柄,并通过
Promise
将其结果返回给调用代码。”不确定在哪里我应该访问“隐式”跑步者的结果。
换句话说,对于
singleRun: true
,我希望仅在测试运行后返回 Server.start
Promise
,而不是在服务器启动并运行后立即返回。既然没有,我想知道在哪里可以连接到必须正在运行的跑步者。
结果:
START:
server promise undefined
after undefined
01 05 2023 16:27:56.094:INFO [karma-server]: Karma v6.4.2 server started at http://localhost:9876/
01 05 2023 16:27:56.097:INFO [launcher]: Launching browsers Chrome with concurrency unlimited
01 05 2023 16:27:56.103:INFO [launcher]: Starting browser Chrome
01 05 2023 16:27:56.916:INFO [Chrome 112.0.0.0 (Windows 10)]: Connected on socket fLZkvHywy1zV36iIAAAB with id 22356421
these are not real tests
add2 function in global scope
√ should return a value that is 2 greater than that which was pushed in
add2broken function in global scope
× should return a value that is 2 greater than that which was pushed in
double function in global scope
√ should return a value double that pushed in
square function in global scope
√ should return a value that squares that which was pushed in
Finished in 0.018 secs / 0.002 secs @ 16:27:56 GMT-0400 (Eastern Daylight Time)
SUMMARY:
√ 3 tests completed
× 1 test failed
FAILED TESTS:
these are not real tests
add2broken function in global scope
× should return a value that is 2 greater than that which was pushed in
Chrome 112.0.0.0 (Windows 10)
Expected 27 to be 7.
at <Jasmine>
at UserContext.<anonymous> (fakeTests/testSubdir/add2.test.js:26:28)
at <Jasmine>
=============================== Coverage summary ===============================
Statements : 76.47% ( 13/17 )
Branches : 50% ( 8/16 )
Functions : 80% ( 4/5 )
Lines : 81.25% ( 13/16 )
================================================================================
需要明确的是,我认为设置
singleRun: false
并“手动”处理服务器生命周期将允许我做我想做的事情,但如果可能的话,我想 KISS 并挂钩到 singleRun: true
版本。
我相信,正确的做法是将所有这些逻辑包装到我自己的
Promise
中。也就是说,karma 不为单次运行提供事件挂钩。这种方法(在原始问题中描述)是浪费精力。
要卷起自己的
Promise
包装纸,这样做(关键是return new Promise(function (resolve, reject) //...
):
function startKarma(karmaRunId, overrides) {
return new Promise(function (resolve, reject) {
overrides = Object.assign(
{},
karmaConfigTools.overridesForMochaTestingRun,
overrides
);
var karmaConfig = karmaConfigTools.createKarmaConfig(overrides);
karma.config
.parseConfig(
null,
karmaConfig,
// In most cases, parseOptions.throwErrors = true should also be set.
// This disables process exiting and allows errors to result in rejected promises.
// http://karma-runner.github.io/6.3/dev/public-api.html
{ promiseConfig: true, throwErrors: true }
)
.then(
(parsedKarmaConfig) => {
// fwiw
// http://karma-runner.github.io/6.4/dev/public-api.html
// I'm not sure why it names the callback function doneCallback.
const server = new karma.Server(
parsedKarmaConfig,
function doneCallback(exitCode) {
// 0 is success/no test failure.
// Anything else is bad. Usually 1 afaict.
utils.debugLog("Wrapped karma has exited with " + exitCode);
karmaRunResults[karmaRunId] = exitCode;
resolve(exitCode);
}
).on("progress", function (data) {
process.stdout.write(data);
});
server.start().then(function (x) {
utils.debugLog("server started", x);
});
},
(rejectReason) => {
utils.debugLog("Error", rejectReason);
throw rejectReason;
}
);
});
}
现在我可以等到到达我最初想要的部分:
const server = new karma.Server(parsedKarmaConfig, function doneCallback(
exitCode
) {
console.log("Karma has exited with " + exitCode); // <<<<<<< happens last. exitCode is defined.
return exitCode;
});
我补充说,
Promise
不是通过业力来监听,而是表现得惊人😏,就像一个Promise
,允许调用者等待,直到获得它想要的信息。如果我需要调用大量的 singleRun 测试套件,我会将这些调用分组到一个数组中并 Promise.all
它们。再说一遍,典型的Promise
东西。
最重要的是,业力似乎不允许您收听单次运行中的事件。如果您想通过 karma 的处理程序使用类似
runner.run({port: 9876}).on('progress', function(data) { // ...
的代码进行监听,则必须设置一个开放式生命周期 (!singleRun) karma 运行器
但是,您可以使用基于“多个 singleRun”的逻辑设置自己的异步(基于
Promise
)管理来完成相同的事情,如上所示。