Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] tsc构建时生sourceMap,导致覆盖率报告中没有执行到的源文件100% 覆盖 #89

Open
springJia opened this issue Nov 14, 2024 · 8 comments

Comments

@springJia
Copy link

697_50

如图,删除src(原始ts 之后覆盖率只有3%),如果原始文件存在,sourceMap 解析之后会显示100%

@cenfun
Copy link
Owner

cenfun commented Nov 14, 2024

没看明白是什么问题,比如现在问题是什么,你期待的结果是什么,描述详细一点

@springJia
Copy link
Author

实际的覆盖率数据对最终展示的不匹配,实际覆盖率应该在3%左右,sourceMap映射到源码之后覆盖率都显示100%

@springJia springJia reopened this Nov 15, 2024
@cenfun
Copy link
Owner

cenfun commented Nov 15, 2024

理论上覆盖就是要使用sourceMap匹配到源码,看源码的覆盖率才有意义
如果覆盖率不对,大概率可能和sourceMap的匹配有关
如果可以,你可以建个仓库,让我可以在本地重现问题,这样调试一下,才知道根本原因在哪

@cenfun
Copy link
Owner

cenfun commented Nov 15, 2024

当然如果是私有项目,你也可以自己按照这个教程,自行调试
https://github.com/cenfun/monocart-coverage-reports/blob/main/README.zh-Hans.md#debug-for-coverage-and-sourcemap

@springJia
Copy link
Author

springJia commented Nov 18, 2024

谢谢。我找到了原因了,sourceMap映射没问题。有两个原因:

  1. 覆盖率报告中没有扫某个文件时,htm报表只展示coverage扫到的文件sourceMap映射的ts, 即不会列出覆盖率0% 的ts 源文件,这样计算的总覆盖率看上去不符合实际。
  2. 我是在代码运行时(非启动时)执行的code coverage,如下 test.js:

export function app(req:any ,res:any) {
console.log('running');
}

function app2Test(req:any ,res:any) {
console.log('running----');
}

生成的覆盖率json ,由于app2Test 没有执行所以不包含app2Test, 如下:
{
"scriptId": "266",
"url": "file:///cov-demo/dist/app.js",
"functions": [
{
"functionName": "app",
"ranges": [
{
"startOffset": 99,
"endOffset": 153,
"count": 8
}
],
"isBlockCoverage": true
}
]
}

_最终html覆盖率报告显示app.js 覆盖率为100%, v8 codecoverage 没有检查到的方法默认monocart生成报告时默认为全局代码了(猜测 _

想问下以上两点有没有解决方法,尤其第二点,会让单个文件的运行时覆盖率不准确

@cenfun
Copy link
Owner

cenfun commented Nov 18, 2024

你说的应该是没有参与测试的源文件应该包含到报告中对吧,那它的覆盖率就是0%,可以通过all参数来包含所有的源文件
https://github.com/cenfun/monocart-coverage-reports/blob/main/README.zh-Hans.md#adding-empty-coverage-for-untested-files

如果是ts的源文件,可以使用编译器进行编译,否则无法解析出function,branch这些
这里是使用swc来编译ts文件的例子

const path = require("path");
const swc = require("@swc/core");
const coverageOptions = {
    all: {
        dir: ['./src'],
        transformer: async (entry) => {
            const { code, map } = await swc.transform(entry.source, {
                filename: path.basename(entry.url),
                sourceMaps: true,
                isModule: true,
                jsc: {
                    parser: {
                        syntax: "typescript",
                        jsx: true
                    },
                    transform: {}
                }
            });
            entry.source = code;
            entry.sourceMap = JSON.parse(map);
        }
    }
};

@springJia
Copy link
Author

重新配置all 之后 没有参与测试的源文件应该包含到报告 的问题解决了(之前我配置的项目根目录,不是src)

第二个问题可能我没解释清楚,覆盖率报告里function 数量总数是2,但是app2Test 没有参与测试~
761_2

@cenfun
Copy link
Owner

cenfun commented Nov 18, 2024

我知道你的意思了
由于覆盖率数据是从编译过的js文件获取的(位置mapping关系来自编译过的文件),然后通过sourcemap还原到源文件
目前的策略是这样的
1,V8覆盖率数据提到的位置范围,就是按照覆盖本身的是否覆盖来标记(count 是0表示未覆盖。count大于0表示覆盖)
2,其实还有很多位置是V8覆盖率数据没有提到的,这里统一按照默认覆盖count=1处理

你的例子里,覆盖率json 没有包含app2Test的任何覆盖率信息,所以按照默认覆盖一次处理(但实际上可能未覆盖,然而v8并不能提供相关信息)

可能的解决办法:app2Test的代码可能剔除了,因为build工具可能开启了treeShaking功能,把明显不需要的代码过滤掉
这样无论如何都不可能收集到app2Test的覆盖率数据,类似的情况比如

if(false) {
  // ....
}

这种代码也是可能被build工具剔除的,因为没有存在的意义,永远都不会执行
所以试试修改build的参数,比如esbuild就可以设置treeShaking: false来保留这些冗余代码,以提供覆盖率数据,你看下你用的工具是否支持

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants