---
order: 15
title: UI 測試
type: 進階
---
UI 測試是項目研發流程中的重要一環,有效的測試用例可以梳理業務需求,保證研發的質量和進度,讓工程師可以放心的重構代碼和新增功能。
Ant Design Pro 封裝了一套簡潔易用的 React 單元測試和 E2E 測試方案,在項目根目錄運行以下命令就能運行測試用例。
```bash
$ npm run test:all # 執行所有測試
```
<img style="box-shadow:none;margin:0;" src="https://gw.alipayobjects.com/zos/rmsportal/EFKJzIswQgWNJzDQNpKr.png" width="700" />
下面簡單介紹如何在項目中書寫你的業務測試用例。
## 單元測試
單元測試用于測試 React UI 組件的表現。我們參考了 [create-react-app](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#running-tests),使用 [jest](http://facebook.github.io/jest/) 作為測試框架。
jest 是一個 node 端運行的測試框架,使用了 jsdom 來模擬 DOM 環境,適合用于快速測試 React 組件的邏輯表現,需要真實瀏覽器可以參考 E2E 測試部分。
### 寫一個用例
比如,我們可以建一個文件 `src/routes/Result/Success.test.js` 來測試成功頁面組件的 UI 表現。
```jsx
import React from 'react';
import { shallow } from 'enzyme';
import Success from './Success'; // 引入對應的 React 組件
it('renders with Result', () => {
const wrapper = shallow(<Success />); // 進行渲染
expect(wrapper.find('Result').length).toBe(1); // 有 Result 組件
expect(wrapper.find('Result').prop('type')).toBe('success'); // Result 組件的類型是成功
});
```
這里使用了 [enzyme](http://airbnb.io/enzyme/docs/api/index.html) 作為測試庫,它提供了大量實用的 API 來幫助我們測試 React 組件。斷言部分沿用了 jest 默認的 [jasmine2 expect 語法](https://facebook.github.io/jest/docs/en/expect.html#content)。
### 本地執行
使用以下的命令將統一搜索和執行 `src` 下 `*.test.js` 格式的用例文件。
```bash
$ npm test .test.js
```
#### 執行單個或一組用例
```bash
$ npm test src/routes/Result/Success.test.js # 測試 Success.test.js
$ npm test src/routes # 測試 routes 下的所有用例文件
```
### 測試 dva 包裝組件
被 dva `connect` 的 React 組件可以使用下面方式進行測試。
```jsx
import React from 'react';
import { shallow } from 'enzyme';
import Dashboard from './Dashboard';
it('renders Dashboard', () => {
// 使用包裝后的組件
const wrapper = shallow(<Dashboard.WrappedComponent user={{ list: [] }} />);
expect(wrapper.find('Table').props().dataSource).toEqual([]);
});
```
## e2e 測試
端到端測試也叫冒煙測試,用于測試真實瀏覽器環境下前端應用的流程和表現,相當于代替人工去操作應用。
我們引入了 [puppeteer](https://github.com/googlechrome/puppeteer) 作為 E2E 測試的工具,puppeteer 是 Google Chrome 團隊官方的無界面(Headless)Chrome 工具。它默認使用 chrome / chromium 作為瀏覽器環境運行你的應用,并且提供了非常語義化的 API 來描述業務邏輯。
### 寫一個 e2e 用例
假設有一個需求,用戶在登錄頁面輸入錯誤的用戶名和密碼,點擊登錄后,出現錯誤提示框。
<img src="https://gw.alipayobjects.com/zos/rmsportal/oZeYewGOUJkmqXAPoOFC.gif" width="400" />
我們寫一個用例來保障這個流程。在 `src/e2e/` 目錄下建一個 `Login.e2e.js` 文件,按上述業務需求描述測試用例。
```js
import puppeteer from 'puppeteer';
describe('Login', () => {
it('should login with failure', async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.type('#userName', 'mockuser');
await page.type('#password', 'wrong_password');
await page.click('button[type="submit"]');
await page.waitForSelector('.ant-alert-error'); // should display error
await page.close();
browser.close();
});
});
```
更多 puppeteer 的方法可以參考 [puppeteer/docs/api.md](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md)。
### 運行用例
運行下列命令將執行 src 下所有的 `*.e2e.js` 用例文件。
```bash
$ npm test .e2e.js
```
<img src="https://gw.alipayobjects.com/zos/rmsportal/LGCXopksUYMUhjRgdYSz.png" width="700" />
> 注意,本地測試 e2e 用例需要啟動 `npm start`,否則會報 `Failed: navigation error` 的錯誤。
## watch 模式
```
$ npm test -- --watch
```
添加 `--watch` 配置可以進入 watch 模式,當你修改和保存文件時,Jest 會自動執行相應用例。Jest 的命令行工具也提供了各種方便的快捷鍵來執行你需要的用例。
<img src="https://gw.alipayobjects.com/zos/rmsportal/MnmxiavystfcBDskyKRg.png" width="700" />
## 測試覆蓋率
```
$ npm test -- --coverage
```
添加 `--coverage` 配置可以顯示項目的測試覆蓋率。
<img src="https://camo.githubusercontent.com/bd0bbda8e44ea747e4c199d0e212d40563ad2fcb/687474703a2f2f692e696d6775722e636f6d2f356246686e54532e706e67" width="700" />
## 聚焦和忽略用例
使用 `xit()` 取代 `it()` 可以暫時忽略用例,`fit()` 可以聚焦當前用例并忽略其他所有用例。這兩個方法可以幫助你在開發過程中只關注當前需要的用例。
## 接入集成測試服務
如果需要接入 travis、CircleCI、Gitlab CI 等集成測試環境,可以參考本倉庫提供的 `.travis.yml`。
注意 e2e 測試需要集成環境支持 electron,如果不支持,你可以使用 `npm test .test.js` 單獨運行單元測試。
## 參考鏈接
更多測試技巧和功能請參考以下鏈接。
- [create-react-app tests](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#running-tests)
- [jest](https://facebook.github.io/jest/)
- [enzyme](http://airbnb.io/enzyme/)
- [puppeteer](https://github.com/googlechrome/puppeteer)
- [Using with puppeteer](https://facebook.github.io/jest/docs/en/puppeteer.html)