@hapi/lab 与 lab-transform-typescript 正在返回错误的代码覆盖率结果
Posted
技术标签:
【中文标题】@hapi/lab 与 lab-transform-typescript 正在返回错误的代码覆盖率结果【英文标题】:@hapi/lab with lab-transform-typescript is returning buggy code coverage results 【发布时间】:2020-07-12 03:25:20 【问题描述】:我在 TypeScript 中有一个 HapiJS 项目,想开始添加一些单元测试。现在代码很简单:
server.ts
import * as Hapi from "@hapi/hapi";
import routes from "./routes";
const server = new Hapi.Server(
port: 80,
host: "0.0.0.0",
debug:
request: ["error"]
);
let serverSetup = false;
const setupServer = async () =>
if (serverSetup) return;
await server.register([routes]);
serverSetup = true;
;
export const init = async () =>
await setupServer();
await server.initialize();
return server;
;
export const start = async () =>
await setupServer();
await server.start();
console.log(`Server running at: $server.info.uri`);
return server;
;
routes.ts:
import * as Hapi from "@hapi/hapi";
export default
name: "RouteIndex",
version: "1.0.0",
register: function (server:Hapi.Server, options:Hapi.ServerRegisterOptions)
server.route(
method: "GET",
path: "/",
handler: (request, h) =>
return message: "Hello, World!";
);
server.route(
method: "*",
path: "/any*",
handler: (request, h) =>
return "404!";
);
;
然后是我的单元测试:
server.test.js
const Lab = require("@hapi/lab");
const expect = require("@hapi/code");
const afterEach, beforeEach, describe, it = exports.lab = Lab.script();
const init, start = require("../src/server");
const HTTP_PORT = 80;
const HTTP_STATUS_OK = 200;
describe("General Server Tests", () =>
let server;
beforeEach(async () =>
server = await init();
);
afterEach(async () =>
await server.stop();
);
it("Starts successfully", async () =>
server = await start();
expect(server.type).to.equal("tcp");
expect(server.settings.port).to.equal(HTTP_PORT);
expect(server.settings.host).to.equal("0.0.0.0");
);
it("Responds to GET requests", async () =>
const res = await server.inject(
method: "GET",
url: "/"
);
expect(res.statusCode).to.equal(HTTP_STATUS_OK);
);
);
要运行我的测试,我的 package.json 中有以下内容:
// ...
"scripts":
// ...
"test": "lab -vclS -T node_modules/lab-transform-typescript **/*.test.js",
// ...
// ...
添加 -v
标志是因为我更喜欢详细输出
添加了-c
标志,以便我可以获得代码覆盖率报告,这就是我的问题所在
必须添加 -l
标志,否则我会收到错误消息:The following leaks were detected:__extends, __assign, __rest, __decorate, __param, __metadata, __awaiter, __generator,...
(由 TypeScript 编译器创建的所有全局变量)
-S
标志是根据 lab-transform-typescript documentation (-S
== --sourcemaps
) 添加的
-T
标志用于加载 lab-transform-typescript
(-T
== --transform
)
当我运行测试时,结果如下:
stevenbarnett@MacBook-Pro hapi-test % npm run test
> hapi-test@1.0.0 test /Users/stevenbarnett/Repos/hapi-test
> lab -vclS -T node_modules/lab-transform-typescript **/*.test.js
Server running at: http://0.0.0.0:80
General Server Tests
✔ 1) Starts successfully (4 ms)
✔ 2) Responds to GET requests (7 ms)
3 tests complete
Test duration: 111 ms
Coverage: 71.50% (61/214)
src/server.ts missing coverage from file(s):
null on line(s): , , , , , , , , , , , , , , , , , ,
src/routes.ts missing coverage from file(s):
null on line(s): , , , , , , , , , , , , , , , , , , , , ,
src/routes/index.ts on line(s): 24
所以我知道src/routes/index.ts
在第 24 行缺少覆盖(这是 404 错误,我没有测试 404)——但其他行是荒谬的:
null on line(s): , , , , , , , , , , , , , , , , , ,
为什么会发生这种情况,我该如何解决?
【问题讨论】:
【参考方案1】:我创建了一个 HapiJS Lab 的分支来解决我自己的问题。我的 fork 不是完美(它不会处理具有多个源文件的代码,例如串联),但它适用于 TypeScript 处理。
请注意,我的更改是从版本 22.0.4 派生出来的(特别是提交 cd0bd3b1ad063ae62b58a764751fb3465a49fe99
),因此这些更改可能无法完全在较新的版本上运行。
我的第一个更改是lib/coverage.js
:
ret.source[num].hits = data.lines[num];
ret.source[num].miss = isMiss;
);
+ // Translate source maps
+ if (ret.sourcemaps)
+
+ const mappedSource = ;
+ const loadedOriginalSource = ;
+ Object.keys(ret.source).forEach(id =>
+
+ const line = ret.source[id];
+ if (line.originalFilename)
+
+ // ERROR: If a file came from two original source files (e.g. concatenation)
+ // then we'll only include the first file in line.source and we'll
+ // combine the number of hits
+ //
+ // Ideally this method needs a way to return more than one file and the files
+ // need to be merged by whoever reads the result
+ //
+ // Although for just TypeScript-to-javascript, this is fine
+ const originalSource = loadedOriginalSource[line.originalFilename] || Fs.readFileSync(line.originalFilename, 'utf8').split("\n");
+ loadedOriginalSource[line.originalFilename] = originalSource;
+ let originalLine = mappedSource[line.originalLine] ||
+ source: originalSource[line.originalLine - 1],
+ hits: 0,
+ miss: false
+ ;
+ originalLine.hits += (line.hits || 0);
+ originalLine.miss = originalLine.miss || line.miss;
+ mappedSource[line.originalLine] = originalLine;
+
+ );
+ ret.source = mappedSource;
+ ret.sloc = Object.keys(ret.source).length;
+ ret.hits = 0;
+ ret.misses = 0;
+ ret.sourcemaps = false;
+ Object.keys(ret.source).forEach(id =>
+
+ if (ret.source[id].miss)
+
+ ret.misses++;
+
+ else
+
+ ret.hits++;
+
+ );
+
+
ret.percent = ret.hits / ret.sloc * 100;
return ret;
;
我的第二个也是不太重要的变化是提高输出。当我看到“2/127”之类的东西时,我一直感到困惑,并认为只有 2 行代码覆盖,而实际上 125 行代码覆盖。当 100% 的行具有代码覆盖率时,也有 no 输出,这是我不喜欢的 - 我希望看到我确定地达到了我的目标。所以我对lib/reporters/console.js
做了如下修改:
const coverage = notebook.coverage;
if (coverage)
const status = coverage.percent.toFixed(2) + '%';
+ const outputColor = coverage.percent === 100 ? green : red;
output += 'Coverage: ';
- output += coverage.percent === 100 ? green(status) : red(status + ' (' + (coverage.sloc - coverage.hits) + '/' + coverage.sloc + ')');
+ output += outputColor(status + ' (' + coverage.hits + '/' + coverage.sloc + ' lines)');
if (coverage.percent < 100)
for (const file of coverage.files)
let missingLines;
【讨论】:
以上是关于@hapi/lab 与 lab-transform-typescript 正在返回错误的代码覆盖率结果的主要内容,如果未能解决你的问题,请参考以下文章