Karma-and-React

1. 目的

使用Karma来测试React编写的应用

2. 安装环境

使用的依赖如下:

babel-core
babel-loader
babel-preset-es2015
babel-preset-react
expect
jasmine
karma
karma-chrome-launcher
// karma-firefox-launcher 如果您使用Firefox来测试,应当安装上它
karma-cli
karma-jasmine
karma-sourcemap-loader
karma-webpack
react
react-addons-test-utils
react-dom
requirejs
webpack

使用npm install命令来安装它们。

在文章最后,我们的项目文件大概是这个样子:

├── karma.conf.js
├── package.json
├── src
│   ├── __tests__
│   │   └── index.test.js
│   ├── components
│   │   ├── __tests__
│   │   │   └── app.test.js
│   │   └── app.comp.jsx
│   └── index.jsx
└── test-main.js

3. 完善karma配置

使用karma init karma.conf.js来引导我们建立配置。

以下是我的选择

Which testing framework do you want to use ?
Press tab to list possible options. Enter to move to the next question.
> jasmine

Do you want to use Require.js ?
This will add Require.js plugin.
Press tab to list possible options. Enter to move to the next question.
> no

Do you want to capture any browsers automatically ?
Press tab to list possible options. Enter empty string to move to the next question.
> Chrome
>

What is the location of your source and test files ?
You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js".
Enter empty string to move to the next question.
> src/*.jsx
>

Should any of the files included by the previous patterns be excluded ?
You can use glob patterns, eg. "**/*.swp".
Enter empty string to move to the next question.
>

Do you want Karma to watch all the files and run the tests on change ?
Press tab to list possible options.
> yes

接下来编辑karma.conf.js,来补充webpack, 添加测试文件等, 主要改动如下:

module.exports = function(config) {
  config.set({
  ...
    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],


    // list of files / patterns to load in the browser
    files: [
       'test-main.js'
    ],

    ...
    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
        'test-main.js': [ 'webpack', 'sourcemap' ]
    },

    webpack: {
        devtool: 'inline-source-map',
        module: {
            loaders: [
                { test: /\.js$/, loader: 'babel-loader?presets[]=react,presets[]=es2015'},
                { test: /\.jsx$/, loader: 'babel-loader?presets[]=react,presets[]=es2015'}
            ]
        }
    },

    webpackServer: {
        noInfo: true
    }
  })
}

注意到files和preprocessors中都提及了test-main.js这个文件,这是一个我们自定义增加的文件,我们用它来选择含有测试代码的文件。

在项目目录中添加完成文件后(我将其放在项目根目录下,如果您放在其他路径,请对应上相应的路径),修改其内容如下:

var context = require.context('./src', true, /(spec|test)\.js$/i);
context.keys().forEach(context);

这里利用了webpack的require.context功能来包括需要的测试文件,第一行中的正则表明这些文件是以spec.js或test.js结尾的, 且对大小写不敏感。

4. 添加测试文件

添加几个React文件以及测试,尽快来尝试功能吧!

添加的几个文件放在src中,目录结构可能是这个样子:

src
├── __tests__
│   └── index.test.js
├── components
│   ├── __tests__
│   │   └── app.test.js
│   └── app.comp.jsx
└── index.jsx

接着一堆代码黏贴:

index.test.js

describe("index.jsx", function(){
    it("renders without problems", function(){
        require("../index.jsx");
    })
})

index.jsx

import React from "react"
import ReactDOM from "react-dom"
import App from "./components/app.comp.jsx"

let root = document.createElement("div")
document.body.appendChild(root)

ReactDOM.render(
    <h1> Hi </h1>,
    root
);

app.comp.jsx

import React from "react"

export default class App extends React.Component{
    constructor(props){
        super(props)
    }

    getNumber(){
        return 3
    }

    render(){
        return (
            <div>
                <h1>Hi, Karma</h1>
                <h1>Hi, React</h1>
            </div>
        )
    }
}

app.test.js

import React from 'react'
import TestUtils from 'react-addons-test-utils'
import expect from 'expect'
import App from '../app.comp.jsx'

describe('app.comp.jsx', function () {
    var app = TestUtils.renderIntoDocument(<App />)

    it('renders without problems', function () {
        expect(app).toExist()
    });

    it("getNumber function works", function(){
        expect(app.getNumber()).toEqual(3)
    })
});

5. 开始测试

在终端中输入 karma startkarma start karma.conf.js, 如图所示,

测试全都正确,Great.

app.test.js中的toEqual(3)改成toEqual(4), 报错, 很好.


整个项目的示例,您可以在这里下载到。

另外水平有限,如有错误,欢迎指正.