cenfun / monocart-coverage-reports

A code coverage tool to generate native V8 reports or Istanbul reports.
MIT License
69 stars 6 forks source link

[Suggest] 建议按语法树解析来判断分支 #48

Closed fanksy closed 3 months ago

fanksy commented 4 months ago

目前生产环境中,出现很多分支误判的情况,明显没有分支的行,却被判断为分支。语法树应该会明确判断该行有没有分支,建议按语法树解析优先。

cenfun commented 4 months ago

目前就是按照AST语法树来判断分支的,这个没有问题,问题的关键不在这,而在于sourcemap是否能精确完成匹配:

而覆盖率的数据,是基于编译过的代码的,所以需要将编译过的代码的覆盖率(准确的),还原到源代码的覆盖率(还原需要sourcemap支持,未必能精确还原) 问题在这里,如果你有好的建议关于精确使用soucemap还原的,随时可以提,或者提供优化思路也可以,或者有重现问题的demo代码和仓库,不然无法继续解决问题

fanksy commented 4 months ago

我整理下案例

fanksy commented 4 months ago

我需要对代码进行脱敏整理,然后再还原看能不能重现,比较耗时间,需要晚几天才能提供。

目前最大问题是该行没有分支且被覆盖执行,却被判断有分支,而且分支都没有被覆盖执行,导致行覆盖率不准确。

即便枚举案例,可能并不能解决所有问题,提个切实折衷的建议,以sourcemap里的源码解析为准,如果源码语法树解析没有分支,那么就判定该行没有分支,只计算该行有没有被覆盖执行,这样既可以消除分支歧义,也可以保留行覆盖率的准确度。

cenfun commented 4 months ago

那是肯定的,越小越好,容易定位问题

对源码进行AST分析,非常好的想法,一开始也是这样想的 但用户的源码的格式是不可知的,比如vue,react,angular,ts,等等,不同的源码有不同的AST解析工具,不可能把所有解析器都集成进来,所以这个方法是不现实的

目前对源码解析,只解析了空行和注释行

cenfun commented 4 months ago

还有个方法就是,你可以自行调试一下,按照下面这个教程 https://github.com/cenfun/monocart-coverage-reports?#debug-for-coverage-and-sourcemap

打开 logging=debug 然后可以看到有问题的代码的位置 然后把你的dist文件和sourcemap文件用下面网站打开,对比位置看看为啥不对 Source Map Visualization

fanksy commented 4 months ago

那是肯定的,越小越好,容易定位问题

对源码进行AST分析,非常好的想法,一开始也是这样想的 但用户的源码的格式是不可知的,比如vue,react,angular,ts,等等,不同的源码有不同的AST解析工具,不可能把所有解析器都集成进来,所以这个方法是不现实的

目前对源码解析,只解析了空行和注释行

调研过js的解析工具,你用的acorn算一个,那个astexplorer就搜集了很多,但都不如顶级项目swc,不过是rust写的,性能很好

https://github.com/swc-project/swc

你看能不能集成,tsx模式下几乎能解析所有的js语言

cenfun commented 4 months ago

这种不行的,之前用rust写过,除非全部用rust重写,那就没必要用nodejs了,因为js和rust写wasm通讯开销极高,得不偿失

而且swc也是通过别人的插件去解析各种源码的,庞大工作量不说,关键是解析出来了,照样要和v8的覆盖率做匹配,工作量更大 毕竟如果是sourcemap都大概已经匹配好了,只是部分地方不精确,如果是重新解析源码AST,是完全没有和编译的代码有任何匹配的 你只是得到一个比如分支的总数是准确的,但未覆盖的分支位置在哪,依旧找不到,也就没法标记成红色

cenfun commented 4 months ago

还不如看看用的是什么build工具,去提PR把sourcemap生成更精确的好 目前来说webpack生成的sourcemap是比较准确有效的,esbuild,rollup这些生成的就差一些 但sourcemap大家一般也只是用到调试上,所以精确不需要那么高,至少暂时也不会专门为了v8覆盖率去提高精度

fanksy commented 4 months ago

这种不行的,之前用rust写过,除非全部用rust重写,那就没必要用nodejs了,因为js和rust写wasm通讯开销极高,得不偿失

而且swc也是通过别人的插件去解析各种源码的,庞大工作量不说,关键是解析出来了,照样要和v8的覆盖率做匹配,工作量更大 毕竟如果是sourcemap都大概已经匹配好了,只是部分地方不精确,如果是重新解析源码AST,是完全没有和编译的代码有任何匹配的 你只是得到一个比如分支的总数是准确的,但未覆盖的分支位置在哪,依旧找不到,也就没法标记成红色

了解,生产上使用,准确性是最重要的,你看能不能在压缩情况下,把行覆盖率做到100%准确,我们现在只是把分支覆盖当作参考数据,行覆盖率才是评估的标准。

cenfun commented 4 months ago

目前来说,行覆盖应该是里面较准确的 当然肯定有些特殊情况没有遇见的,但大家又很难提供重现的案例 比如vite这个,它可能为了性能或者热重载一些原因,在编译的代码里面加入很多和源码无关的代码,导致覆盖率也会针对这些代码,再加上此处的sourcemap又不准确,匹配回源码就产生一些副作用,这大概就是现在可能的一些问题

fanksy commented 4 months ago

或许可以借鉴下chrome Devtools显示行覆盖率的算法,官方的准确度应该是没问题的

cenfun commented 4 months ago

chrome Devtools又不能分析源码,它只是显示编译后的代码,这个MCR本来就完全支持,而且比chrome的强大很多,它只能看行,其他都看不了,MCR设置logging=debug就能看到编译后的文件的覆盖率 最早就看过他们写的源码了

fanksy commented 4 months ago

chrome Devtools又不能分析源码,它显示只是显示编译后的代码,这个MCR本来就完全支持,设置logging=debug就能看到 最早就看过他们写的源码了

只要有sourcemap,chrome Devtools就可以分析,你要在Sources栏目点开左侧的资源加载树,chrome会把sourcemap还原成目录

cenfun commented 4 months ago

如果也支持sourcemap,那我觉得准确性可能还没MCR高,毕竟MCR做了很多精度的修正优化 但它应该实现了行的覆盖 你不如拿你的案例比较一下,看看它的匹配是不是准的

fanksy commented 3 months ago

@cenfun ignore注释屏蔽代码,要求编译后压缩过的文件保留ignore注释?原本以为是通过解析源码里的注释进行排除

cenfun commented 3 months ago

理论上无需保留注释,是通过解析源码里的注释进行排除,但排除的范围,也一样要通过sourcemap匹配回源码的位置,这个位置也需要匹配到注释的对应位置才行 还是之前提到的,如果对代码进行压缩,sourcemap的精度将低很多

fanksy commented 3 months ago

那我看错了,还以为你通过执行文件里的注释来排除v8的字节偏移量

fanksy commented 3 months ago

报告结果有没有标记哪些行是被排除的,因为我做的是增量统计,如果你没有标记,我就得自己去解析标记了

cenfun commented 3 months ago

有的,数据和界面上都有 https://cenfun.github.io/monocart-coverage-reports/v8/#page=0d92811daa4d17b96b8abcee06398848dde603e2 image

fanksy commented 3 months ago

转换的istanbul数据格式也有?我看看

cenfun commented 3 months ago

首先V8永远都会转换成Istanbul,但又不仅仅只有Istanbul,里面包含Istanbul和可读性更好的V8报告数据

fanksy commented 3 months ago

试了下,没有精确到行,只有偏移量,我试试把偏移量转换成行

cenfun commented 3 months ago

需要的可以加上,换算接口都有 关键你现在是怎么用的,要在哪里获取?浏览器还是nodejs 把你的使用场景提供一下

fanksy commented 3 months ago

在后端解析用的,你看能不能给转换的istanbul数据也加上ignores,基于行的ignores

cenfun commented 3 months ago

我会在数据里加一个额外的信息 image 包含

cenfun commented 3 months ago

刚刚发了2.9.0版你试试 image

fanksy commented 3 months ago

请教下,你有了解安卓或者ios原生代码的覆盖率方案么?

cenfun commented 3 months ago

请教下,你有了解安卓或者ios原生代码的覆盖率方案么?

不了解,我只懂JS前端