英文:
Why are my React Testing Library tests so slow?
问题
我的工作场所有一个相当大的单页应用程序,它是在2020年构建的,使用Create React App作为构建工具。不幸的是,几乎每个组件的测试都需要很长时间。有时超过300秒,有时100秒,我见过的最快测试完成时间是30秒。这种情况是否正常?如果不正常,为什么测试会花这么长时间?
虽然这个代码示例无法重现,但我希望有人可以阅读一下它,并指出一些可能存在问题的地方:
以下是相关的依赖项:
"dependencies": {
"@types/node": "^12.12.50",
"@types/react": "^17.0.52",
"@types/react-dom": "^17.0.18",
"@types/react-router-dom": "^5.1.7",
"@types/react-leaflet": "^2.8.1",
"aws-amplify": "^4.3.26",
"leaflet": "^1.7.1",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-leaflet": ">=3.1.0 <3.2.0 || ^3.2.1",
"@react-leaflet/core": ">=1.0.0 <1.1.0 || ^1.1.1",
"react-router-dom": "^6.4.3",
"typescript": "^3.7.5"
}
"devDependencies": {
"react-scripts": "^5.0.1",
"@testing-library/dom": "^7.28.1",
"@testing-library/jest-dom": "^5.11.6",
"@testing-library/react": "^12.1.5",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^26.0.4",
"jest": "^26.6.3",
"node-sass": "^6.0.1"
}
本地开发的Node版本:v16.15.1
英文:
My workplace has largish single page application, it was built in 2020 and uses Create React App for the build tool. Unfortunately, nearly every component takes an excessive amount of time to test. Sometimes it is longer than 300seconds, sometimes 100seconds, the fastest I've ever seen a test complete is 30seconds. Is this normal behaviour, if not, why are these tests taking such a long time?
While this code example is not reproducable, I am hoping that somebody may be able to take a read through it and highlight some possible problem areas:
// required imports from React & 3rd party libraries
import React from 'react';
import { render, screen, within } from '@testing-library/react';
import { API } from 'aws-amplify';
// react component to be tested, plus context and helper functions
import { MyComponent } from './MyComponent';
import { Store, UserContext, FurtherDetailContext } from 'store/store';
import * as helpers from 'helpers';
// mock data
import userContextMock from '../../../tests/fixtures/userContext/userContext.json';
import furtherDetailContextMock from '../../../tests/fixtures/furtherDetailContext/furtherDetailContext.json';
import gqlQueryResponse1 from '../../../tests/fixtures/gql/gqlQueryResponse1.json';
import gqlQueryResponse2 from '../../../tests/fixtures/gql/gqlQueryResponse2.json';
const mockJson = {
this: 'is',
an: 'example',
response: true
};
const arrange = async () => {
const mockToggleOpen = jest.fn();
render(
<Store>
<UserContext.Provider
value={{
userContext: userContextMock,
setUserContext: () => {
// do nothing
}
}}>
<FurtherDetailContext.Provider
value={{
furtherDetailContext: furtherDetailContextMock,
setFurtherDetailContext: () => {
/*do nothing */
}
}}>
<MyComponent myProps={mockJson} toggleOpen={mockToggleOpen} />
</FurtherDetailContext.Provider>
</UserContext.Provider>
</Store>
);
// this component performs a network request before rendering
await screen.findByText('text on the screen');
const testid1 = screen.getByTestId('test-id-example');
const testid2 = screen.getByTestId('test-id-example-2');
return { testid1, testid2 };
};
describe('MyComponent', () => {
beforeEach(() => {
// get auth token
jest.spyOn(helpers, 'getAuthtoken').mockResolvedValue('validAuthToken');
});
describe('all calls mocked', () => {
beforeEach(() => {
// mock graphql requests
API.graphql = jest.fn().mockImplementation((url) => {
const gqlQuery = url.query;
if (RegExp('.*.mockGqlQuery*').test(gqlQuery)) {
return gqlQueryResponse1;
}
if (RegExp('.*.mockGql2*').test(gqlQuery)) {
return gqlQueryResponse2;
}
return;
});
});
it('shows the original text on component mount', async () => {
const { testid1 } = await arrange();
expect(within(testid1).getByText('this text should be here')).toBeInTheDocument();
});
});
});
Here are the relevant dependencies:
"dependencies": {
"@types/node": "^12.12.50",
"@types/react": "^17.0.52",
"@types/react-dom": "^17.0.18",
"@types/react-router-dom": "^5.1.7",
"@types/react-leaflet": "^2.8.1",
"aws-amplify": "^4.3.26",
"leaflet": "^1.7.1",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-leaflet": ">=3.1.0 <3.2.0 || ^3.2.1",
"@react-leaflet/core": ">=1.0.0 <1.1.0 || ^1.1.1",
"react-router-dom": "^6.4.3",
"typescript": "^3.7.5",
}
"devDependencies": {
"react-scripts": "^5.0.1",
"@testing-library/dom": "^7.28.1",
"@testing-library/jest-dom": "^5.11.6",
"@testing-library/react": "^12.1.5",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^26.0.4",
"jest": "^26.6.3",
"node-sass": "^6.0.1",
}
local development node version: v16.15.1
答案1
得分: 1
这是一个众所周知的问题,create-react-app
的速度相当慢;而这个问题也延伸到了测试中。
问题可能出在webpack
,你的打包程序上,可悲的是你不能轻易将使用create-react-app
构建的应用与它分离。
我的建议是转向使用vite
,然后使用vite的测试库:vitest。
(我认为你可以保留正常的create-react-scripts
,并且仅仅在测试中使用vitetest。)
我理解这可能不是你想要得到的答案类型 - 这不仅仅是_又一个依赖项_,它还意味着改变了很多基础架构;但总的来说,我发现从create-react-app
转向vite
非常有用;速度差异如天与地之别。
这是一个vitest的迁移指南,你可能会找到它很有用。
英文:
It's a well known issue that create-react-app
is quite slow; and this issue is also extended to the tests.
The problem is probably webpack
, your bundler program, sadly you can't easily decouple an app built with create-react-app
from it.
My recommendation is to switch over to vite
, and then to use vite's testing library: vitest in particular.
(I believe you might keep your normal create-react-scripts
and only use vitetest for testing.)
I understand that this is not the type of answer you might like to receive - it's not only Yet Another Dependency it also means changing a lot of the plumbing; but overall I found it incredibly useful to switch from create-react-app
to vite
; the speed difference is night and day.
Here's a migration guide for vitest that you might find useful.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论