# Testing Library란
- UI 컴포넌트를 사용자 중심적으로 테스트하기 위한 경량화된 라이브러리
- 주로 웹애플리케이션의 DOM 기반 테스트를 지원
- React, Vue, Svelte, Angular 등 다양한 프레임워크 지원

- 철학 : 테스트가 실제 사용자가 애플리케이션을 사용하는 방식과 유사해야..
- 웹프론트엔드 테스트에서 사실상 표준으로 자리잡은 라이브러리
🔗 Testing Library 사이트 : https://testing-library.com/
Testing Library | Testing Library
Simple and complete testing utilities that encourage good testing practices
testing-library.com
Simple and complete testing utilities that encourage good testing practices
여기서 utilities란?
- 소프트웨어 테스트를 지원하는 도구, 함수, 또는 메서드
- 테스트를 작성하고 실행하는데 도움을 주는 특정 함수나 도구
- DOM 노드를 조작하거나 쿼리하여 사용자가 애플리케이션을 사용하는 방식과 유사한 테스트를 작성할 수 있도록 돕는다.
## 구현주도 테스트방법론 Implement Driven Test vs 행동주도테스트방법론 Behavior Driven Test)
[ 구현주도 테스트 IDT ]
- 애플리케이션이 어떻게 작동되는지에 대해서 초점을 두어 테스트 작성
- 아래 UI를 테스트한다고 했을 때, <h2>라는 태그가 쓰였고, title이라는 클래스가 사용되었는지의 여부를 테스트
- 아래 코드에서 h2태그가 h3태그로 바뀌었을 경우, 테스트가 깨진다.
- ex: Airbnb에서 만든 Enzyme 라이브러리
<h2 class="title">제목</h2>
[ 행동주도 테스트 Behavior Driven Test ]
- 사용자가 애플리케이션을 이용하는 관점에서 사용자의 실제 경험 위주로 테스트 작성
- 사용자 입장에서는 <h2> 태그를 사용하고, title이라는 class가 사용되는지는 관심이 없다.
- 화면에 보이는 컨텐츠, 이벤트 발생 시의 화면변화에 관심이 있다.
- 위 코드에서 h2태그가 h3태그로 바뀌어도 화면상에는 여전히 '제목'이라는 컨텐츠가 잘 노출되므로 테스트가 깨지지 않는다.
- ex: Testing Library 라이브러리
# React Testing Library의 주요 API
- render() 함수 : DOM에 컴포넌트를 랜더링해주는 함수
- screen 객체 : DOM에서 특정 영역을 선택하기 위한 다양한 쿼리함수 제공
- fireEvent 객체 : 쿼리함수로 선택된 영역을 대상으로 특정 사용자 이벤트를 발생시켜준다.
import { render, screen, fireEvent } from "@testing-library/react";
test("type='submit'으로 지정된 버튼 클릭 시, form이 제출됨", () => {
const handleSubmit = vi.fn();
render(
<form onSubmit={handleSubmit}>
<Button type="submit" variant="solid">
Submit Button
</Button>
</form>,
);
const submitButton = screen.getByText("Submit Button");
fireEvent.click(submitButton);
expect(handleSubmit).toHaveBeenCalledTimes(1);
});
# fireEvent vs userEvent
## fireEvent
- click(), mouseover(), focus(), change()등 이벤트를 트리거할 수 있는 다양한 메소드들을 제공
- 위 코드처럼 테스트코드에서 click()을 호출하면 onClick이라는 Dom Event 하나만 발생시킨다.
즉, 단순히 click 이벤트만 발생시킨다.
- 실제로 발생해야 하는 '모든' 유저이벤트가 발생하지 않고, 해당 이벤트만 발생.
## userEvent
- 전용 패키지 : @testing-library/user-event
- fireEvent와 마찬가지로 사용자 이벤트를 발생시킨다. (실제 내부적으로 fireEvent로 구현됨)
- 하지만 fireEvent보다 실제 사용자가 수행하는 것과 더 유사하게 이벤트를 발생시킨다.
- 해당 element에서 이벤트 호출 시, 실제 브라우저에서 발생하는 모든 이벤트들을 같이 발생시킨다.
- ex: 실제 사용자가 button을 click할 때, click뿐만 아니라 hover 등 다른 유저 이벤트들이 발생한다. userEvent를 사용하면 모든 이벤트들이 발생한다.
userEvent click의 내부코드는 아래와 같다.
function click(element, init, {skipHover = false, clickCount = 0} = {}) {
if (!skipHover) hover(element, init)
switch (element.tagName) {
case 'LABEL':
clickLabel(element, init, {clickCount})
break
case 'INPUT':
if (element.type === 'checkbox' || element.type === 'radio') {
clickBooleanElement(element, init, {clickCount})
} else {
clickElement(element, init, {clickCount})
}
break
default:
clickElement(element, init, {clickCount})
}
}
위 fireEvent사용 코드를 아래 userEvent로 변경해보자.
import { render, screen, fireEvent } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
test("type='submit'으로 지정된 버튼 클릭 시, form이 제출됨", async () => {
const handleSubmit = vi.fn();
const user = userEvent.setup();
render(
<form onSubmit={handleSubmit}>
<Button type="submit" variant="solid">
Submit Button
</Button>
</form>,
);
const submitButton = screen.getByText("Submit Button");
await user.click(submitButton);
expect(handleSubmit).toHaveBeenCalledTimes(1);
});
** @testing-library/user-event의 버전14부터 모든 API가 비동기함수로 바뀌었다. 따라서 async/await를 사용해야 동작 가능
참고사이트
react-testing-library 의 fireEvent 를 userEvent로 마이그레이션 하기 with Antd
이번 글에서는 사내 백오피스 서비스에 프론트엔드 테스트를 붙이고, 마이그레이션한 경험을 공유 드리고자 합니다.
medium.com
- https://www.daleseo.com/react-testing-library/
React Testing Library 사용법
Engineering Blog by Dale Seo
www.daleseo.com
- https://www.daleseo.com/testing-library-user-agent/
React Testing Library 유저 이벤트 처리
Engineering Blog by Dale Seo
www.daleseo.com