단위 테스트

Publish date: 2022-05-16
Tags: test tdd

인상 깊은 단락

p30

대부분의 프로그래머는 단위 테스트를 실천하고 중요성을 알고 있다. 단위테스트를 적용해야하지는 더 이상 논쟁거리가 아니다.

논쟁은 ‘단위 테스트를 작성해야 하는가?‘에서 ‘좋은 단위 테스트를 작성하는 것은 어떤 의미인가?‘로 바뀌었다.

p32

테스트하기 쉬운 코드는 좋은 코드의 필요조건이지만 충분 조건은 아니다.

코드를 단위 테스트하기 어렵다면 코드 개선이 반드시 필요하다는 것을 의미한다.

코드베이스를 쉽게 단위 테스트할 수 있다고 해도 반드시 코드 품질이 좋은 것을 의미하지는 않는다.

p45

다시 말하면, 커버리지 지표는 좋은 부정 지표이지만 나쁜 긍정 지표다. 커버리지 숫자가 낮으면(예: 60% 미만) 문제 징후라 할 수 있다. 코드베이스에 테스트되지 않은 코드가 많다는 뜻이다. 그러나 높은 숫자도 별 의미는 없다.

p61

공유 의존성, 비공개 의존성, 프로세스 외부 의존성

p63

‘휘발성 의존성(volatile dependency)’ 개념 설명. Dependency Injection Principles, Practices, and Patterns 책에 나온 개념.

p64

런던파와 고전파의 차이

격리 주체단위의 크기테스트 대역 사용 대상
런던파단위단일 클래스불변 의존성 외 모든 의존성
고전파단위 테스트단일 클래스 또는 클래스 세트공유 의존성

p70

테스트는 해결하는 데 도움이 되는 문제에 대한 이야기를 들려줘야 하며, 이 이야기는 프로그래머가 아닌 일반 사람들에게 응집도가 높고 의미가 있어야 한다.

예로 ‘우리집 강아지를 부르면, 바로 나에게 온다.’

p73

런던 스타일은 고전 스타일보다 테스트가 구현에 더 자주 결합되는 편이다.

단위 테스트의 정의

  • 작은 코드 조각을 검증하고
  • 빠르게 수행하고
  • 격리된 방식으로 처리한다.

p75

엔드 투 엔드 테스트는 통합 테스트의 일부다. 엔드 투 엔드 테스트도 코드가 프르세스 외부 종속성과 함께 어떻게 동작하는지 검증한다. 엔드 투 엔드 테스트와 통합 테스트 간의 차이점은 엔드 투 엔드 테스트가 일반적으로 의존성을 더 많이 포함한다는 것이다.

따라서 엔드 투 엔드라는 명칭은 모든 외부 애플레킹션을 포함해 시스템을 최종 사용자의 관점에서 검증하는 것을 의미한다.

p77

런던파 테스트의 가장 큰 문제는 과잉 명세, 즉 SUT 세부 구현에 결합된 테스트 문제다.

p83

통합 테스트에서는 실행 구절을 여러 개 두는 것이 괜찮을 때도 있다.

if 문은 테스트가 한 번에 너무 많은 것을 검증한다는 표시다.

p98

단위 테스트 명명지침

엄격한 명명 정책을 따르지 않는다. … 표현의 자유를 허용하자

p100

테스트 메서드 이름에 SUT의 메서드 이름을 포함하지 말라고 저자는 주장.

p101

테스트 메서드 이름에서 should be를 is로 바꾸는 사례

p134

간단한 테스트는 우수한 리팩터링 내성과 빠른 피드백을 제공하지만 회귀 방지 장치가 없다.

p138

최상의 테스트는 유지 보수성과 리팩터링 내성을 최대한 갖기 때문에 항상 이 두 특성을 최대화하도록 노력해야 한다. 따라서 회귀 방지와 빠른 피드백 사잉의 선택으로 절충이 귀결된다.

p141

단위 테스트조차도 리팩토링 내성을 양보해서는 안 된다.

엔드 투 엔드 테스트는 회귀 방지에 유리하고, 단위 테스트는 빠른 피드백을 강조하며, 통합 테스트는 그 중간에 있다.

p143

테스트를 작성할 때는 블랙박스 테스트가 바람직하지만, 테스트를 분석할 때는 화이트박스 방법을 사용할 수 있다.

p145

검증문을 작성할 때 제품 코드에 의존하지 말라. 테스트에서 별도의 리터럴과 상수 집합을 사용하라. 필요하면 리터럴과 상수를 복제하라.

p150

목은 SUT와 관련 의존성 간의 상호 작용을 모방하고 검사하는 반면, 스텁은 모방만 한다.

p152

즉, 스텁은 SUT가 출력을 생성하도록 입력을 제공한다.

스텁과의 상호 작용을 검증하는 것은 취약한 테스트를 야기하는 일반적인 안티 패턴이다.

p156

즉, 테스트는 ‘어떻게'가 아니라 ‘무엇'에 중점을 둬야 한다.

p163

캡슐화는 궁극적으로 단위 테스트와 동일한 목표를 달성한다. 즉, 소프트웨어 프로젝트의 지속적인 성장을 가능하게 하는 것이다.

p169

각 테스트는 도메인 전문가에게 의미 있는 이야기를 전달해야 하며, 그렇지 않으면 테스트가 구현 세부 사항과 결합돼 있으므로 불안정하다는 강한 암시다.

p179

클래스 간의 통신을 검증하는 것은 두뇌의 뉴런이 서로 통과하는 신호를 측정해 사람의 행동을 유추하는 것과 유사하다. 이러한 세부 수준은 너무 세밀하다. 중요한 것은 클라이언트 목표로 거슬러 알라갈 수 있는 동작이다. 클라이언트는 도움을 청할 때 두뇌의 어떤 뉴런이 켜지는지 신경 쓰지 않는다.

p190

상태기반 테스트는 일반적으로 거짓 양성이 되기 쉽다.

p199

함수형 프로그래밍의 목표는 부작용을 완전히 제거하는 것이 아니라 비즈니스 로직을 처리하는 코드와 부작용을 일으키는 코드를 분리하는 것이다.

p201

목표는 출력 기반 테스트로 함수형 코어를 두루 다루고 가변 셀을 훨씬 더 적은 수의 통합 테스트에 맡기는 것이다.

p202

마이클 페더스(Michael Feathers)의 문장을 인용

객체지향 프로그래밍은 작동 부분을 캡슐화해 코드를 이해할 수 있게 한다. 함수형 프로그래밍은 작동 부분을 최소화해 코드를 이해할 수 있게 한다.

p203

가변 셀에서 불면 코어를 완전히 떼어내 셀이 제공하는 입력을 단순한 값으로 모방할 수 있다.

p249

Parameterized test 예제

p281

가치가 충분하지 않은 테스트는 테스트 스위트에 있어서는 안 된다.

p284

하지만 배포 후 프로젝트의 상태 점검을 위해 한 개 또는 두 개 정도의 중요한 엔드 투 엔드 테스트를 작성할 수 있다.

p288

단일 구현을 위한 인터페이스는 추상화가 아니며, 해당 인터페이스를 구현하는 구체 클래스보다 결합도가 낮지 않다.

p289

진정한 추상화(구현이 둘 이상인 추상화)는 목과 상관없이 인터페이스로 나타낼 수 있다. 그러나 목 대체 이외의 이유로 단일 구현을 위해 인터페이스를 도입하는 것은 YAGNI에 위배된다.

p291

도메인 모델은 프로젝트가 해결하고자 하는 문제에 대한 도메인 지식의 모음이다.

p297

3장에서 살펴봤듯이, 테스트에서 두 개 이상의 준비나 싫랭 또는 검증 구절을 두는 것은 ‘코드 악취'에 해당한다.

p298

‘로깅을 테스트해야하는가?’ 단락.

로깅을 보는 사람이 개발자외에도 있다면 테스트해야 한다고 함. (감상) ‘사람'외에 다른 시스템이 로그 파일로부터 정보를 파싱해서 읽어가는 경우에도 마찬가지 일듯

p300

그러나 ILogger 인터페이스를 목으로 처리하지 말라. 지원 로깅은 비즈니스 요구사항이므로, 해당 요구 사항을 코드베이스에 명시적으로 반영하라.

p308

정적 메서드를 통해 Logger를 얻어와서 비공개 정적 필드에 저장하는 방식을 ‘앰비언트 컨텍스트'로 분류. Dependency Injection Principles, Practices, and Patterns 책에 나온 개념.

‘앰비언트 컨텍스트'의 단점

p325

오히려 ‘단위'라는 용어는 코드 단위가 아니라 동작 단위를 의미한다.

p327

보유 타임만 목으로 처리하고 외부 라이브러리는 Adapter를 통해 사용하고 Adapter를 목처리하라는 가이드. Growing Object-Oriented Software, Guided by Tests 에 나온 개념.

Adapter가 anti-corruption layer 역할.

p329

목의 수는 비관리 의존성의 수에 따라 달라진다.

p380

처음에는 직관적이지 않아 보일 수 잇지만, 단위 테스트에서는 예상 결과를 하드코딩하는 것이 좋다.

p335

데이터베이스 연동 테스트 기법

마이그레이션 기반 방식은 초기에는 구현하고 유지 보수하기가 어렵지만 장기적으로 상태 기반 방식보다 훨씬 효과적이다.

p338

결과적으로 상태 기반 방식은 대다수의 프로젝트에서 실용적이지 않다.

comments powered by Disqus