前端测试:组件测试

为什么进行测试

你是否有以下烦恼:

  • 当你加班加点完成一个功能后,提交给测试部,立马返回几个bug

  • 当你修改完bug后,并检查了好几遍,确保无误后,提交给测试部,有返回几个bug

    ……

对于以上情境,你是否有过疑问,为什么检查都没问题了还是出现bug?以上这些都是因为没有做好测试。

你可能会问,做了呀,都检查好几遍了。的确,你是测试了,但是你并没有完成测试的闭环。你可能完成测试的一部分,其他的部分并没有完成。既然你说我没完成测试,那何为测试,又怎么进行测试?

什么是测试?

对于前端来说,测试主要是对HTML、CSS、JavaScript进行测试,以确保代码的正常运行。

常见的测试有单元测试、集成测试、端到端(e2e)的测试。

  • 单元测试:对程序中最小可测试单元进行测试。我们可以类比对汽车的测试,在汽车组装之前需要对零件进行测试,这种情况下就和单元测试一致。只有零件正常才会进行下一步的组装
  • 集成测试:对多个可执行单元组成的整体进行测试。类比于汽车的测试,就相当于测试发动机之前,需要把发动机所需的零件组装在一起对组装后的发动机这个整体进行测试。
  • 端到端的测试:从服务端到客户端的测试。这种测试是对服务端和客户端组成的整个系统进行测试,它是能够执行完整流程的测试。

既然知道了有这些测试种类,接下来就说说这些测试应当如何实现。

如何进行测试

测试的方式可以分为人工测试、自动测试。

人工测试:就是让测试部的人员根据业务流程进行操作当某一步或几步出现问题就说明这部分代码有问题。这种测试方式有很明显的不足:

  1. 它只能测试测试人员看得见的部分,对于测试人员看不见的部分不能测试。比如一些内部的工具函数、逻辑代码等,这些很可能存在问题。

自动测试:利用写好的代码对代码进行测试。这种测试能够弥补人工测试的不足,它的颗粒度是代码级别的,能够准确地识别某个方法的错误

由此,在实际的开发过程中我们可以采用人工测试+自动测试的方式进行测试,力求100%的覆盖测试目标。人工测试暂且不谈,我们先谈谈自动测试的方式实现组件测试。

单元测试中使用的是jest,本篇继续使用jest。

jest本身并不能解析vue组件,需要引入babel-jest和vue-jest这两个转换器进行转换。
babel-jest可以将现代JavaScript编译成可以在Node中运行的JavaScript。vue-jest可以将单文件组件(SFC)编译成JavaScript

安装babel-jest和vue-jest

npm install babel-jest vue-jest -D

安装完毕后运行jest命令当打印引入的组件时会输出一个带有渲染函数的对象,但是此时并不能在浏览器上显示,需要将组件挂载。

挂载组件,需要将组件选项转换为一个Vue构造函数,使用Vue.extend函数将组件转换成Vue构造函数,然后使用new关键词创建一个实例,并调用mount挂载组件

Vue test utils

Vue Test Utils库会让Vue组件单元测试变得更容易。它包含的一些辅助方法可以实现组件挂载、与组件交互以及断言组件输出

安装vue test utils

npm install @vue/test-utils -D

API

mount

Vue Test Utils导出一个mount方法,该方法在接收一个组件后,会将其挂载并返回一个包含被挂载组件实例(vm)的包装器对象,包装器不仅包含Vue实例,还包括一些辅助方法,可以使用它们来设置props,检查实例属性以及对实例执行操作。

shallowMount

shallowMount不会像mount一样渲染整个组件树,它只渲染一层组件树,shallowMount在挂载组件之前对所有子组件进行存根。

shallowMount可以确保你对一个组件进行独立测试,有助于避免测试中因子组件的渲染输出而混乱结果

渲染组件输出测试

输出文本测试

import Item from '@/components/Item.vue'
import {
    
    shallowMount} from '@vue/test-utils'
describe('item.vue', () => {
    
    
	test('item.url', () => {
    
    
			const wrapper = shallowMount(Item);
			expect(wrapper.text()).toBe('hello world');
	});
});
import Item from '@/compoennts/Item.vue'
import {
    
    shallowMount} from '@vue/test-utils'
dscribe('测试元素文本', () => {
    
    	
	const wrapper = shallowMount(Item);
	test('测试a标签中的文本', () => {
    
    
		expect(wrapper.find('a').text()).toBe('新闻');
	});
});

测试DOIM属性

import Item from '@/compoennts/Item.vue'
import {
    
    shallowMount} from '@vue/test-utils'
describe('测试DOM属性', () => {
    
    
	const wrapper = shallowMount(Item);
	test('测试元素属性', () => {
    
    
		expect(wrapper.attributes().href === Item.url).toBe(true);
	});
});

测试prop

import Item from '@/components/Item.vue'
import {
    
    shallowMount } from '@vue/test-utils'
describe('测试prop', () => {
    
    
	const wrapper = shallowMount(Item)
	test('测试prop', () => {
    
    
		expect(wrapper.find(Item).prop().propA).toBe('itemProp');
	});
});

测试class

import Item from '@/components/Item.vue'
import {
    
    shallowMount } from '@vue/test-utils'
describe('测试class', () => {
    
    
	const wrapper = shallowMount(Item)
	test('测试class', () => {
    
    
		expect(wrapper.classes()).toContain('hidden');
	});
});

测试样式

import Item from '@/components/Item.vue'
import {
    
    shallowMount } from '@vue/test-utils'
describe('测试样式', () => {
    
    
	const wrapper = shallowMount(Item)
	test('测试样式', () => {
    
    
		expect(wrapper.element.style.width).toContain('200px');
	});
});

测试组件的公共方法

import Item from '@/components/Item.vue'
import {
    
    shallowMount } from '@vue/test-utils'
describe('测试组件公共方法', () => {
    
    
	const wrapper = shallowMount(Item)
	test('测试组价公共方法', () => {
    
    
		wrapper.vm.hide();
		expect(wrapper.element.style.display).toBe('none');
	});
});

测试组件事件

import Item from '@/components/Item.vue'
import {
    
    shallowMount } from '@vue/test-utils'
describe('测试组件事件', () => {
    
    
	const wrapper = shallowMount(Item)
	test('测试组价事件', () => {
    
    
	wrapper.find('div').trigger('mouseover')
		expect(onClose).toHaveBeenCalled();
	});
});
测试自定义时间
import Item from '@/components/Item.vue'
import {
    
    shallowMount } from '@vue/test-utils'
describe('测试自定义事件', () => {
    
    
	const wrapper = shallowMount(Item)
	test('测试自定义事件', () => {
    
    
	wrapper.find('button').trigger('click')
		expect(wrapper.$emitted('submit')).toHaveLength(1);
	});
});

测试输入表单

import Item from '@/components/Item.vue'
import {
    
    shallowMount } from '@vue/test-utils'
describe('测试输入表单', () => {
    
    
	const wrapper = shallowMount(Item)
	test('测试输入框', () => {
    
    
		wrapper.find('input[type=text]').value = 'edd';
		wrapepr.find('input[type=text]').trigger('change');
			expect(wrapper.text()).toContain('edd');
	});
	test('测试单选按钮', () => {
    
    
		wrapper.find('input[value=no]').setChecked();
			expect(wrapper.find('input[value=no]').value === true).toBe(true);
	});
});

猜你喜欢

转载自blog.csdn.net/qq_40850839/article/details/130986109