Implement modern front-end unit testing step by step

Today we are step by step to combine a variety of different technologies to complete page unit testing and e2e testing.

1 karma + mocha + power assert

Karma is a test process management tool , including some actions before the execution of the test, automatically running the test code in a specified environment (can be a real browser, or a headless browser such as PhantamJS).
Mocha testing framework, similar to jasmine and jest . Personally, I feel that mocha's asynchronous support and display of feedback information are very good.
The power asser assertion library is characterized by No API is the best API. The error display is very clear and comes with complete self-description.

```
1) Array #indexOf() should return index when the value is present:
   AssertionError: # path/to/test/mocha_node.js:10

assert(ary.indexOf(zero) === two)
       |   |       |     |   |
       |   |       |     |   2
       |   -1      0     false
       [1,2,3]

[number] two
=> 2
[number] ary.indexOf(zero)
=> -1
```

All the following commands are assumed to be operated under the test-demo project.

1.1 Installation dependencies and initialization

# 为了操作方便在全局安装命令行支持
~/test-demo $ npm install karma-cli -g

# 安装 karma 包以及其他需要的插件和库,这里不一一阐述每个库的作用
~/test-demo $ npm install karma mocha power-assert karma-chrome-launcher karma-mocha karma-power-assert karma-spec-reporter karma-espower-preprocessor cross-env -D

# 创建测试目录
~/test-demo $ mkdir test

# 初始化 karma
~/test-demo $ karma init ./test/karma.conf.js

Perform the initialization process and follow the prompts to select and enter

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

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.
>

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.
> no

The generated configuration file is slightly modified as follows (due to space reasons, comments are hidden):

module.exports = function(config) {
  config.set({
    basePath: '',

    // 表示可以在测试文件中不需引入即可使用两个库的全局方法
    frameworks: ['mocha', 'power-assert'],
    files: [
      '../src/utils.js',
      './specs/utils.spec.js.js'
    ],
    exclude: [
    ],
    preprocessors: {
      './specs/utils.spec.js': ['espower']
    },
    reporters: ['spec'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: false,
    browsers: ['Chrome'],
    singleRun: false,
    concurrency: Infinity
  })
}

1.2 Code to be tested

We put the source files in the srcdirectory.

// src/utils.js
function reverseString(string) {
  return string.split('').reverse().join('');
}

1.3 Test code

Test code in the test/specsdirectory, each test file .spec.jsas a suffix.

// test/spes/utils.spec.js
describe('first test', function() {
  it('test string reverse => true', function() {
    assert(reverseString('abc') === 'cba');
  });

  it('test string reverse => false', function() {
    assert(reverseString('abc') === 'cba1');
  });
});

1.4 Run test

Back to the project root directory, run the command npm run testto start performing the test, and then see the browser will automatically open test is performed, the command output results are as follows:

[karma]: Karma v2.0.0 server started at http://0.0.0.0:9876/
[launcher]: Launching browser Chrome with unlimited concurrency
[launcher]: Starting browser Chrome
[Chrome 63.0.3239 (Mac OS X 10.13.1)]: Connected on socket HEw50fXV-d24BZGBAAAA with id 24095855

  first test
    ✓ test string reverse => true
    ✗ test string reverse => false
	AssertionError:   # utils.spec.js:9

	  assert(reverseString('abc') === 'cba1')
	         |                    |
	         "cba"                false

	  --- [string] 'cba1'
	  +++ [string] reverseString('abc')
	  @@ -1,4 +1,3 @@
	   cba
	  -1

Chrome 63.0.3239 (Mac OS X 10.13.1): Executed 2 of 2 (1 FAILED) (0.022 secs / 0.014 secs)
TOTAL: 1 FAILED, 1 SUCCESS

It can be seen that one test succeeds and one test fails.

2 test coverage (test coverage)

Test coverage is one of the main criteria for measuring test quality, which means the current test coverage of source code execution. In the karmause of karma-coverageplug-ins can output test coverage, the bottom plug is used istanbul.

~/test-demo $ npm i karma-coverage -D

Modify the karma.conf.jsfile:

preprocessors: {
  '../src/utils.js': ['coverage'],
  './specs/utils.spec.js': ['espower']
},

reporters: ['spec', 'coverage'],
coverageReporter: {
  dir: './coverage', // 覆盖率结果文件放在 test/coverage 文件夹中
  reporters: [
    { type: 'lcov', subdir: '.' },
    { type: 'text-summary' }
  ]
},

Run the test command again, and the test coverage information will be output at the end

=============================== Coverage summary ===============================
Statements   : 100% ( 2/2 )
Branches     : 100% ( 0/0 )
Functions    : 100% ( 1/1 )
Lines        : 100% ( 2/2 )
================================================================================

Open the test/coverage/lcov-report/index.htmlWeb page you can see detailed data

3 webpack + babel

The above example can only be used to test js files written in traditional ways. To modular and component-based , we may use the ES6, commonjs, AMDand other modular program, then use the umd webpack output modules are packaged to be compatible with different ways. Generally ES6+, the new syntax we need to use needs to be added babelas a translation plugin in webpack .

The use of webpack and babel and the required dependencies and configuration are not described in detail here, because they are mainly based on the needs of the project. This article only points out the places that need to be modified for testing .

3.1 Installation dependencies

~/test-demo $ npm i babel-plugin-istanbul babel-preset-power-assert karma-sourcemap-loader karma-webpack -D

3.2 Modify configuration

.babelrc

Modify the power-assertand coveragecode injection to be performed during the babelcompilation phase, .babelrcand add the following configuration to the file:

{
  "env": {
    "test": {
      "presets": ["env", "babel-preset-power-assert"],
      "plugins": ["istanbul"]
    }
  }
}

test/index.js

In the case that there are many test files and source code files, or we want our test code to use the above ES6+syntax and functions, we can create an entry to import these files uniformly, and then use webpack to process the entire entry, in the testdirectory New index.js:

// require all test files (files that ends with .spec.js)
const testsContext = require.context('./specs', true, /\.spec$/)
testsContext.keys().forEach(testsContext)

// require all src files except main.js for coverage.
// you can also change this to match only the subset of files that
// you want coverage for.
const srcContext = require.context('../src', true, /^\.\/(?!main(\.js)?$)/)
srcContext.keys().forEach(srcContext)

** karma.conf.js**The modification has added the corresponding configuration

{
  files: [
    './index.js'
  ],
  preprocessors: {
    './index.js': ['webpack', 'sourcemap'],
  },
  webpack: webpackConfig,
  webpackMiddleware: {
    noInfo: false
  },
}

utils.spec.js

import reverseString from '../../src/utils';

describe('first test', function() {
  it('test string reverse => true', function() {
    assert(reverseString('abc') === 'cba');
  });

  it('test string reverse => false', function() {
    assert(reverseString('abc') === 'cba1');
  });
});

3.3 Run test

Run the test and get the same result as the second step.

4 view

If vue is used in the project, we want to test the packaged components, which is also very simple.

First, add the logic of processing vue to the webpack configuration and install the required dependencies, so I won't go into details here.

srcAdd in the directory HelloWorld.vue:

<template>
  <div class="hello">
    <h1>{
   
   { msg }}</h1>
    <h2>Essential Links</h2>

  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="scss" scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

Then add the test code:

// test/specs/vue.spec.js
import Vue from 'vue';
import HelloWorld from '@/HelloWorld';

describe('HelloWorld.vue', () => {
  it('should render correct contents', () => {
    const Constructor = Vue.extend(HelloWorld)
    const vm = new Constructor().$mount()
    assert(vm.$el.querySelector('.hello h1').textContent === 'Welcome to Your Vue.js App')
  })

})

Run the test, you can see the command line output:

 first test
    ✓ test string reverse => true
    ✗ test string reverse => false
        AssertionError:   # test/specs/utils.spec.js:9

          assert(reverseString('abc') === 'cba1')
                 |                    |
                 "cba"                false

          --- [string] 'cba1'
          +++ [string] reverseString('abc')
          @@ -1,4 +1,3 @@
           cba
          -1

  HelloWorld.vue
    ✓ should render correct contents

Here Vue can be replaced with any other front-end framework, as long as it can be packaged correctly according to the configuration of the corresponding framework.
If you exchange experience in software testing, interface testing, automated testing, and interviews. If you are interested, you can add software test communication: 1085991341, and there will be technical exchanges with colleagues.

Conclusion

The above probably explained the methods and processes of modern front-end testing, but some people may ask, why do we need to do so much, write so much code, or even test code more than real code? Here is an official passage from Egg to answer this question:

先问我们自己以下几个问题:
  - 你的代码质量如何度量?  
  - 你是如何保证代码质量?  
  - 你敢随时重构代码吗?  
  - 你是如何确保重构的代码依然保持正确性?  
  - 你是否有足够信心在没有测试的情况下随时发布你的代码?  

如果答案都比较犹豫,那么就证明我们非常需要单元测试。  
它能带给我们很多保障:  
  - 代码质量持续有保障  
  - 重构正确性保障  
  - 增强自信心  
  - 自动化运行   

Web 应用中的单元测试更加重要,在 Web 产品快速迭代的时期,每个测试用例都给应用的稳定性提供了一层保障。 API 升级,测试用例可以很好地检查代码是否向下兼容。 对于各种可能的输入,一旦测试覆盖,都能明确它的输出。 代码改动后,可以通过测试结果判断代码的改动是否影响已确定的结果。

Did you eliminate a lot of doubts in your mind?

If there are any errors or omissions in the above content, or have other opinions, please leave a message and discuss together.
The above content is the entire content of this article. The above content hopes to be helpful to you. Friends who have been helped are welcome to like and comment.

Guess you like

Origin blog.csdn.net/Chaqian/article/details/106689052