테스트 주도 개발로 배우는 객체 지향 설계와 실천

이진호·2023년 5월 20일
0

logs

목록 보기
2/3
post-thumbnail

테스트 주도 개발의 핵심은 무엇인가?

1.1 학습 과정으로서의 소프트웨어 개발

  • 프로젝트에서는 예상치 못한 요소가 많음.
  • 불확실성을 해결하는 데 도움이 될 프로세스가 필요.

1.2 피드백은 가장 기본적인 도구다

  • 경험에 의거한 피드백
  • 반복적인 활동 주기
  • 점진적이고 반복적인 개발

1.3 변화를 돕는 실천법

  • 회귀 오류를 잡아줄 꾸준한 테스트 - 자동화된 테스트
  • 코드를 가능한 한 단순하게 유지 - 꾸준한 리팩터링
  • 테스트 주도 개발
    • 코드를 작성하기 전에 테스트를 작성
    • 테스트를 설계 활동으로 변경.
  • 자동화된 회귀 테스트라는 안전망.

1.4 테스트 주도 개발 간단 정리

TDD 핵심 주기

TDD 핵심 주기

  1. 테스트 작성
  2. 테스트가 동작하게 만드는 코드 작성
  3. 단순한 구현으로 리팩터링

테스트 작성의 장점

  • 작업에 대한 인수 조건이 명확해짐.
  • 느슨하게 결합된 구성 요소 작성.
  • 코드에 대한 실행 가능한 설명 추가.
  • 완전한 회귀 스위트 증가

테스트 실행의 장점

  • 오류를 탐지
  • 과도한 최적화, 불필요한 기능 추가를 방지

테스트 주도 개발의 황금률 - 실패하는 테스트 없이는 새 기능을 작성하지 말라.

1.5 좀 더 큰 그림

언제 코드 작성을 멈춰야 하는가? - 실패하는 테스트로 시작해야 하는 이유

인수 테스트(acceptance test)

인수 테스트

  • 만들고자 하는 기능을 시험하는 테스트.
  • 실패하는 동안은 해당 기능이 구현되지 않았음을 보임.
  • 직접 관련된 코드만 작성하게 유도.

1.6 전 구간 테스트

  • 인수 테스트에서는 시스템 전 구간을 테스트해야 함.
  • 전 구간 테스트(end-to-end test)는 외부에서 유입되는 시스템(사용자 인터페이스를 통하거나 서드 파티 시스템에서 온 것처럼 메시지를 전송하거나 웹 서비스를 호출하거나 보고서를 구문 분석하는 등의 방식)과 상호작용.

1.7 테스트의 수준

  • 인수 테스트: 전체 시스템이 동작하는가?
  • 통합 테스트: 변경할 수 없는 코드를 대상으로 코드가 동작하는가?
  • 단위 테스트: 객체가 제대로 동작하는가? 객체를 이용하기가 편리한가?

1.8 외부 품질과 내부 품질

외부 품질과 내부 품질의 구분

  • 외부 품질: 시스템이 고객과 사용자의 요구를 얼마나 잘 충족하는가(기능, 신뢰성, 가용성, 응답성 등)
  • 내부 품질: 시스템이 개발자와 관리자의 요구를 얼마나 잘 충족하는가(이해하기 쉬운가, 변경하기 쉬운가 등)
  • 전구간 테스트 - 시스템의 외부 품질 파악 가능.
  • 단위 테스트 - 시스템의 내부 품질 파악 가능.

철저한 단위 테스트

  • 철저한 단위 테스트는 내부 품질을 개선하는 데 도움.
  • 테스트 픽스처에서 해당 단위를 시스템 바깥에서 실행할 수 있게 구조화를 유도.
  • 좋은 설계
    • 느슨한 결합
    • 높은 응집력

테스트 주도 개발의 핵심은 무엇인가?

2.1 객체망

객체 지향 설계는 객체 자체보다 객체 간의 의사소통에 더 집중

  • 중요한 것은 메시지 전달
  • 객체는 메시지로 의사소통. 메시지를 보낸 객체에 값이나 예외를 반환.
  • 자신이 이해할 수 있는 메시지를 처리하는 메서드(method)가 존재.
  • 내부 상태를 캡슐화.

객체 지향 시스템은 협업하는 객체의 망으로 구성

  • 시스템은 객체를 생성해 서로 메시지를 주고받을 수 있게 조립하는 과정을 거쳐 만들어짐.
  • 시스템에 포함된 객체의 구성을 변경해 시스템 작동 방식을 변경할 수 있음.
    • 선언적 정의(declarative): 객체 구성을 관리할 목적으로 작성하는 코드

2.2 값과 객체

값(value)

  • 변하지 않는 양이나 크기를 의미
  • 양이 고정된 불변 인스턴스
  • 상태(값)이 같으면 동일

객체(object)

  • 시간이 지남에 따라 상태가 변하며, 식별자(identity)가 있는 계산 절차(computational process)를 의미
  • 변경 가능한 상태를 가지며, 시간의 추이에 따른 객체의 행위를 나타냄.
  • 식별자가 같아야 동일

2.3 메시지를 따르라

  • 다른 객체와 쉽계 관계를 맺을 수 있게 객체를 설계하면 고수준의 선언적 접근법이 주는 혜택을 누릴 수 있음.
  • 객체는 일반적인 의사소통 패턴을 따르고 객체 간의 의존성은 명시적이어야 함.

역할, 책임, 협력자

  • 역할: 관련된 책임의 집합
  • 책임: 어떤 과업을 수행하거나 정보를 알아야 할 의무
  • 협력: 객체나 역할의 상호 작용
  • 객체는 하나 이상의 역할을 구현한 것.

2.4 묻지 말고 말하라

디미터 법칙(Law of Demeter)

  • 객체는 내부적으로 보유하고 있거나 메시지를 통해 확보한 정보만 가지고 의사 결정을 내려야 함.

2.5 그래도 가끔은 물어라

값과 컬렉션으로부터 정보를 가져오거나 팩터리를 이용해 새 객체를 생성할 때는 물어도 됨.

2.6 협력 객체의 단위 테스트

객체가 호출될 떄 이웃 객체에 메시지를 보내는 경우, 이웃 객체의 내부 상태를 드러내지 않고 메시지가 올바르게 수행되는지 테스트하는 법.

이웃 객체를 목 객체(mock object)로 대체.

  • 대상 객체가 가짜 이웃과 어떻게 상호 작용할지 지정 가능 - 예상 구문(exprectation)
  • 목 객체가 예상대로 호출됐는지 단정.
  • 나머지 테스트가 동작하는 데 필요한 행위(스텁)을 구현할 수 있음.

2.7 목 객체를 활용한 TDD 지원

  • 필요한 목 객체 생성
  • 대상 객체를 포함한 실제 객체 생성
  • 대상 객체에서 목 객체가 어떻게 호출될지 예상하는 바를 기술
  • 대상 객체에서 유발(trigger) 메서드(하나 또는 여러개)를 호출
  • 결과 값이 유효하고 예상되는 메서드 호출이 모두 일어났는지 확인

도구 소개

3.2 간략한 JUnit 4 소개

3.2.4 테스트 팩스처

  • 테스트 픽스처(test fixture): 테스트가 시작할 때 존재하는 고정된 상태.
  • 테스트가 반복 가능함을 보장.
  • 테스트가 실행되기 전에 준비(set up) 테스트 실행이 완료된 후 정리(tear down)

3.3 햄크레스트 매처와 aseertThat()

  • 매칭 조건을 선언적으로 작성하는 프레임워크

3.4 jMock2: 목 객체

  • 테스트 대상 객체가 상호 작용 중인 목 객체를 어떻게 호출하고 목 객체가 거기에 반응해 어떻게 동작해야 할지를 지정하는 고수준 API를 제공

출처

0개의 댓글