百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 优雅编程 > 正文

一步一步实现现代前端单元测试(前端单元测试到底测什么)

sinye56 2024-10-25 16:22 12 浏览 0 评论

今天我们一步一步把各种不同的技术结合一起来完成页面的单元测试和 e2e 测试。

1 karma + mocha + power assert

karma是一款测试流程管理工具,包含在执行测试前进行一些动作,自动在指定的环境(可以是真实浏览器,也可以是PhantamJS 等 headless browser)下运行测试代码等功能。mocha测试框架,类似的有 jasmine 和 jest 等。个人感觉 mocha 对异步的支持和反馈信息的显示都非常不错。power asser断言库,特点是 No API is the best API。错误显示异常清晰,自带完整的自描述性。

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

以下所有命令假设在 test-demo 项目下进行操作。

1.1 安装依赖及初始化

# 为了操作方便在全局安装命令行支持
~/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

执行初始化过程按照提示进行选择和输入

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

生成的配置文件略作修改,如下(因篇幅原因,隐藏了注释):

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 待测试代码

我们把源文件放在src目录下。

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

1.3 测试代码

测试代码放在test/specs目录下,每个测试文件以 .spec.js 作为后缀。

// 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 运行测试

回到项目根目录,运行命令 npm run test 开始执行测试,然后看到浏览器会自动打开执行测试,命令行输出结果如下:

[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

可以看出一个测试成功一个测试失败。

2 测试覆盖率(test coverage)

测试覆盖率是衡量测试质量的主要标准之一,含义是当前测试对于源代码的执行覆盖程度。在 karma 中使用 karma-coverage 插件即可输出测试覆盖率,插件底层使用的是 istanbul。

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

修改 karma.conf.js 文件:

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' }
  ]
},

再次运行测试命令,在最后会输出测试覆盖率信息

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

打开 test/coverage/lcov-report/index.html 网页可以看到详细数据

3 webpack + babel

上面的例子,只能用于测试使用传统方式编写的 js 文件。为了模块化组件化,我们可能会使用ES6、commonjs、AMD等模块化方案,然后使用 webpack 的 umd 打包方式输出模块以兼容不同的使用方式。一般我们还需要使用ES6+的新语法,需要在 webpack 中加入babel作为转译插件。

webpack 和 babel 的使用以及需要的依赖和配置,这里不做详细说明,因为主要是按照项目需要走,本文仅指出为了测试而需要修改的地方

3.1 安装依赖

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

3.2 修改配置

.babelrc

把power-assert以及coverage的代码注入修改为在babel编译阶段进行,在.babelrc 文件中加入以下配置:

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

test/index.js

在测试文件以及源码文件都非常多的情况下,或者我们想让我们的测试代码也使用上ES6+的语法和功能,我们可以建立一个入口来统一引入这些文件,然后使用 webpack 处理整个入口,在test目录下新建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修改已经增加对应的配置

{
  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 运行测试

运行测试,能得到和第二步相同的结果。

4 vue

如果项目中使用了 vue,我们想对封装的组件进行测试,也非常简单。

首先 webpack 配置中添加处理 vue 的逻辑,安装需要的依赖,这里不再赘述。

在src目录下添加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>

然后添加测试代码:

// 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')
  })

})

运行测试,可以看到命令行输出:

 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

这里 Vue 能替换为其他任意的前端框架,只需要按照对应框架的配置能正确打包即可。

结语

以上大概讲解了现代前端测试的方法和过程,但是有人会问,我们为什么需要搞那么多事情,写那么多代码甚至测试代码比真实代码还要多呢?这里引用 Egg 官方一段话回答这个问题:

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

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

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

是不是消除了很多心中的疑惑?

以上内容如有错漏,或者有其他看法,请留言共同探讨。

以上内容就是本篇的全部内容以上内容希望对你有帮助,如果对接口、性能、自动化测试、面试经验交流等感兴趣的,可以关注我的头条号,我会不定期的发放免费的资料,这些资料都是从各个技术网站搜集、整理出来的,如果你有好的学习资料可以私聊发我,我会注明出处之后分享给大家。欢迎分享,欢迎评论,欢迎转发。需要资料的同学可以关注小编+转发文章+私信【测试资料】

相关推荐

程序员:JDK的安装与配置(完整版)_jdk的安装方法

对于Java程序员来说,jdk是必不陌生的一个词。但怎么安装配置jdk,对新手来说确实头疼的一件事情。我这里以jdk10为例,详细的说明讲解了jdk的安装和配置,如果有不明白的小伙伴可以评论区留言哦下...

Linux中安装jdk并配置环境变量_linux jdk安装教程及环境变量配置

一、通过连接工具登录到Linux(我这里使用的Centos7.6版本)服务器连接工具有很多我就不一一介绍了今天使用比较常用的XShell工具登录成功如下:二、上传jdk安装包到Linux服务器jdk...

麒麟系统安装JAVA JDK教程_麒麟系统配置jdk

检查检查系统是否自带java在麒麟系统桌面空白处,右键“在终端打开”,打开shell对话框输入:java–version查看是否自带java及版本如图所示,系统自带OpenJDK,要先卸载自带JDK...

学习笔记-Linux JDK - 安装&amp;配置

前提条件#检查是否存在JDKrpm-qa|grepjava#删除现存JDKyum-yremovejava*安装OracleJDK不分系统#进入安装文件目...

Linux新手入门系列:Linux下jdk安装配置

本系列文章是把作者刚接触和学习Linux时候的实操记录分享出来,内容主要包括Linux入门的一些理论概念知识、Web程序、mysql数据库的简单安装部署,希望能够帮到一些初学者,少走一些弯路。注意:L...

测试员必备:Linux下安装JDK 1.8你必须知道的那些事

1.简介在Oracle收购Sun后,Java的一系列产品就被整合到Oracle官网中,打开官网乍眼一看也不知道去哪里下载,还得一个一个的摸索尝试,而且网上大多数都是一些Oracle收购Sun前,或者就...

Linux 下安装JDK17_linux 安装jdk1.8 yum

一、安装环境操作系统:JDK版本:17二、安装步骤第一步:下载安装包下载Linux环境下的jdk1.8,请去官网(https://www.oracle.com/java/technologies/do...

在Ubuntu系统中安装JDK 17并配置环境变量教程

在Ubuntu系统上安装JDK17并配置环境变量是Java开发环境搭建的重要步骤。JDK17是Oracle提供的长期支持版本,广泛用于开发Java应用程序。以下是详细的步骤,帮助你在Ubuntu系...

如何在 Linux 上安装 Java_linux安装java的步骤

在桌面上拥抱Java应用程序,然后在所有桌面上运行它们。--SethKenlon(作者)无论你运行的是哪种操作系统,通常都有几种安装应用程序的方法。有时你可能会在应用程序商店中找到一个应用程序...

Windows和Linux环境下的JDK安装教程

JavaDevelopmentKit(简称JDK),是Java开发的核心工具包,提供了Java应用程序的编译、运行和开发所需的各类工具和类库。它包括了JRE(JavaRuntimeEnviro...

linux安装jdk_linux安装jdk软连接

JDK是啥就不用多介绍了哈,外行的人也不会进来看我的博文。依然记得读大学那会,第一次实验课就是在机房安装jdk,编写HelloWorld程序。时光飞逝啊,一下过了十多年了,挣了不少钱,买了跑车,娶了富...

linux安装jdk,全局配置,不同用户不同jdk

jdk1.8安装包链接:https://pan.baidu.com/s/14qBrh6ZpLK04QS8ogCepwg提取码:09zs上传文件解压tar-zxvfjdk-8u152-linux-...

运维大神教你在linux下安装jdk8_linux安装jdk1.7

1.到官网下载适合自己机器的版本。楼主下载的是jdk-8u66-linux-i586.tar.gzhttp://www.oracle.com/technetwork/java/javase/downl...

window和linux安装JDK1.8_linux 安装jdk1.8.tar

Windows安装JDK1.8的步骤:步骤1:下载JDK打开浏览器,找到JDK下载页面https://d.injdk.cn/download/oraclejdk/8在页面中找到并点击“下载...

最全的linux下安装JavaJDK的教程(图文详解)不会安装你来打我?

默认已经有了linux服务器,且有root账号首先检查一下是否已经安装过java的jdk任意位置输入命令:whichjava像我这个已经安装过了,就会提示在哪个位置,你的肯定是找不到。一般我们在...

取消回复欢迎 发表评论: