Руководство по предотвращению ложных срабатываний
При создании веб-приложения вам необходимо убедиться, что ваши компоненты хорошо протестированы. Один из способов протестировать ваше приложение — использовать библиотеку типа @testing-library. Эта библиотека предоставляет вам функции для визуализации ваших компонентов и взаимодействия с ними, что упрощает тестирование вашего приложения.
Одним из ключевых элементов обеспечения тестируемости ваших компонентов является добавление к ним уникальных атрибутов data-testid
. Эти атрибуты действуют как селекторы, которые помогают библиотеке тестирования идентифицировать компоненты, которые вы хотите протестировать. Однако важно избегать жесткого кодирования этих атрибутов в ваших компонентах, так как это может привести к ложным срабатываниям при тестировании вашего приложения.
Вот пример жестко закодированного data-testid
:
import React from 'react'; interface ButtonProps { label: string; onClick: () => void; } const Button: React.FC<ButtonProps> = ({ label, onClick }) => { return ( <button data-testid="submit-button" onClick={onClick}> {label} </button> ); }; export default Button;
Давайте проверим, работает ли он так, как ожидалось:
import React from 'react'; import { render, fireEvent } from '@testing-library/react'; import Button from './Button'; describe('Button component', () => { it('should call onClick function when button is clicked', () => { const mockOnClick = jest.fn(); const { getByTestId } = render( <Button label="Submit" onClick={mockOnClick} /> ); const submitButton = getByTestId('submit-button'); fireEvent.click(submitButton); expect(mockOnClick).toHaveBeenCalled(); }); });
Как видите, тест пройден, но если у вас есть несколько экземпляров этого компонента на странице, жестко заданный data-testid
приведет к неправильным результатам теста.
Жесткое кодирование атрибутов data-testid
в повторно используемых компонентах может привести к ложным срабатываниям при тестировании вашего приложения. Взгляните на этот пример:
import React from 'react'; interface ButtonProps { label: string; onClick: () => void; } const Button: React.FC<ButtonProps> = ({ label, onClick }) => { return ( <button data-testid="submit-button" onClick={onClick}> {label} </button> ); }; const App = () => { return ( <div> <Button label="Submit 1" onClick={() => console.log('Button 1 clicked')} /> <Button label="Submit 2" onClick={() => console.log('Button 2 clicked')} /> </div> ); }; export default App;
Теперь давайте напишем тест для этого компонента App
, где мы хотим проверить, работают ли обе кнопки должным образом:
import React from 'react'; import { render, fireEvent } from '@testing-library/react'; import App from './App'; describe('App component', () => { it('should call the onClick function of both buttons when they are clicked', () => { const mockOnClick1 = jest.fn(); const mockOnClick2 = jest.fn(); const { getByTestId } = render( <App /> ); const submitButton1 = getByTestId('submit-button'); fireEvent.click(submitButton1); expect(mockOnClick1).toHaveBeenCalled(); const submitButton2 = getByTestId('submit-button'); fireEvent.click(submitButton2); expect(mockOnClick2).toHaveBeenCalled(); }); });
В этом случае, несмотря на то, что мы используем разные функции onClick
для обеих кнопок, тест все равно будет пройден, поскольку обе кнопки имеют одинаковые data-testid
из submit-button
. Это наглядный пример того, как жестко закодированные тестиды могут приводить к ложным срабатываниям при тестировании.
Чтобы избежать этой проблемы, вы должны передавать атрибуты data-testid
в качестве свойств, чтобы каждый экземпляр компонента мог иметь уникальное значение. Это поможет убедиться, что ваши тесты точны и надежны. Вот пример:
import React from 'react'; interface ButtonProps { label: string; onClick: () => void; testId: string; } const Button: React.FC<ButtonProps> = ({ label, onClick, testId }) => { return ( <button data-testid={testId} onClick={onClick}> {label} </button> ); }; export default Button;
А вот обновленный тест для этого компонента:
import React from 'react'; import { render, fireEvent } from '@testing-library/react'; import Button from './Button'; describe('Button component', () => { it('should call onClick function when button is clicked', () => { const mockOnClick = jest.fn(); const { getByTestId } = render( <Button label="Submit" onClick={mockOnClick} testId="submit-button-1" /> ); const submitButton = getByTestId('submit-button-1'); fireEvent.click(submitButton); expect(mockOnClick).toHaveBeenCalled(); }); });
При таком подходе вы можете отображать несколько экземпляров компонента, и каждый экземпляр будет иметь уникальный идентификатор теста, что позволит вам тестировать каждый экземпляр компонента по отдельности.