通过学习测试React网站和应用程序来获取可用于生产的代码。
#react#
如何测试React网站和应用程序
如果您想知道如何测试React,那么您来对地方了。您真的知道您的代码可以执行它的工作吗?您是否在浏览器中测试过?如果您还没有,或者您无法测试所有内容,并且会中断生产该怎么办?
测试库是开发人员用来在应用程序组件上编写单个测试的一组实用程序。测试的一些主要部分是:
- 描述:描述测试的内容
- 使用/渲染:在可以测试组件的环境中使用组件
- 模拟:创建伪装函数,以便您可以检查自己的假设
在本文的整个过程中,我将探索React Testing库中的一些示例,以帮助您开始使用这种有价值的方法来提高代码输出的健壮性,并确保代码不会抛出错误。一旦投入生产,就会产生令人讨厌的惊喜。
01.开始使用React测试库
我将在此演示中使用create-react-app,因为它已经预先配置了测试库。如果您使用的是Gatsby或自定义设置,则可能需要先进行一些配置,然后才能开始使用测试库。
首先,让我们创建一个新的应用程序。如果您已经拥有最新版本的Node.js,则可以运行以下命令而无需全局安装其他任何东西:
npx create-react-app netmag-javascript-testing
02.确定要测试的内容
假设我们有一个简单的组件,比如说具有某种状态的按钮。在这样的组件中需要测试哪些内容?
● 组件的外观:
编写组件后,我们不希望任何意外更改。因此,我们将编写一个快照测试以捕获其渲染方式。然后,如果有任何更改,我们将无需手动或视觉测试即可快速看到它。这对于包含许多较小组件的组件非常有用:您可以快速看到外观的何时何地受到影响。
● 呈现的不同分支:
因为我们可能有两个或更多个不同的输出,所以我们需要测试它是否正确渲染了所有输出,而不仅仅是其中之一。因此,我们需要模拟一个click事件,并在运行此代码分支之后对其呈现方式进行另一个快照测试。
● 该函数将按预期方式调用:
我们要确保编写的用来调用另一个函数的代码能够正常工作。但是由于该函数是外部依赖项,因此我们不想在这里进行测试。我们的测试应该只封装我们想要的功能。
03.编写您的第一个测试
让我们写我们的第一个测试。在与组件相同的文件夹中创建一个名为MyComponent.unit.test.js的新文件。通过在最后添加test.js,测试库将自动选择它。该文件的内容如下:
import React from ‘react’import { render } from ‘@testing-library/react’import MyComponent from ‘./MyComponent’describe(‘the ’, () => { // tests go here})
我要引起您注意的第一件事是describe()函数,该函数带有两个参数:第一个是可以用来更好地描述测试字符串的字符串(作为文本字符串)。在我们的案例中,我们只是说应该渲染。当其他人查看您的代码或您必须记住以后的操作时,这非常有用。编写良好的describe语句是代码文档的一种形式,也是编写测试的另一个很好的理由。
第二个参数是您的测试。该描述()函数将运行所有这些测试一个接一个的。
04.使用清理功能
让我们介绍一个名为beforeEach()的辅助函数。我们需要使用它,因为每次我们对组件进行操作时,我们都希望获得一个新副本,而没有以前传递给它的道具仍然存在于组件中。或者,我们可能需要重新渲染该组件:beforeEach()为我们完成了此任务,我们可以将其传递给清理函数。
import { render, cleanup } from ‘@testing-library/react’...describe(‘the component should render’, () => { beforeEach(cleanup)}
05.编写快照测试
在这一步中,我们将“挂载”我们的组件(或渲染它)。
describe(‘the component should render’, () => { beforeEach(cleanup) it(‘renders with basic props’, () => { render() })}
此渲染使我们可以访问已编译组件的所有渲染属性。最好将其放入console.log(),这样您可以更清楚地看到它的作用。如果这样做,您会发现这里有一些有用的属性可以利用。我将进行断言(进行可测试的声明)并通过提取容器进行测试。容器“包含”与组件关联的DOM节点(所有HTML)。
it(‘renders with basic props’, () => { const { container } = render()})
现在我们可以访问容器了,如何确定它是根据我的断言渲染的?通过添加快照测试。
将快照想像成照片。它在特定时间点为我们的组件拍摄快照。然后,每当对代码进行更改时,我们都可以查看它是否仍与原始快照匹配。如果是这样,我们可以确信组件中没有任何变化。但是,如果不是这样,我们可能已经发现了一个问题,该问题源于另一个组件,而以前我们可能没有发现过:
06.测试性质
组件的属性或属性也可以使用快照进行测试。测试您提供给组件的各种道具将为您提供更大的覆盖范围和信心。您永远不知道什么时候需求将意味着您组件的props被重构并且最终输出将改变。
将以下对象添加到文件的顶部:
const lightProperties = { backgroundColour: ‘white’, textColour: ‘darkblue’}
我们在对象中定义属性,然后使用散布运算符(三个点后跟对象名称:... lightproperties),因为在渲染这种方式时只能传递一个参数。查看隔离传递的属性也很有用:
it(‘renders with basic props’, () => { const { container } = render( ) expect(container).toMatchSnapshot() }) it(‘renders with the light version props’, () => { const { container } = render( ) expect(container).toMatchSnapshot() })
07.测试用户界面中的更改
想象一下,我们的组件有一个按钮,并且您想确保单击按钮时发生某些事情。您可能会认为您想测试应用程序的状态。例如,您可能很想测试状态是否已更新。但是,这不是这些测试的目的。
这向我们介绍了使用测试库的重要概念:这里我们不是要测试状态或组件的工作方式。我们在这里测试人们如何使用该组件以及该组件是否符合他们的期望。
因此,状态是否已更新无关紧要;我们要测试的是该按钮按下的结果。
假设我们正在测试将UI从暗模式更改为亮模式的函数的结果。这是组件:
const modeToggle = () => { const [mode, setMode] = useState[‘light’] const toggleTheme = () => { if (theme === ‘light’) { setTheme(‘dark’) } else { setTheme(‘light’) } } return ( Toggle mode )}
首先,我们应该在按钮上添加一个测试ID,以便我们可以在渲染阶段找到它:
return ( Toggle mode
您是否注意到我们向按钮添加了新属性data-testid?这是您可能会测试的方法。首先,从测试库导入一个新函数fireEvent:
import { cleanup, fireEvent, render } from ‘@testing-library/react’
我们可以使用该功能来测试UI中是否有更改,并且这些更改是否一致:
it(‘renders with basic props’, () => { const { container } = render( ) expect(container).toMatchSnapshot()})it(‘renders the light UI on click’, () => { const { container, getByTestId } = render() fireEvent.click(getByTestId(‘mode-toggle’)) expect(container).toMatchSnapshot()})
太好了:我们不必手动访问该站点并四处查看,然后单击按钮并再次浏览-在此期间,您可能会承认,您可能会忘记或错过某些东西!现在我们可以放心,在给定相同输入的情况下,我们可以期望组件中具有相同的输出。
当涉及到测试ID时,我个人不喜欢使用data-testid在DOM中查找内容。毕竟,测试的目的是模仿用户在做什么,并测试他们在做什么。数据-testid似乎有点作弊-尽管数据-testid对您的质量检查工程师可能会派上用场(请参阅“质量保证工程师的角色”装箱)。
相反,我们可以使用getByText()并传入按钮的文本。该方法将更多地针对行为。
08.模拟和监视功能
有时我们可能需要测试对某个函数的调用,但是该函数不在测试范围之内。例如,我有一个单独的模块,其中包含一个函数,该函数将pi的值计算为一定的小数位数。
我不需要测试该模块的结果是什么。我需要测试我的功能是否按预期进行。有关原因的更多信息,请参见“单元和集成测试”框。在这种情况下,我们可以“模拟”该功能:
const getPiValue = jest.fn()it(‘calls the function on click’, () => { const { container, getByTestId } = render() fireEvent.click(getByTestId(‘mode-toggle’)) expect(getPiValue).toHaveBeenCalledTimes(1) )})
该功能toHaveBeenCalledTimes()是在测试库中的许多辅助功能,使我们一个
测试功能的输出。这不仅使我们可以将测试的范围仅扩展到要测试的模块,还意味着我们可以“窥探”或查看函数调用该函数时的功能。
09.开始测试React应用程序
开始编写测试似乎有些艰巨。我希望本教程使您更有信心尝试它。