테스트하기 쉬운 코드는 테스트 파일을 많이 붙인 코드가 아니라, 변경했을 때 어디를 확인해야 하는지 분명한 코드에 가깝다. 특히 프론트엔드에서는 DOM, API 호출, 전역 상태가 한 함수 안에 섞이면 테스트도 어려워지고 장애가 났을 때 원인도 늦게 잡힌다.
이 글은 프론트엔드 코드를 기준으로 테스트하기 쉬운 구조를 만들 때 자주 보는 조건을 정리한다.
같은 입력에 대해 항상 같은 출력을 반환하고, 외부 상태를 바꾸지 않는 함수는 가장 테스트하기 쉽다.
// 순수 함수 예시
function add(a: number, b: number): number {
return a + b;
}
하나의 함수나 모듈이 하나의 역할만 맡으면 테스트 범위도 작아진다.
예시 (나쁜 예):
async function fetchAndRenderUser(id: string) {
const res = await fetch(`/api/users/${id}`);
const data = await res.json();
document.querySelector("#username").textContent = data.name;
}
개선된 예:
async function fetchUser(id: string) {
const res = await fetch(`/api/users/${id}`);
return await res.json();
}
function renderUser(user: { name: string }) {
document.querySelector("#username").textContent = user.name;
}
테스트 용이성:
let count = 0;
function unpredictable() {
return ++count;
}
function predictable(a: number, b: number): number {
return a + b;
}
지양해야 하는 예:
private → public으로 변경권장하는 접근:
| 조건 | 설명 |
|---|---|
| 순수 함수 | 외부 상태에 의존하지 않음, 독립적인 테스트 가능 |
| 단일 책임 원칙 | 하나의 역할만 하도록 설계, 테스트가 명확해짐 |
| 예측 가능한 코드 | 테스트 시 의도치 않은 결과 방지 |
| 리팩토링 관점 | 테스트가 어렵다면 코드 자체를 개선할 시점 |