目录
前言
测试除了可以让我们对线上代码更有信心,更重要的是
当需要重构代码时,有测试用例的代码才叫重构,没有测试用例的代码叫重写
所以,测试对于软件工程来说是非常重要的,本文先讲讲最基础的前端测试
一、example
1.1 测试的组件
我们需要测试一个Counter的组件,其中有count初始值是0,有两个buttons,点击Decrement,count-1,点击Increment,count+1
1.2 create div element
我们首先需要创建一个div然后把需要测试的Counter组件包裹起来
let div = document.createElement('div')
document.body.append(div)
ReactDOM.render(<Counter />, div)
1.3 获取需要测试的元素
通过div.querySelectorAll('button')
我们可以获取所有的buttons组件,通过div.firstChild.querySelector('div')
可以获取第一个div元素
let button = div.querySelectorAll('button')
let message = div.firstChild.querySelector('div')
let decrement= button[0]
let increment = button[1]
1.4 模拟用户的事件
对于Counter的组件,页面初始的时候Current count为0,这个是首先由测试的
然后,用户事件一共有两个,点击Decrement,count-1,点击Increment,count+1
expect(message.textContent).toBe( 'Current count: 0')
increment.dispatchEvent(
new MouseEvent('click', {
bubbles: true,
cancelable: true,
button: 0,
})
)
expect(message.textContent).toBe( 'Current count: 1')
decrement.dispatchEvent(
new MouseEvent('click', {
bubbles: true,
cancelable: true,
button: 0,
})
)
expect(message.textContent).toBe( 'Current count: 0')
1.5 清理DOM
在测试完成之后,需要清理DOM,否则可能会导致问题,清理代码如下
div.remove()
或者加上如下代码
beforeEach(() => {
document.body.innerHTML = ''
})
二、使用React Testing Library
使用React Testing Library简化了一些每次测试都需写的代码,使用这个Library还是比较推荐的; 其中可以用screen.debug()
来做测试代码的debug
2.1 新的React组件包裹API
不需要手动创建div了,直接使用render就好
const {container} = render(<Counter />)
2.2 获取元素
获取元素与之前类似
const [decrement, increment] = container.querySelectorAll('button')
const message = container.firstChild.querySelector('div')
2.3 模拟用户事件
API稍微有所改变,测试如下
expect(message).toHaveTextContent('Current count: 0')
fireEvent.click(increment)
expect(message).toHaveTextContent('Current count: 1')
fireEvent.click(decrement)
expect(message).toHaveTextContent('Current count: 0')
三、避免实现细节
3.1 background
可以从上面的测试代码看出来,button的获取是通过querySelectorAll获取的,当前实现是decrement button在前而increment button在后,但是这个顺序如果变化了,测试就需要重写了,所以测试代码应该尽量避免实现细节
3.2 借助screen
screen有个很重要的功能就是向外提供了getByRole, getByText等API,这样可以一定程度避免了hard code,比如通过使用getByRole可以获得button name为increment的button,这样即便button先后顺序换了,只要name没有变化,还是可以获取需要测试的button的
const increment = screen.getByRole('button', {name: /increment/i})
const decrement = screen.getByRole('button', {name: /decrement/i})
const message = screen.getByText(/current count/i)
3.3 Chrome插件
这里还可以借用test playground的Chrome插件,帮组我们自动生成query代码,通过点击如下图中红色区域的左上角的element选择器,选中Decrement的button,就能生成decrement button的query
总结
本文主要讲了React测试的基本方法render react组件到DOM
,获取组件
,触发事件
;同时也介绍了react test library帮助减少冗余代码,以及避免实现细节