All'alba vincerò

At dawn, I will win!

기타

TDD(Test Driven Development) 개발 방법론: 테스트 먼저 작성 후 개발하기

나디아 Nadia 2024. 12. 31. 13:31

TDD (Test Driven Development)

: 테스트 코드를 먼저 작성하고, 그 테스트를 통과하는 실제 코드를 작성하는 개발 방법론

  • 짧은 개발 주기의 반복에 의존하는 개발 프로세스로, 애자일 방법론 중 하나인 eXtream Programming(XP)의 'Test-First' 개념에 기반을 둔 단순한 설계를 중요시한다.
  • 소프트웨어의 품질, 성능, 신뢰성을 평가하는 과정
  • 프로그램 실행을 통해 오류를 발견하고 수정하는 활동
  • 예상 결과와 실제 결과를 비교 및 검증
eXtream Programming(XP) 

미래에 대한 예측을 최대한 하지 않고, 지속적으로 프로토타입을 완성하는 애자일 방법론 중 하나이다. 
이 방법론은 추가 요구사항이 생기더라도, 실시간으로 반영할 수 있다. 

 

 

 

TDD의 기본 원칙

  • 아래 과정은 Red-Green-Refactor 사이클로 반복되며, 이를 통해 점진적으로 품질 높은 코드를 만들어나간다.

  1. 테스트를 먼저 작성한다.
    • 구현하려는 기능의 목표를 명확히 하기 위해 먼저 테스트 코드를 작성한다.
    • 테스트는 실패 상태로 시작해야 한다.
  2. 테스트를 통과하는 최소한의 코드를 작성한다.
    • 테스트를 통과하는 데 필요한 최소한의 코드만 작성하며, 불필요한 기능은 포함하지 않는다.
    • 단순히 테스트 성공을 목표로 코드를 작성한다.
  3. 리팩토링을 한다.
    • 테스트를 통과한 후 코드의 가독성과 효율성을 높이기 위해 리팩토링한다.
    • 중복 코드를 제거하고 구조를 개선하며, 테스트가 성공하는 상태를 유지한다.

 

 

 

TDD 개발주기

  • TDD 주기는 테스트, 코드 작성, 리팩토링의 반복으로, 코드 품질을 점진적으로 향상시킨다.
  • 이 과정을 통해 불필요한 설계를 피하고, 정확한 요구 사항에 집중할 수 있다.

1. Red 단계

  • 실패하는 테스트 코드를 작성한다.
  • 구현하려는 기능에 대한 테스트를 먼저 작성하며, 테스트는 실패 상태로 시작한다.
  • 중요한 점은 실제 코드를 작성하기 전에 테스트 코드를 먼저 작성하는 것이다.

 

2. Green 단계

  • 테스트를 통과하는 최소한의 실제 코드를 작성한다.
  • 실패한 테스트를 통과할 수 있도록 최소한의 코드만 작성한다.
  • 이 단계의 목표는 테스트를 성공시키는 것이므로,  품질 고려는 최소화한다.

 

3. Refactor(Yellow) 단계

  • 리팩토링을 수행한다.
  • 중복 코드를 제거하고, 코드를 일반화하여 가독성과 효율성을 개선한다.
  • 중요한 점은 리팩토링을 통해 테스트가 성공하는 상태를 유지하는 것이다.

 

 

 

일반 개발 방식  vs  TDD 개발 방식

 

일반 개발 방식

  • 일반적인 개발 방식은 요구사항 분석 → 설계 → 개발 → 테스트 → 배포 단계를 따르는 주기를 갖는다.

 

위험 요소

  1. 소비자의 요구사항이 명확하지 않을 수 있다.
    • 초기 단계에서 완벽한 설계를 만드는 것은 어려움이 있다.
  2. 코드 품질 저하 가능성
    • 재설계 과정에서 불필요하거나 중복된 코드가 남을 가능성이 커진다.
    • 결과적으로 코드 재사용이 어려워지고 관리 및 유지보수가 복잡해진다.
  3. 버그 검출 능력 저하
    • 프로젝트 규모가 커질수록, 작은 수정에도 모든 기능을 테스트해야 하므로 전체적인 버그를 발견하기 어려워진다.
  4. 테스트 비용 증가
    • 모든 기능을 다시 테스트해야 하기 때문에 자체 테스트 비용이 크게 증가한다.

 

 

위험 요소가 생기는 원인

  • 초기 설계가 완벽할 수 없고, 프로젝트 진행 중 고객 요구사항 변경, 디자인 오류 등 여러 조건의 문제가 발생하기 때문이다.
  • 이 과정에서 재설계가 필요하고, 코드 삽입, 수정, 삭제가 반복되면서 코드의 품질이 저하되고 관리가 어려워진다.

 

결론

  • 코드 재사용이 어렵고, 관리가 복잡해져 유지보수가 점점 더 어려워진다.
  • 작은 수정에도 전체 테스트가 필요하며, 이로 인해 버그 검출 능력이 저하되고 테스트 비용이 증가한다.

 

 

 

TDD 개발 방식

  • TDD는 테스트 코드를 먼저 작성한 후 실제 코드를 작성하는 방식이다.
    • 반면, 일반적인 개발 방식은 보통 설계 후에 코드 작성과 테스트가 진행된다.

 

개발 과정

  1. 설계 단계에서 프로그래밍 목적과 테스트할 내용을 미리 정의해야 한다.
  2. 테스트 코드를 작성하고, 코드 작성 중 발생하는 버그나 수정 사항은 테스트 케이스에 추가하고 설계를 개선한다.
  3. 이후 테스트가 통과된 코드만 실제 코드 개발 단계에서 작성한다.

 

장점

  • 반복적인 단계를 통해 자연스럽게 코드의 버그가 줄어들고, 소스코드는 간결해집니다.
  • 테스트 케이스 작성 과정에서 설계가 자연스럽게 개선되며, 이로 인해 재설계 시간이 절감됩니다.

 

 

 

TDD의 장단점

장점 단점
  1. 코드의 품질이 향상된다.
  2. 요구사항을 명확히 이해할 수 있다.
  3. 유지보수성과 확장성이 높아진다.
  4. 디버깅 시간이 줄어든다.
  5. 코드에 대한 신뢰도가 높아진다.
  1. 초기 개발 속도가 느릴 수 있다.
  2. 테스트 작성에 추가적인 시간이 필요하다.
  3. 테스트 코드 관리 비용이 증가할 수 있다.
  4. 모든 상황을 테스트로 커버하기 어렵다.

 


Test Tools

 

1. Jest

: JavaScript용 테스트 프레임워크

  • 주로 React 애플리케이션에서 사용되며, 단위 테스트와 통합 테스트를 효율적으로 처리할 수 있다.
  • 테스트 러너, 어설션 라이브러리, 모킹(mocking) 등을 모두 제공하여, 테스트를 손쉽게 작성하고 실행할 수 있도록 돕는다.

 

장점

  • 별도의 설정 없이 바로 테스트를 작성하고 실행 가능
  • React 컴포넌트와 함께 사용할 때 직관적이고 효율적인 테스트 가능
  • 스냅샷 테스트와 모킹 기능 제공
  • 빠른 테스트 실행을 위한 병렬 처리 기능

 

특징

  • 자동화된 테스트 실행: 테스트가 자동으로 실행되며, 실패한 테스트를 쉽게 확인할 수 있다.
  • 스냅샷 테스트: UI 컴포넌트의 스냅샷을 저장하여, 이후 변경 사항을 확인할 수 있다.
  • 빠른 테스트 실행: 병렬 실행을 통해 테스트 결과를 빠르게 확인할 수 있다.
  • 모킹 기능: 외부 API 호출이나 의존성 모킹을 통해, 테스트 환경을 통제할 수 있다.
  • Zero Configuration: 기본 설정만으로 바로 사용 가능하며, 별도의 설정 없이 테스트를 실행할 수 있다.
// 테스트할 함수
function add(a, b) {
  return a + b;
}

// Jest를 사용한 단위 테스트
test('adds 1 + 2 to equal 3', () => {
  expect(add(1, 2)).toBe(3);
});

 

 

 

2. React Testing Library (RTL)

: React 애플리케이션의 UI 컴포넌트를 테스트하기 위한 라이브러리

  • RTL은 "UI가 어떻게 동작하는지"에 초점을 맞추며, 실제 사용자가 상호작용하는 방식대로 테스트를 작성할 수 있도록 돕는다.
  • 내부 구현보다는 사용자 경험 중심으로 테스트를 진행합니다.

 

장점

  • 컴포넌트의 동작을 실제 사용자처럼 테스트
  • UI가 실제로 어떻게 동작하는지 테스트
  • Jest와 통합하여 더욱 강력한 테스트 환경 구성

 

특징

  • 사용자 경험 중심: 실제 사용자가 컴포넌트를 어떻게 사용하고 상호작용하는지를 테스트한다.
  • DOM 접근: 렌더링된 컴포넌트의 DOM을 직접 조작하여 테스트를 진행한다.
  • 추천 테스트 접근: 컴포넌트 내부 구현이 아니라 UI의 동작을 테스트한다.
  • Jest와 통합: Jest와 함께 사용하여 더 효율적인 테스트 환경을 제공한다.
import { render, screen, fireEvent } from '@testing-library/react';
import MyButton from './MyButton';

test('button click changes text', () => {
  render(<MyButton />);
  const button = screen.getByRole('button');
  fireEvent.click(button);
  expect(screen.getByText('Clicked!')).toBeInTheDocument();
});

 


 

 

[기술면접] TDD(Test-Driven-Development) 방법론에 대해서

TDD(Test-Driven-Development) 방법론에 대해서 파헤쳐보자! ❓ TDD가 무엇입니까? - TDD란 Test Driven Development의 약자로 '테스트 주도 개발'이라고 한다. 반복 테스트를 이용한 소프트웨어 방법론으로, 작은

wooaoe.tistory.com

 

 

Jest

By ensuring your tests have unique global state, Jest can reliably run tests in parallel. To make things quick, Jest runs previously failed tests first and re-organizes runs based on how long test files take.

jestjs.io

 

 

React Testing Library | Testing Library

React Testing Library builds on top of DOM Testing Library by adding

testing-library.com