带有labtransform-typescript的@hapi/lab返回错误代码覆盖率结果



我在TypeScript中有一个HapiJS项目,想开始添加一些单元测试。现在的代码很简单:

服务器.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;
};

路线.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);
});
});

为了运行我的测试,我的包.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标志是根据实验室转换类型脚本文档添加的(-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): , , , , , , , , , , , , , , , , , ,

    为什么会发生这种情况,我该如何解决?

    我创建了一个HapiJS实验室的分支来解决我自己的问题。我的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%的行都有代码覆盖时,也有没有的输出,这是我不喜欢的——我喜欢看到我达到了目标。因此,我对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;
    

    最新更新