cenfun / monocart-coverage-reports

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

[Feature] 调用add添加数据时进行实时Merge #61

Closed fanksy closed 3 months ago

fanksy commented 3 months ago

需求背景: 在持续测试的模式下,需要持续搜集数据,并尽可能缓存数据,一方面确保数据不丢失,另一方面方便观察历史数据排查问题。但是.cache缓存文件数据过多,会导致CPU内存消耗很大。

功能建议: 在调用add添加数据时,实时进行merge成单个覆盖率数据文件

fanksy commented 3 months ago

https://github.com/cenfun/monocart-reporter/issues/134#issuecomment-2235242465

实时进行merge可能不大行,因为add本身是异步的并行的,不好控制merge时机,然后就是merge也消耗时间影响正常测试,而且可能做太多的无用功,最后一起merge就不存在这个问题

能提供目前cache文件的数量有多少吗,每个大概多大?

CPU没什么好说的,基本就是没法控制的,都是有多少用多少。

内存的话之前修正过一次,不知道你用的是不是最新版的MCR
之前遇到的case差不多有几百个覆盖率文件,但测试了挺快的,内存并没有消耗太多
https://github.com/cenfun/monocart-coverage-reports/actions/runs/9917255166/job/27400525834

如果依旧爆内存,可以试试开启额外内存限制

NODE_OPTIONS: --max-old-space-size=4096
如果4g不够,可以试试8g (NODE_OPTIONS: --max-old-space-size=8192)

https://nodejs.org/docs/latest/api/cli.html#--max-old-space-sizesize-in-megabytes

目前使用场景:将monocart-coverage-reports集成到electron客户端,供测试人员在电脑安装使用,需要持续收集数据,每10秒收集一次,一天可能产生上万份数据文件,因为是客户端,也不能随意分配大内存,目前临时解决方案是每10秒生成报告然后遍历删除历史数据文件,这样做就无法回溯了,最好是能做到实时merge,看能否做个merge开关,由使用者自己控制merge的时机,或者每次生成报告时进行merge,将扫描到的数据文件合并成一个大的数据文件

cenfun commented 3 months ago

首先,electron一样可以调节内存

import { app } from "electron";
app.commandLine.appendSwitch('js-flags', '--max-old-space-size=4096');
app.on('ready', () => {
    // ...
});

但我感觉关键问题不在这里,为什么会持续收集覆盖率呢?最多也就是案例多一点而已 首先,覆盖率衡量的是一份代码,和针对这份代码的所有测试案例,运行一次后的情况 也就是,下一次重复运行之前,就应该要调用generate()生成覆盖率报告了,此时覆盖率数据应该已经合并了,cache也可以删除了,只剩下报告作为历史纪录使用即可

不可能一直往cache里add()数据没有尽头吧?报告就应该是一份一份的,而不是持续累加的

fanksy commented 3 months ago

我们实际使用方式与你们平时使用有差异,目前并没有与case关联,测试用例自动化程度不高,上万的测试用例全是靠测试人员手动点击测试的,e2e基本算是没有,测试人员打开浏览器进行手动点击测试,electron只负责旁路持续收集浏览器产生的数据,并不知道测试什么时候结束。目前生成完报告就删除数据也已经解决问题,主要考虑monocart可能计算不准确,由于数据被删除,出现问题不好回溯追查。

cenfun commented 3 months ago

哦,这情况确实挺特别的。

那现在是定时生成报告?还是依照cache里的数量?

是否可以监听浏览器打开关闭,以及对应的网址做依据?比如仅需在网页关闭或跳转前收集?

如果没有触发点的持续收集,太多重复无意义的数据了

或者既然人工测试,也可以让人阶段性点击某个按钮生成报告

fanksy commented 3 months ago

每10秒生成一次,上传生成的istanbul json数据在后端进行合并,客户端越简单越好,设置限制了反倒会很麻烦

cenfun commented 3 months ago

Istanbul的json可以自行合并,合并代码

const istanbulLibCoverage = require('istanbul-lib-coverage');
const mergeIstanbulCoverage = (dataList) => {
    const istanbulCoverageList = dataList.map((it) => it.data);
    const coverageMap = istanbulLibCoverage.createCoverageMap();
    istanbulCoverageList.forEach((coverage) => {
        coverageMap.merge(coverage);
    });
    const istanbulData = coverageMap.toJSON();
    return istanbulData;
};

https://www.npmjs.com/package/istanbul-lib-coverage

顺便,如果是用Istanbul,完全没有必要使用MCR,直接用Istanbul的报告接口即可 MCR也只是包装了Istanbul接口而已,否则反而把问题复杂化 https://www.npmjs.com/package/istanbul-lib-report

MCR更多是聚焦在原生V8覆盖率数据,以后也会更多考虑直接使用类V8数据 顺便转换成Istanbul数据,也是兼容目前的生态,因为Istanbul的格式普遍被支持 而V8格式很少有支持,但支持自己原生格式的报告系统,我都是跳过Istanbul直接用V8转的,比如

直接用V8转没有精度损失,如果使用Istanbul,其实是V8到Istanbul的lcov,最后lcov再转成对应格式,可能损失精度 如果你直接使用Istanbul的数据,完全没必要使用MCR,直接用Istanbul即可

fanksy commented 3 months ago

我已经把前端的merge代码翻译成后端代码执行,正是考虑到istanbul的格式是普遍被支持的,所以后端才统一支持istanbul格式上报,用MCR就是不想做编译时插桩,主要看中行覆盖率和分支覆盖率,损失字节覆盖率可以接受。所以最好能直接merge原生的v8数据。可以把这个merge功能做成开关,想用就开启,不想用就关闭默认成现有状态。看你们规划吧,你们不想支持也能理解,不然我只能在项目里面打patch补丁了

cenfun commented 3 months ago

建议自行merge v8覆盖率 目前MCR使用的工具是: https://www.npmjs.com/package/@bcoe/v8-coverage 使用说明在这里:https://github.com/demurgos/v8-coverage