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

이진호·2023년 5월 20일
0

logs

목록 보기
2/4
post-thumbnail

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

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

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

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

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

1.3 변화를 돕는 실천법

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

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

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개의 댓글