Bun 의 테스트 러너는 React Testing Library 와 happy-dom 을 포함한 기존 구성요소 및 DOM 테스트 라이브러리와 잘 작동합니다.
happy-dom
프론트엔드 코드와 구성요소에 대한 헤드리스 테스트를 작성하려면 happy-dom 을 권장합니다. Happy DOM 은 HTML 과 DOM API 의 완전한 세트를 일반 JavaScript 로 구현하여 높은 충실도로 브라우저 환경을 시뮬레이션할 수 있게 합니다.
시작하려면 @happy-dom/global-registrator 패키지를 dev dependency 로 설치하세요.
bun add -d @happy-dom/global-registrator테스트 실행 전에 happy-dom globals 를 등록하기 위해 Bun 의 프리로드 기능을 사용할 것입니다. 이 단계는 document 와 같은 브라우저 API 를 전역 범위에서 사용할 수 있게 합니다. 프로젝트 루트에 happydom.ts 라는 파일을 생성하고 다음 코드를 추가하세요.
import { GlobalRegistrator } from "@happy-dom/global-registrator";
GlobalRegistrator.register();bun test 전에 이 파일을 프리로드하려면 bunfig.toml 파일을 열거나 생성하고 다음 줄을 추가하세요.
[test]
preload = ["./happydom.ts"]이것은 bun test 를 실행할 때 happydom.ts 를 실행합니다. 이제 document 와 window 와 같은 브라우저 API 를 사용하는 테스트를 작성할 수 있습니다.
import { test, expect } from "bun:test";
test("dom 테스트", () => {
document.body.innerHTML = `<button>내 버튼</button>`;
const button = document.querySelector("button");
expect(button?.innerText).toEqual("내 버튼");
});TypeScript 지원
tsconfig.json 설정에 따라 위의 코드에서 "Cannot find name 'document'" 타입 오류가 표시될 수 있습니다. document 와 다른 브라우저 API 에 대한 타입을 "주입"하려면 테스트 파일 상단에 다음 triple-slash 지시문을 추가하세요.
/// <reference lib="dom" />
import { test, expect } from "bun:test";
test("dom 테스트", () => {
document.body.innerHTML = `<button>내 버튼</button>`;
const button = document.querySelector("button");
expect(button?.innerText).toEqual("내 버튼");
});bun test 로 이 테스트를 실행해 봅시다.
bun testbun test v1.3.3
dom.test.ts:
✓ dom test [0.82ms]
1 pass
0 fail
1 expect() calls
Ran 1 tests across 1 files. 1 total [125.00ms]React Testing Library
Bun 은 React 구성요소 테스트를 위해 React Testing Library 와 원활하게 작동합니다. 위에서 보여준 대로 happy-dom 을 설정한 후 React Testing Library 를 정상적으로 설치하고 사용할 수 있습니다.
bun add -d @testing-library/react @testing-library/jest-dom/// <reference lib="dom" />
import { test, expect } from 'bun:test';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
function Button({ children }: { children: React.ReactNode }) {
return <button>{children}</button>;
}
test('버튼 렌더링', () => {
render(<Button>클릭하세요</Button>);
expect(screen.getByRole('button')).toHaveTextContent('클릭하세요');
});고급 DOM 테스트
커스텀 요소
동일한 설정을 사용하여 커스텀 요소와 웹 구성요소를 테스트할 수 있습니다.
/// <reference lib="dom" />
import { test, expect } from "bun:test";
test("커스텀 요소", () => {
// 커스텀 요소 정의
class MyElement extends HTMLElement {
constructor() {
super();
this.innerHTML = "<p>커스텀 요소 콘텐츠</p>";
}
}
customElements.define("my-element", MyElement);
// 테스트에서 사용
document.body.innerHTML = "<my-element></my-element>";
const element = document.querySelector("my-element");
expect(element?.innerHTML).toBe("<p>커스텀 요소 콘텐츠</p>");
});이벤트 테스트
DOM 이벤트와 사용자 상호작용을 테스트하세요.
/// <reference lib="dom" />
import { test, expect } from "bun:test";
test("버튼 클릭 이벤트", () => {
let clicked = false;
document.body.innerHTML = '<button id="test-btn">클릭하세요</button>';
const button = document.getElementById("test-btn");
button?.addEventListener("click", () => {
clicked = true;
});
button?.click();
expect(clicked).toBe(true);
});구성 팁
전역 설정
더 복잡한 DOM 테스트 설정을 위해 더 포괄적인 프리로드 파일을 생성할 수 있습니다.
import { GlobalRegistrator } from "@happy-dom/global-registrator";
import "@testing-library/jest-dom";
// happy-dom globals 등록
GlobalRegistrator.register();
// 여기에 전역 테스트 구성 추가
global.ResizeObserver = class ResizeObserver {
observe() {}
unobserve() {}
disconnect() {}
};
// 필요에 따라 다른 API 목
Object.defineProperty(window, "matchMedia", {
writable: true,
value: jest.fn().mockImplementation(query => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn(),
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});그런 다음 bunfig.toml 을 업데이트하세요.
[test]
preload = ["./test-setup.ts"]문제 해결
일반적인 문제
DOM API 에 대한 TypeScript 오류: 테스트 파일 상단에 /// <reference lib="dom" /> 지시문을 포함했는지 확인하세요.
누락된 globals: @happy-dom/global-registrator 가 프리로드 파일에서 올바르게 가져오고 등록되었는지 확인하세요.
React 구성요소 렌더링 문제: @testing-library/react 을 설치했고 happy-dom 이 올바르게 설정되었는지 확인하세요.
성능 고려사항
Happy-dom 은 빠르지만 매우 대규모 테스트 스위트의 경우 다음을 원할 수 있습니다.
beforeEach를 사용하여 테스트 간 DOM 상태 재설정- 단일 테스트에서 너무 많은 DOM 요소 생성 피하기
- 테스트 라이브러리의
cleanup함수 사용 고려
import { afterEach } from "bun:test";
import { cleanup } from "@testing-library/react";
afterEach(() => {
cleanup();
document.body.innerHTML = "";
});