也能夠在這裏看:https://leozdgao.me/modern-karma/前端
以前寫過的測試都是針對簡單的工具方法,用的 mocha + chai 寫,最近在研究前端路由,想寫寫測試代碼,遇到 window.location
,忽然意識到先後端的差別問題,須要一個瀏覽器環境,因而想到以前用過的 Karma + phamtonjs 環境,搭的過程當中遇到一些坑,由於涉及到了 Babel 和 commonjs 模塊系統,因而這裏記錄分享下。node
因爲 Karma 只是一個 Test Runner,我們的測試框架和斷言庫仍是須要的,因而先裝這些東西:webpack
> npm install --save-dev karma karma-mocha karma-chai
對於 npm 版本 >=3.0 的話,這幾個 peerDependencies:web
> npm install --save-dev mocha chai
這些裝完後,利用 karma-cli 來初始化一份配置文件:shell
> ./node_modules/.bin/karma init
按照提示填寫配置便可,完成後生成一份 karma.config.js
,把裏面 singleRun 設成 false,結束。npm
接下來給 Karma 準備 Browsers 了,我這裏選擇 PhantomJS(在上面初始化 Karma 配置的時候就能夠選了),不過這東西的安裝過程是真的糾結:後端
> npm install --save-dev karma-phantomjs-launcher phantomjs-prebuilt
在安裝的過程當中,發現 PhantomJS 須要從 https://bitbucket.org/ariya/phantomjs/downloads/
下載,速度很是慢,反正我是沒有成功下載下來過。好在有淘寶鏡像,哈哈,太棒了!cnode 帖子的連接在這裏。瀏覽器
> PHANTOMJS_CDNURL=https://npm.taobao.org/dist/phantomjs npm install phantomjs-prebuilt --registry=https://registry.npm.taobao.org --no-proxy
而後貼出一部分配置:babel
module.exports = function (config) { config.set({ basePath: './', frameworks: [ 'mocha', 'chai' ], files: [ 'src/**/*.js', 'test/**/*.js' ], plugins: [ 'karma-mocha', 'karma-chai', 'karma-mocha-reporter', 'karma-phantomjs-launcher' ], reporters: [ 'mocha' ], port: 9876, colors: true, logLevel: config.LOG_INFO, autoWatch: false, browsers: [ 'PhantomJS' ], singleRun: true, concurrency: Infinity }) }
這些順利安裝完後,而且你的配置文件正確配置的狀況下,理應是能夠跑了,然而我如今的工做流已經深度依賴於 Babel + commonjs 模塊系統,因此若是你和我同樣的話,那麼咱們的環境還沒搭好。框架
這邊我用的 Babel 版本是 v6.0+,根據 Babel 官網 說的:
> npm install --save-dev karma-babel-preprocessor
並在配置裏添加預處理配置:
plugins: [ ... 'karma-babel-preprocessor', ... ], preprocessors: { "src/**/*.js": [ "babel" ], "test/**/*.js": [ "babel" ] },
然而即使是這樣也仍是不行,考慮到 Babel 是將 ES6 的模塊系統轉換爲 commonjs 的模塊系統,而 Karma 是直接把匹配到的腳本放在瀏覽器環境裏跑的,瀏覽器環境裏確定沒有 require
、module.exports
這種東西,因此在看了幾個例子以後,發現還須要 karma-commonjs
這個東西。
> npm install --save-dev karma-commonjs
完整的配置文件以下:
module.exports = function(config) { config.set({ basePath: './', frameworks: [ 'mocha', 'chai', 'commonjs' ], files: [ 'src/**/*.js', 'test/**/*.js' ], exclude: [ ], preprocessors: { 'src/**/*.js': [ 'babel', 'commonjs' ], 'test/**/*.js': [ 'babel', 'commonjs' ] }, plugins: [ 'karma-mocha', 'karma-chai', 'karma-mocha-reporter', 'karma-commonjs', 'karma-babel-preprocessor', 'karma-phantomjs-launcher' ], reporters: [ 'mocha' ], port: 9876, colors: true, logLevel: config.LOG_INFO, autoWatch: false, browsers: [ 'PhantomJS' ], singleRun: true, concurrency: Infinity }) }
好了,如今只須要在 npm scripts 里加上一條:
scripts: { test: 'karma start' }
上面的 karma-commonjs
有個問題,它只能加載配置裏 files
選項匹配的模塊,這一點很不方便,因而想到 webpack 是否能夠和 karma 協同工做,果真是有的,因而找我最終使用了這個方式。
> npm install --save-dev karma-webpack
karma-webpack 提供了兩種方式加載測試文件,配置以下:
files: [ 'test/*_test.js', 'test/**/*_test.js' ], preprocessors: { 'test/*_test.js': ['webpack'], 'test/**/*_test.js': ['webpack'] }, webpack: { module: { loaders: [ { test: /\.js$/, exclude: /node_modules/, loader: 'babel' } ] }, plugins: [ new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('test') }) ] }
此時,被加入 files 配置匹配的文件都被認爲是入口點(entry),並加上 webpack 的預處理配置便可(有了 webpack 結合 commonjs 的模塊系統,就不須要手動加入項目源碼了,僅引入測試代碼就行)。不過下面這種方式更加簡單,只須要一個文件:
// tests.webpack.js // require all modules ending in ".spec.js" from the // current directory and all subdirectories var testsContext = require.context("./test", true, /\.spec\.js$/) testsContext.keys().forEach(testsContext)
本質上就是把全部匹配到的文件都 require 一遍,好比我上面就把全部 test 文件夾下的 .spec.js
結尾的文件都跑了一遍,Karma 的配置也稍微精簡了點。
files: [ 'tests.webpack.js' ], preprocessors: { 'tests.webpack.js': [ 'webpack' ] }, webpack: { module: { loaders: [ { test: /\.js$/, exclude: /node_modules/, loader: 'babel' } ] }, plugins: [ new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('test') }) ] }
項目若是比較大,代碼量較多的時候,webpack 打包會比較慢(對於打開 watch 選項的同窗,可能會比較崩潰),你們本身取捨吧。
大功告成,這裏推薦你們寫個 yo generator 來減小重複工做,以前寫過 一篇文章 來介紹。
好了,結束,水文一篇,不過仍是但願對你們有幫助。 :)