天天看點

React前端功能測試覆寫率統計-插樁

1.React工程插樁教程

對于前端的覆寫率統計,單元測試的可以i通過jest和Enzyme配合進行單元測試并統計覆寫率,但是現在說的覆寫率主要是指功能測試的覆寫率。

而對于功能測試的測試覆寫率,肯定是需要進行代碼插樁然後統計代碼執行的密度,進行覆寫率統計,而插樁的庫主流的就是istanbul

一,對于node項目

可以使用istanbul-middleware來進行插樁以及覆寫率統計,可以參考樣例https://github.com/chenhengjie123/middleware-browser-coverage-demo

在依賴中添加istanbul-middleware和nopt,

然後使用istanbulMiddleware.hookLoader(__dirname , {verbose:true})來注入鈎子傳回插樁代碼

app.use('/coverage', coverage.createHandler({ verbose: true, resetOnGet: true }));

app.use(coverage.createClientHandler(publicDir, { matcher: matcher }));

暴露/coverage來擷取覆寫率,然後可以通過遠端請求擷取覆寫率或這定時i上報采集分析覆寫率,覆寫率資訊儲存至全局變量window.__coverage__中

二,對于React項目

因為React是屬于用戶端,react的代碼,都會通過webpack打包編譯成純的js檔案然後放到服務端當作靜态檔案執行,我們本地的環境實際

是通過React和node模拟了一個服務端,那麼如果要進行覆寫率統計需要對react元件進行插樁然後編譯成js執行。

插樁有兩種方式,一種是nyc(istanbul的指令行接口),還有一種是使用babel插件

1.使用nyc方式,nyc instrument [input] [output]

nyc instrument src ..\monitortool\jddl-app-client-back\src

如果插樁失敗的可以使用npm install -g [email protected],這個問題i實際是高版本的nyc做出了一些限制,修改下配置也是可以的

建立一個工程作為采集服務:wind-common-middleware(采集服務)

将需要插樁的代碼考到該工程中

 cp -r wind-common/src wind-common-middleware

 然後進入該工程

 cd wind-common-middleware

 進行插樁

 nyc instrument src ../wind-common/src

 啟動wind-common

 啟動wind-common-middleware

 問題:這種方式插樁後的代碼編譯失敗,主要的問題有:

 ①.引用問題,引用必須在第一行,插樁後的引用不在第一行

 ②.引用代碼被修改 

 import {Layout,Menu} from 'antd';被改成了import{Layout,Menu}from'antd';導緻引用失效

 ③.某些代碼查妝後不能執行

 const{SubMenu}=Menu;   ======>    const{SubMenu}=(cov_28x5j2q2at.s[0]++,Menu);

 2.使用插件方式

因為上面第一種方式的問題,那麼我們可不可以插樁後再通過babel編譯運作呢,

結果是不行的,代碼似乎沒有問題,沒有了import也沒有其他的文法問題,但是依然還是過不了react這一關,還是會報錯,依然是之前的那些問題,那麼這樣隻有一條路可以走了,是用babel編譯後的代碼進行插樁,使用插件babel-plugin-istanbul

 首先項目的目錄結構如下

React前端功能測試覆寫率統計-插樁

引入依賴:

    "@babel/cli": "7.7.7",

    "babel-loader": "8.1.0",

    "babel-plugin-istanbul": "6.0.0",

    "@babel/preset-react": "7.8.0"

babel-cli是babel編譯的主要依賴

babel-loader是檔案處理器,在webpack的配置檔案中需要配置react元件使用此loader來進行傳輸處理

babel-plugin-istanbul是插樁的主要依賴

babel-preset-react是react使用babel必須的依賴

如果需要在不同的環境啟用istanbul插件則還需要引入"@babel/preset-env": "7.7.7",

建立.babelrc檔案,内容

{

    "presets": ["@babel/react"],

    "plugins": ["istanbul"]

  }

webpack.config.js檔案如下

const path = require('path');

module.exports = {

  mode: 'development',

  entry: './src/index.js',

  module: {

    rules: [

      {

        test: /\.(js|jsx)$/,

        exclude: /node_modules/,

        use: [{

          loader: 'babel-loader'

        }]

      }

    ]

  }

};

package.json中的腳本檔案如下

"scripts": {

    "start": "react-app-rewired start",

    "build": "react-app-rewired build",

    "test": "react-app-rewired test"

  },

然後完成後,啟動報錯

React前端功能測試覆寫率統計-插樁

按照要求 npm install -save @babel/plugin-proposal-class-properties

依然報錯:

React前端功能測試覆寫率統計-插樁

添加依賴 npm install -save @babel/plugin-transform-modules-commonjs

在添加一個增強性能的 @babel/plugin-transform-modules-commonjs

啟動後依然有問題,雖然沒有報錯,但是關于antd的css樣式全沒了

React前端功能測試覆寫率統計-插樁

最後呢,通過文章https://testerhome.com/topics/24122了解到:

是因為istanbul和babel-plugin-import沖突,babel-plugin-import是一個antd ui庫的按需加載的插件, 因為antd的使用非常的廣泛, 基本上我們的前端項目都會使用到這個ui庫, 是以注定這個問題會遇到了

相關的問題在istanbul issue中也可以找到 https://github.com/istanbuljs/babel-plugin-istanbul/issues/161 文中提到的解決方案有兩種:

1.直接修改babel-plugin-import的源碼。

2.修改自己引用ui庫的方式。

上述兩種都比較麻煩,然而我們在機緣巧合下發現 可以通過在babelrc中引入 @babel/plugin-transform-modules-commonjs 也可以解決這個問題。不過原因暫時還不清楚(前端的打包真的太深奧了)

我們引入了@babel/plugin-transform-modules-commonjs後,發現依然有樣式問題,那麼可以分析得到肯定是babel-plugin-import沒有生效,最後發現是因為自己沒有在.babelrc中進行配置,配置後的.babelrc檔案完整如下:

{

    "presets": ["@babel/react"],

    "plugins": ["@babel/plugin-proposal-class-properties","@babel/plugin-transform-modules-commonjs",

      "istanbul",["import",{"libraryName":"antd","style":"css"}]]

  }

到此,配置全部完成

最終的package新增依賴:

    "@babel/core": "^7.12.3",

    "@babel/plugin-proposal-class-properties": "^7.12.1",

    "@babel/plugin-transform-modules-commonjs": "^7.12.1",

    "@babel/plugin-transform-runtime": "^7.12.1",

    "@babel/cli": "7.7.7",

    "babel-loader": "8.1.0",

    "babel-plugin-istanbul": "6.0.0",

    "@babel/preset-env": "7.7.7",

    "@babel/preset-react": "7.8.0"

.babelrc配置:

{

    "presets": ["@babel/react"],

    "plugins": ["@babel/plugin-proposal-class-properties","@babel/plugin-transform-modules-commonjs",

      "istanbul",["import",{"libraryName":"antd","style":"css"}]]

  }

webpack配置:

config.module.rules.push({

            test: /\.(js|jsx)$/,

            exclude: /node_modules/,

            use: [{

              loader: 'babel-loader'

            }]

          });

啟動成功後,可以看到能夠擷取到window.__coverage__

React前端功能測試覆寫率統計-插樁

看source可以看到是查妝後的代碼:

React前端功能測試覆寫率統計-插樁

完成

遇到的問題:

1.添加依賴修改配置後,前端插樁成功,但是編譯失敗,報錯,講webpack配置

config.module.rules.push({

            test: /\.(js|jsx)$/,

            exclude: /node_modules/,

            use: [{

              loader: 'babel-loader'

            }]

          });

改為

config.module.rules.unshift({

            test: /\.(js|jsx)$/,

            exclude: /node_modules/,

            use: [{

              loader: 'babel-loader'

            }]

          });

也就是将babel-loader排在第一位,問題解決,可能原因是依賴中有添加loader的,導緻插樁後代碼出錯

2.關于babel的依賴問題,在babel6和babel7中,版本存在很大的差別

是以在babel6中,我們需要依賴6的一些包:

"babel-core": "6.26.3",

 "babel-plugin-import": "1.11.0",

"babel-preset-env": "1.7.0",

    "babel-preset-react": "6.24.1",

    "babel-cli": "6.26.0",

    "babel-loader": "6.4.0",

    "babel-plugin-istanbul": "5.0.0"

babel7移除了stage,是以在babel7中完全就不需要stage了

推薦幾篇相關的文章:

React Native 代碼覆寫率擷取探索 (二):https://testerhome.com/topics/8919

前端精準測試探索:覆寫率實時統計工具:https://www.infoq.cn/article/UPfOuyQIkVr6708DNV4V

聊聊前端代碼覆寫率 (長文慎入):https://testerhome.com/topics/24122

Vue 應用的代碼覆寫率:https://my.oschina.net/u/4592325/blog/4554268