为什么需要前端自动化测试呢?

327次阅读  |  发布于3年以前

我们先来回顾几个公知问题

自动化测试就是面向这些问题而生的。

而接入前端自动化测试,可以帮助我们提前暴露bug并修复、降低bug产生的成本/提升测试的覆盖率,降低对其他功能原有逻辑的干扰。接下来我们进入正题,向大家介绍前端自动化测试

前端自动化测试的种类

共四类:

  1. 单元测试 单元测试是最基础的自动化测试,用来检测项目当中的最小可测单元,例如工具函数、基础组件等
  2. 集成测试 在单元测试的基础上,不同功能集成在一起,验证整体功能
  3. ui测试 并不是只对ui设计效果的验证,而是只对数据渲染、交互上的验证
  4. 端对端测试 相对真实、完整链路的模拟真实操作验证

在vue或react这种前端框架下,延伸出一种组件测试,根据组件的粒度,其实应该属于单元测试、或者集成测试的部分。

自动化测试金字塔

介绍完自动化测试的种类,我们来简单比较一下这四种测试

有下之上,测试用例的数量逐步减少、粒度变粗、验证的功能变多变复杂。

同时受需求变化的影响变大,重复利率降低

同时编写测试用例的时间变长 、执行的时间也响应变长

另一方面,由上至下,发先的bug数量逐渐变小。

所以,从发先bug数量/编写测试用例时间&重复利用率的纬度上讲,单元测试的收益最大,越向上收益越小。

这也是大部分项目中采用的自动化测试,是在单元测试这一层的原因。

满足自动化测试的条件

说了那么多,哪什么情况下,我们适合使用前端自动化测试呢?

这里我总结了一些情况,实际上只需要满足几点就可以了

  1. 任务测试明确,不会频繁变动
  2. 每日构建后的测试验证
  3. 比较频繁的回归测试
  4. 软件系统界面稳定,变动少
  5. 多平台上测试、组合遍历型的测试、大量的重复任务
  6. 软件维护周期长
  7. 项目进度压力不太大
  8. 开发比较规范,具有可测试性
  9. 具备大量的自动化测试平台
  10. 测试人员具备较强的编程能力

一些常见的测试工具

说了这么多,其实应用的最广泛的,收益相对来讲最高的还是单元测试

所以后面我将具体给大家讲一下,如何将单元测试融入到我们的开发当中

如何编写单元测试

我们是先开发,后补充单元测试呢?还是先编写单元测试再开发呢?

相信大多数第一次,接触这个问题的人可能都想我一样,觉得是先开发后补充

但是实际上应当是先编写单元测试,在开发代码。这种模式成为测试驱动开发(TDD)

很简单的道理,如果你写的代码逻辑有问题,那么按照错误逻辑写的单元测试,永远不可能验证出问题来。

我们应当围绕功能设计来编写我们的单元测试,测试内容对我们来讲就是一个黑盒,我们只需要验证他是否满足我们的设计预期就好了,而无关内部细节。只有这样,才能保证测试用例的稳定,支撑重构

测试驱动开发流程

  1. 快速新增一个测试
  2. 运行新增测试,发现新增的测试不能通过
  3. 分节点开发,一边开发一边验证,扩大测试通过范围运行
  4. 所有的测试,并且全部通过
  5. 重构代码,以消除重复设计,优化设计结构
  6. 再次验证,通过完成开发

单元测试步骤

  1. 准备(Arrange) 为测试做好设置。渲染组件/执行条件/准备数据
  2. 行动(Act) 对系统执行操作,例如点击按钮、触发钩子函数
  3. 断言(Assert) 确保真实的结果匹配你的期望

单元测试开发案例

假设现在我们要开发一个按钮,

我们先来设计这个按钮的功能

首先能接收自定义文字,能够接收size设置不同尺寸,能够触发事件,然后还有禁用功能

接下来我们开始写单元测试

// tests/button.spec.js
import Button from '@/components/Button.vue'
import { mount } from "@vue/test-utils"

const BUTTON_TEXT = '点击'
describe('Button.vue', () => {
    it('render text', () => {
        const wrapper = mount(Button, {
            slots: {
                default: BUTTON_TEXT,
            },
        })
        expect(wrapper.text()).toBe(BUTTON_TEXT)
    })
    it('size', () => {
        const wrapper = mount(Button, {
            propsData: {
                size: 'small'
            }
        })
        expect(wrapper.classes()).toContain('btn-small')
    })
    test('handle click', async () => {
        const wrapper = mount(Button, {
            slots: {
                default: BUTTON_TEXT,
            },
        })
        await wrapper.trigger('click')
        expect(wrapper.emitted().click).toBeDefined()
    })
    test('handle disabled click', async () => {
        const wrapper = mount(Button, {
            slots: {
                default: BUTTON_TEXT,
            },
            propsData: {
                disabled: true
            }
        })
        expect(wrapper.classes()).toContain('is-disabled')
        await wrapper.trigger('click')
        expect(wrapper.emitted().click).toBeUndefined()
    })
})   

完成组件功能

<template>
    <button 
    :class="[
      'el-button',
        size ? 'btn-' + size : '',
      {
        'is-disabled': disabled,
      }
    ]"
    @click="handleClick">
            <span v-if="$slots.default"><slot></slot></span>
    </button>
</template>

<script>
export default {
    props:{
        size:{
            type:String,
            required:false
        },
        disabled:{
            type:Boolean,
            default:false,
            required:false
        },
    },
    methods:{
        handleClick(evt) {
            !this.disabled && this.$emit('click', evt)    
        }
    }
}
</script>

<style>
//省略样式
</style>

总结

在开发中引入前端自动化测试,可以帮我们带来很多好处。但是同时不能忽视的一个问题,就是成本、无论是编写自动测试的时间成本,平台的搭建成本,项目成员学习自动化测试的成本。要考虑验证的的内容是否有价值需要自动化测试,我们费劲心血写的自动化测试是否足够稳健,不会频繁变更。

总之只有合适的才是最好的。

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8