• 或者你能不能提供一个单独的文件处理 针对他插桩试试看 ,如果不行能方便去掉一些敏感的代码 拿出一个文件 我们来看下?

  • 你不能这么搞的 你这么处理的话就相当于 你的 babel 的 parser 只是用的装饰器那个插件的。复制下我这个吧

    "parser-plugins": [
            "typescript",
            "jsx",
            "asyncGenerators",
            "bigInt",
            "classProperties",
            "classPrivateProperties",
            "dynamicImport",
            "importMeta",
            "objectRestSpread",
            "optionalCatchBinding",
            "decorators"
        ]
    

  • 加个 decorators 可以解决的。 你是用的 nyc 插桩吧

  • 你微信多少? 我没怎么用 istanbul-middleware 不过可以一起看看

  • 但是你这个匿名函数会有啥影响吗?或者方便的话 加个微信聊下?

  • 没有遇到过,不过可以分享下那个函数怎么样的吗,我这边也试试看?

  • 是的 ,你可以看下这个 issue 最后解决的内容,Fix printing TSTypeOperator token 那个被替换为 word 了。所以最后没有跑那个方法了。

  • 咦 我这边都显示正常呀。

  • 可以了解下 selenium ide 最新版本的录制工具,我记得上面能支持拖拽,右键的一些录制的

  • cypress 那块更多的是基于自动化的方式的,但是它里面的实现逻辑是可以参考的。
    增量这块我们其实也做了,但是我们目前只是做到了基于文件的情况,就是这个文件被修改到就要求被覆盖,还没有继续完善到基于行或者方法的覆盖率这种。


  • 更新于 2020.07.20

    前端代码覆盖率又接入了新的项目,但是这次的前端用到了一个新的框架 easywebpack, 不过好在官方的文档是相当的详尽,所以在babel 升级基本没有遇到什么大的问题。

    原以为一切的会比较顺利的进行, 但是测试的同事反馈说出现几个文件的覆盖率数据明显不正确,并且那几个文件的数据都是一样的。我们来看下结果数据
    image

    这里的四个覆盖率数据竟然是完全一样的,我们再详细看下某个文件的详细覆盖率数据

    image

    很明显 从 11 行的地方我们发现这里的代码与覆盖率的数据其实是完全对应不上的,我们在 11 行处根本就不存在有 IF 的代码逻辑。

    那现在的问题来了为什么会出现这种情况呢? 首先我们的覆盖率数据是有经过多次合并的,所以首先我们可能要怀疑是我们的覆盖率数据合并导致的问题。那我们就先验证下原生的网页上的覆盖率数据是否有问题吧

    image

    这里是从浏览器的控制台打印出来的结果,从上述的一些数据我们可以看出来,在 11 的时候,确实有一个 if 的语句,所以说明了一个问题 就是原本的文件覆盖率数据就已经错误了。

    那问题到底出在哪里呢?这里还是需要从打包的地方去分析这个问题了。

    以下是 webpack 的部分截图

    image

    这里分别了客户端渲染以及服务端渲染的打包,所以我们要重点看下 loader.js 里面做了啥事情。

    module.exports = function() {
      this.cacheable();
      return `
        import React from 'react';
        import ReactDom from 'react-dom';
        import { AppContainer } from 'react-hot-loader';
        import Entry from '${this.resourcePath.replace(/\\/g, '\\\\')}';
        const state = window.__INITIAL_STATE__;
        const render = (App)=>{
          ReactDom.hydrate(EASY_ENV_IS_DEV ? <AppContainer><App {...state} /></AppContainer> : <App {...state} />, document.getElementById('app'));
        };
    
        if (EASY_ENV_IS_DEV && module.hot) {
          module.hot.accept('${this.resourcePath.replace(/\\/g, '\\\\')}', () => { render(Entry) });
        }
        render(Entry);
      `;
    };
    
    

    针对要处理的 js 文件,看起来这里的 loader 又重新进行 render 了一次,而且如果细心一点 我们可能注意到一个很关键的因素,这里从 return 方法往下的第 11 行 刚好是 if (EASY_ENV_IS_DEV && module.hot) { 一个 if 语句, 所以其实我们所有错误的 js 的覆盖率都被这段的逻辑所影响到了。那我们原本的 jsx 的文件有没有被插桩呢?所以还是需要看下插桩后的文件到底长什么样。

    针对 campCourse.jsx 的打包文件

    image

    我们在 6w 多行的时候可以看到有这样的一个方法 针对的就是该文件的覆盖率数据

    然后我们再观察
    image

    在 11w 多行的时候, 也出现了同样的覆盖率数据,而且该数据与我们从浏览器读到的数据是一致的也就是错误的数据。到这里应该就能有一定的总结的,也就是说源码文件其实是有被插桩的,只是说它的数据最终被另外一个相同对象给覆盖了导致我们拿到了错误的数据。

    问题到了这里就要想着怎么解决了,其实 istanbul 提供另一些方式来过滤掉一些你不想插桩的代码。具体可以看 ignoring-code-for-coverage

    所以我们需要做的是忽略到这个文件的插桩,不过这个 ignore 添加在哪里还是有一定的技巧的 我们来看下最后的改动代码吧。

    module.exports = function() {
      this.cacheable();
      return `/* istanbul ignore file */
        import React from 'react';
        import ReactDom from 'react-dom';
        import { AppContainer } from 'react-hot-loader';
        import Entry from '${this.resourcePath.replace(/\\/g, '\\\\')}';
        const state = window.__INITIAL_STATE__;
        const render = (App)=>{
          ReactDom.hydrate(EASY_ENV_IS_DEV ? <AppContainer><App {...state} /></AppContainer> : <App {...state} />, document.getElementById('app'));
        };
    
        if (EASY_ENV_IS_DEV && module.hot) {
          module.hot.accept('${this.resourcePath.replace(/\\/g, '\\\\')}', () => { render(Entry) });
        }
        render(Entry);
      `;
    };
    
    

    我们需要将/* istanbul ignore file */的 内容添加在 return 语句的后面,即第一行才行,如此下来的代码都不会被插桩处理了。

  • 哈哈,暂时没有考虑这个,不过很感谢😄

  • 这个我没有遇到过,如果你不嫌麻烦的话,可以弄一个最小的仓库内容出来 然后我帮你看看是什么情况,不然这样子描述 我帮不上什么忙

  • 看下 16 楼的回复,可以不回滚版本也是能解决那个问题的。

  • 嗯 验证了下 确实是这样子,感谢呀。

  • 我有个问题呀,你说的 5w 多的代码是指的你的源码吗?然后 2w 多是指的插桩后的报告吧。这个报告能够对应到你真正的源码不?
    我看到你的报告中的 vplayer 看上去不像是你们的源码呀

  • https://www.jianshu.com/p/fc038a92d1eb 看看这个文章 网上比较多 关于 express 设置跨域的方式

  • 这个是前端的跨域请求了 你可以改下你那个 8088 的服务,让他允许跨域请求就可以了。

  • 要怎么解决呢?有方法吗? 不过我看文档的说明是说 15 的版本是默认开启 jsx 的解析的,之前 14 的版本是不开启的,感觉貌似有点相反了。

  • 浏览器端实时插桩这种方案很难做的,现在基本上前端代码都是 es6 代码然后 babel 转 es5 然后浏览器拿到的时候已经是被编译后的代码了,这个时候插桩怎么映射回源码的,这个事情很难

  • 能不能提供更详细的信息 我们这边 typescript 的插桩是可以的,并且有能够获取到覆盖率数据,但是我们这边都是前端项目,不是针对 react-native 的。

  • 你在 build 的过程中有没有报错 (记得还要安装 npm install @babel/plugin-transform-modules-commonjs),如果没有其实就是没问题的,然后你要验证这个插桩是否成功的话直接打开对应的页面,然后 F12, 控制台输入 window.coverage 看看是否有内容,当然更便捷的就是直接打开打包后的 js 文件,查看里面有没有 cov,branchMap 的字样。

  • 如果说你的项目是 babel,并且版本是 7 的话 那确实只需要修改 babelrc 就可以了

  • instrument-backend-code node 端的插桩的话 参考下这里

  • 我们这边 node 端只是做请求转发到后台的作用而已,基本没有实现什么业务逻辑,所以 node 端我们是没有插桩的。这块我了解的不多。可能需要你去到 nyc 官网去看下,理论上应该是可以的。