테스트 주도 개발(Test-Driven Development, TDD)은 테스트 코드를 먼저 작성한 후, 이를 통과하는 최소한의 기능을 구현하고, 이후 리팩토링을 반복하는 개발 방식이다.
이는 소프트웨어의 안정성과 유지보수성을 높이고, 버그를 줄이는 효과가 있다.
✅ "테스트가 실패하는 코드"를 먼저 작성
✅ 테스트를 통과할 수 있는 최소한의 코드 작성
✅ 테스트를 지속적으로 실행하며 코드 개선(리팩토링) 진행
즉, "테스트 → 기능 구현 → 리팩토링" 과정을 반복하면서 코드를 점진적으로 발전시키는 방식이다.
TDD는 세 단계로 이루어진다.
✅ 예제: Jest를 사용한 간단한 테스트
// sum.js
export function sum(a, b) {
return a + b;
}
// sum.test.js
import { sum } from "./sum";
test("1 + 2는 3이 되어야 한다", () => {
expect(sum(1, 2)).toBe(3);
});
sum 함수가 아직 없기 때문) FAIL ./sum.test.js
ReferenceError: sum is not defined
✅ sum 함수 구현
export function sum(a, b) {
return a + b;
}
PASS ./sum.test.js
✅ 예제: 불필요한 코드 제거
export const sum = (a, b) => a + b;
TDD를 적용하면 여러 가지 이점이 있다.
npm install --save-dev jest
// jest.config.js
module.exports = {
testEnvironment: "node",
};
test("3 + 5는 8이어야 한다", () => {
expect(3 + 5).toBe(8);
});
npm install --save-dev mocha chai
const { expect } = require("chai");
describe("기본 수학 테스트", function () {
it("2 + 2는 4이어야 한다", function () {
expect(2 + 2).to.equal(4);
});
});
npm install cypress --save-dev
describe("로그인 테스트", () => {
it("올바른 이메일과 비밀번호를 입력하면 로그인되어야 한다", () => {
cy.visit("/login");
cy.get("input[name=email]").type("test@example.com");
cy.get("input[name=password]").type("password123");
cy.get("button[type=submit]").click();
cy.url().should("include", "/dashboard");
});
});
💡 실제 프로젝트에서 TDD를 적용하는 방법은 다음과 같다.
TDD는 코드의 품질을 높이고, 유지보수를 쉽게 하며, 버그를 줄이는 효과적인 개발 방식이다.
처음에는 테스트 작성이 번거롭게 느껴질 수 있지만, 장기적으로 개발 속도를 높이고 코드의 안정성을 확보하는 데 도움이 된다.
Jest, Mocha, Cypress 등의 다양한 테스트 프레임워크를 활용하면 TDD를 보다 쉽게 적용할 수 있다.