使用Jest和React测试库的测试案例

414 阅读4分钟

使用Jest和React测试库的测试案例

作者 Satya Swaroop Mohapatraon July 9, 2021; tagged underreactjs,jest,react-testing-library

当涉及到更好的用户体验,处理bug和修复一个特定的组件或它的一些功能时,Testing ,防止我们的船在生产后😃沉没。

像Jest这样的测试框架,提供了一些功能和方法,通过它们我们可以在项目中进行各种assertions

因此,让我们通过使用react创建一个简单的Counter App ,深入了解jest和react-testing-library。

像往常一样,我们将使用cra 模板进行设置

npx create-react-app my-counter
cd my-counter
npm start

让我们创建一个简单的计数器:

import {useState} from "react"
import './App.css';
function App() {
  const [count,setCount] = useState(1);
  const increment = () => {
    setCount(count + 1);
  }
  const decrement = ()=>{
    if(count === 0){
      return
    }
    setCount(count - 1);
  }
  return (
    <div className="App">
      <h1>Counter App 😃</h1>
      <div className="flex">
         <button onClick={increment}>+</button>
         <button onClick={decrement}>-</button>
      </div>
      <div className="App">
       <h2 title="Display">{count}</h2>
      </div>
    </div>
  );
}
export default App;

现在我们已经创建了我们的计数器,现在让我们关注一下什么是jestreact-testing-library ,以及为什么我们要一起使用这些?

Jest

Jest是一个javascript测试框架,它提供了一个混合的断言库,以及一个测试运行器和一个内置的嘲弄库。

React测试库

它是一个测试库,用于渲染反应组件。它直接与DOM节点一起工作,确保我们编写的测试与用户与组件的交互方式非常相似。

为什么我们要一起使用这个?

Jest为我们提供了各种测试块,如it(),test()describe() ,用于命名测试和包括各自的代码。它还为我们提供了一个全局断言函数,即expect() ,以进行简单的测试断言。

注意:it()test() 是完全相同的,只是在命名上有所不同。

jest-dom 为了使测试案例易于阅读,易于维护,jest ,它提供了一些自定义的匹配器函数,如toBeInTheDocument(),toHaveAttribute() toHaveStyle() 等。与DOM API的交流变得非常容易,就像我们在浏览器中交流一样。

而另一方面,react-testing-libary为我们提供了各种方法,如render() ,以渲染react组件。screen 对象,它有所有的查询,document 对象模型被包裹在<body> 元素中。

由于我们使用的是cra 模板,上述软件包会作为devDependencies自动安装在package.json 文件中。如果我们不使用cra 模板,我们需要手动安装它。

使用npm

npm install --save-dev @testing-library/react @testing-library/jest-dom

或使用yarn

yarn add --dev @testing-library/react @testing-library/jest-dom

现在,让我们看一下setupTest.js 文件,这里我们导入了jest-dom包,这样react就可以在设置测试环境时初始化它。

测试案例

Case-1: Will test if the title "Counter App 😃" is present in the document or not.

Case-2: Will test when the + clicked it should increment the counter by 1.

Case-3: Will test when the - clicked it should decrement the counter by 1.

注意:每当我们写测试用例时,我们的文件命名惯例应该是some-name.test.js 。如果我们的组件目录中有一个some-name.js 文件,我们可以创建一个__test__ 目录,并在其中创建some-name.test.js 文件,这样我们就可以从一个文件级别导入some-name.js 文件。

让我们删除App.test.js 文件中的所有内容并从头开始:

import { render, screen } from '@testing-library/react';
import App from './App';

test('renders Counter App 😃 title', () => {
  render(<App />);
  const titleElement = screen.getByText(/Counter App 😃/);
  expect(titleElement).toBeInTheDocument();
});

这里我们使用render() 方法来渲染整个<App/> 组件,然后我们通过使用getByText() 查询screen 对象来查询标题。然后我们有我们的全局断言函数expect() 和一个匹配器函数toBeInTheDocument() ,它只是测试这个元素是否在DOM中被渲染。

运行该测试:

yarn test

npm run test

现在jest 会自动寻找.test.js 文件并执行测试。如果一切正常,测试案例就会通过:

test-result

恭喜你 🎉 我们已经写好了第一个测试用例。

让我们通过使用getByRole() 查询来编写其余的测试用例,这里我们也将使用事件处理程序,与我们在浏览器中执行事件的方式相同。我们将使用userEvent来实现。

为了使用这个,我们首先需要手动安装它:

npm install --save-dev @testing-library/user-event @testing-library/dom

yarn add --dev @testing-library/user-event @testing-library/dom
import userEvent from "@testing-library/user-event";

test("increment button is clicked and the value increments by 1",()=>{
  render(<App/>);
  const displayValue = screen.getByTitle("Display");
  userEvent.click(screen.getByRole('button',{name: '+'}));
  expect(displayValue.textContent).toBe("2");
});

test("decrement button is clicked and the value decrements by 1",()=>{
  render(<App/>);
  const displayValue = screen.getByTitle("Display");
  userEvent.click(screen.getByRole('button',{name: '-'}));
  expect(displayValue.textContent).toBe("0");
});

这里我们通过使用getByTitle() 查询,从<App/> 组件中获得<h2> 元素。为了引用确切的元素,我们给它添加了一个title 属性。

之后,我们使用了userEvent ,并给它附加了一个click 事件,然后我们通过使用getByRole 查询从<App/> 获取两个按钮。当我们运行测试时,事件的触发方式与我们在浏览器中执行的click 事件相同。

最后,我们对这两个测试案例进行断言,使其与预期值相符。

你可以在GitHub上查看这些代码。

本博客到此结束。我们将在下一篇博客中重点讨论async 测试。

学习愉快😇!