Mocha 渐进式学习(二)- 实战DEMO:ts+webpack+mocha搭建

1,220 阅读6分钟

第一部分中介绍了mocha的一些基本知识和断言库的简单使用, 在本文中我会搭建一个简单的示意性的demo,来看看如何在工程中使用mocha。

mocha+typescript+webpack 简单示例

项目的代码:github.com/997282173/m…

首先初始化项目目录, 随意选择一个空文件夹运行npm init -y, 得到一个默认的 package.json.

然后安装相应的 webpacktypescript:

npm install webpack webpack-cli typescript ts-lint ts-loader --sace-dev

然后在项目目录下创建webpack.config.js文以及src文件夹, webpack 配置内容如下:

const webpack = require('webpack');
const path = require('path');

module.exports = {
    entry: path.resolve(__dirname, './src/index.ts'),
    // devtool: 'inline-source-map',
    output: {
        filename: 'dist.js',
        path: path.resolve(__dirname, './dist')
    },
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                use: 'ts-loader',
                exclude: /node_modules/
            }
        ]
    },
    resolve: {
        extensions: ['.tsx', '.ts', '.js']
    }
};

根目录创建tslint.json:

{
    "rules": {
        "no-console": false,
        "indent": [true, "spaces", 2],
        "no-consecutive-blank-lines": [true, 2],
        "align": [true, "parameters", "statements"]
    },
    "linterOptions": {
        "exclude": ["config/**/*.js", "node_modules/**"]
    }
}

根目录创建tsconfig.json:

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es5",
        "noImplicitAny": true,
        "sourceMap": true
    }
}

在 src 下面写一个index.ts, 内容不限, 在同文件夹下创建example.ts文件夹, 写一个测试函数:

export function add(x: number, y: number) {
    return x + y;
}

package.json文件夹中, 写入运行脚本:

"scripts": {
    "build": "webpack --mode production",
},

在命令行中运行:npm run build, 看看 webpack 和 typescript 是否配置完成.

继续下一步, 添加mocha需要的相关依赖:

npm install chai mocha nyc ts-node @types/chai @types/mocha --save-dev

新建test文件夹, 创建配置文件mocha.opts:

-r ts-node/register
test/**/*.spec.ts
--colors

在 test 下创建测试文件example.spec.ts

import { describe, it } from 'mocha';
import { expect } from 'chai';

import * as sampleIndex from '../src/sampleIndex';

describe('add function test', () => {
    it('should return 5 when 2 + 3', () => {
        expect(sampleIndex.add(2, 3)).to.be.equal(5);
    });
});

添加运行命令:

"test": "nyc mocha"

至此, 我们的 mocha 就配置完成了, 运行npm run test, 可以看到 mocha 的运行输出:

> mochatest@1.0.0 test /Users/mochaTest
> nyc mocha



  add function test
    ✓ should return 5 when 2 + 3


  1 passing (5ms)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |        0 |        0 |        0 |        0 |                   |
----------|----------|----------|----------|----------|-------------------|

一个简单的 webpack+typescript+mocha 的应用框架就可以运行了, 但是还有一些问题没有解决:

  • 浏览器测试
  • react 如何进行测试
  • 网络环境下测试
  • 测试结果报告

本文中我们先来解决第一个浏览器测试的问题。

浏览器测试

刚才我们的示例中, 是在 node 环境中运行的测试, 也就是没有浏览器提供的对象, 但显然这是不行的.

不过, mocha是支持浏览器测试的, 运行命令mocha init test_browser, mocha会在根目录下的test_browser生成一些文件:

  • index.html: 入口页面
  • test.js: 测试代码
  • mocha.css: 测试页面 样式
  • mocha.js: mocha 源码

其中比较重要的是index.html文件, 内容如下:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>Mocha</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <link rel="stylesheet" href="mocha.css" />
    </head>
    <body>
        <div id="mocha"></div>
        <script src="mocha.js"></script>
        <script>
            mocha.setup('bdd');
        </script>
        <script src="tests.js"></script>
        <script>
            mocha.run();
        </script>
    </body>
</html>

mocha.run()表示运行测试, 所以tests.js中应该存放我们的测试代码.

但是按照原本的逻辑, 我们需要在test.js中重新编写我们的代码, node 端的测试无法和浏览器端共享, 所以接下来就要做一点小小的改动来似的两个环境下使用同一套测试代码(也可以配置成两套,主要参考你的系统).

首先我们创建一个public文件夹, 并且配置copywebpackplugin插件:

const CopyWebpackPlugin = require('copy-webpack-plugin');

//plugin
new CopyWebpackPlugin([
    {
        from: path.resolve(__dirname, '../public'),
        to: path.resolve(__dirname, '../dist')
    }
]);

然后将test_browser中的mocha.jsmocha.css移动到public下的lib/mocha_browser.

test_browser移动到项目根目录,重命名为test.html, 修改为以下内容:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>Mocha</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <link rel="stylesheet" href="../lib/mocha_browser/mocha.min.css" />
        <script src="../lib/mocha_browser/mocha.min.js"></script>
        <script>
            mocha.setup('bdd');
        </script>
    </head>
    <body>
        <div id="mocha"></div>
        <script>
            mocha.run();
        </script>
    </body>
</html>

这里我额外的对 js 和 css 文件进行了压缩, 需要注意文件名称.

最后一部分就是在 webpack 中进行多入口配置:

  1. 动态入口:
entry: () => {
    return new Promise(resolve => {
        let files = fs.readdirSync(path.resolve(__dirname, '../test'));

        files = files
            .map(name => {
                if (name !== 'mocha.opts') {
                    return path.basename(name, '.ts');
                }
            })
            .filter(name => {
                return !!name;
            });

        let entries = {
            index: path.resolve(__dirname, '../src/index.ts')
        };

        for (let i = 0; i < files.length; i++) {
            const file = files[i];
            entries['test/' + file] = path.resolve(__dirname, '../test', file);
        }

        resolve(entries);
    });
};
  1. 输出文件名称:
output: {
    filename: '[name].js',
    path: path.resolve(__dirname, '../dist')
},
  1. htmlplugin:
new HtmlWebpackPlugin({
    title: 'Mocha demo',
    template: './index.html',
    filename: 'index.html',
    chunks: ['index']
}),
new HtmlWebpackPlugin({
    title: 'Mocha demo Test',
    filename: 'test/test.html',
    template: './test.html',
    inject: 'head',
    excludeChunks: ['index']
}),
  1. node 和 performance:
performance: {
    hints: 'warning', // 枚举
    maxAssetSize: 30000000, // 整数类型(以字节为单位)
    maxEntrypointSize: 50000000 // 整数类型(以字节为单位)
},
node: {
    fs: 'empty'
},

最后在index.html文件中添加入口, 就可以看到浏览器测试了:

<a href="./test/test.html">运行测试</a>

启动npm:npm run dev:

然后点击运行测试:

进一步的, 我们使用无头浏览器在在命令行下运行浏览器测试:

首先需要在test.html中添加一行:

<script>
    //添加这一行, 注意要先判断, 否则你的网页端就会报错
    window.initMochaPhantomJS && window.initMochaPhantomJS();
    mocha.setup('bdd');
</script>

在本地安装:

sudo cnpm install --save-dev phantomjs-prebuilt mocha-phantomjs

在 npm 中添加命令:

 "test:browser": "npm run build && mocha-phantomjs --path ./node_modules/.bin/phantomjs ./dist/test/test.html "

注意, 这里我在进行浏览器测试的时候, 先运行了打包命令, 因为我的测试文件指向 dist 目录下编译完成的test.html文件, 所以需要先进行打包.
所以你在运行这个命令的时候会先看到打包输出:


Hash: ccd15746fa6c8d716cd2
Version: webpack 4.40.2
Time: 2083ms
Built at: 2019-09-23 11:12:56
                          Asset       Size  Chunks                   Chunk Names
                     index.html  428 bytes          [emitted]
                       index.js   1.15 KiB       0  [emitted]        index
                   index.js.map   4.89 KiB       0  [emitted] [dev]  index
lib/mocha_browser/mocha.min.css   4.21 KiB          [emitted]
 lib/mocha_browser/mocha.min.js    245 KiB          [emitted]
       test/sampleIndex.spec.js   68.9 KiB       1  [emitted]        test/sampleIndex.spec
   test/sampleIndex.spec.js.map   79.1 KiB       1  [emitted] [dev]  test/sampleIndex.spec
                 test/test.html  645 bytes          [emitted]
Entrypoint index = index.js index.js.map
Entrypoint test/sampleIndex.spec = test/sampleIndex.spec.js test/sampleIndex.spec.js.map
 [7] ./src/sampleIndex.ts 137 bytes {0} {1} [built]
[16] ./src/index.ts 208 bytes {0} [built]
[17] ./test/sampleIndex.spec.ts 324 bytes {1} [built]
[22] (webpack)/buildin/global.js 472 bytes {1} [built]
    + 38 hidden modules
Child html-webpack-plugin for "index.html":
     1 asset
    Entrypoint undefined = index.html
    [0] ./node_modules/_html-webpack-plugin@3.2.0@html-webpack-plugin/lib/loader.js!./index.html 603 bytes {0} [built]
    [2] (webpack)/buildin/global.js 472 bytes {0} [built]
    [3] (webpack)/buildin/module.js 497 bytes {0} [built]
        + 1 hidden module
Child html-webpack-plugin for "test/test.html":
     1 asset
    Entrypoint undefined = test/test.html
    [0] ./node_modules/_html-webpack-plugin@3.2.0@html-webpack-plugin/lib/loader.js!./test.html 802 bytes {0} [built]
    [2] (webpack)/buildin/global.js 472 bytes {0} [built]
    [3] (webpack)/buildin/module.js 497 bytes {0} [built]
        + 1 hidden module


  add function test
    ✓ should return 5 when 2 + 3


  1 passing (5ms)

至此, 我们的浏览器测试就搭建完成了,具体的逻辑其实可以根据你的实际需求来进行修改,比如不用webpack的打包过程而使用tsc来转译ts单测文件,从而跳过打包这一步直接进行浏览器打包等。 前端工具的组合搭配是非常灵活的,你可以借助各种工具搭建出你需要的任何前端工程流。

下面还有一篇文章, 我会介绍如何使用enzym,sion

本人也刚开始接触单测,所以有了这几篇文章来记录我的学习过程,如果有哪里不对的地方,希望大佬们不吝指点。