SlideShare a Scribd company logo
xUnit Test Pattern
15장. 코드 냄새
박상혁 http://pixelmine.tistory.com
    아꿈사 http://andstudy.com
15장에서 다루는 냄새
애매한 테스트
테스트 내 조건문 로직
테스트하기 힘든 코드
테스트 코드 중복
제품 코드 내 테스트 로직
15장에서 다루는 냄새
애매한 테스트
테스트 내 조건문 로직
테스트하기 힘든 코드
테스트 코드 중복
제품 코드 내 테스트 로직
애매한 테스트(Obscure Test)
 테스트를 한 눈에 이해하기 어렵다
   긴 테스트, 복잡한 테스트, 장황한 테스트


 자동테스트의 목표
   1. SUT가 어떻게 동작해야 하는가에 대한 문서역할
   2. 실행해볼 수 있는 자체 검증 명세


 테스트를 실행할 수 있게 구현하다 보면 복잡해지기 때문에 이 두
 가지 목표를 동시에 만족하기 어렵다.
애매한 테스트(Obscure Test)
 욕심쟁이 테스트
   하나의 메소드에서 너무 많은 기능을 검증하려는 테스트
 미스터리한 손님
   픽스처와 검증로직간의 인과 관계가 보이지 않는 테스트
 일반 픽스처
   기능 검증에 필요 이상으로 큰 픽스처를 생성하거나 참조한다
 관련 없는 정보
   정보가 너무 많아 실제 동작에 영향을 미치는 것이 무엇인지 파악하기 힘들다
 하드코딩된 테스트 데이터
   데이터 값이 하드 코딩돼 있어 입력과 기대 결과값 사이의 인과 관계가 애매하다
 간접 테스팅
   테스트 메소드와 SUT가 다른 객체를 통해 간접적으로 상호작용한다
애매한 테스트(Obscure Test)
 증상 : 테스트에서 검증하는 동작을 이해하기 힘들다

   이것 저것 '없는 거 빼고 전부 다' 검증한다
   어디까지가 픽스처 설치인지, 어디서부터 SUT실행부인지 알기 어렵다
   픽스처 설치나 결과 검증부가 테스트에서 볼 수 없는 정보에 의존한다
   외부 정보를 찾지 않고는 동작을 이해하기 어렵다
   필요이상으로 큰 픽스처를 구축한다
   '픽스처-SUT실행-결과값' 사이의 인과관계 파악이 힘들다
   객체에 전달되는 값 중 무엇이 기대출력에 영향을 주는지 알기 어렵다
   픽스처 설치 로직이 길고, 무엇을 검증하려는지 알기 어렵다
   테스트 검증 코드가 복잡하다
   하드코딩된 값이 어떻게 서로 관련되어 있는지 알기 어렵다
   어떤 값들이 SUT의 동작에 영향을 주는지 알기 어렵다
   검증해야 하는 객체가 아닌 다른 객체와 주로 상호작용한다
애매한 테스트(Obscure Test)
 증상 : 테스트에서 검증하는 동작을 이해하기 힘들다
               욕심쟁이 테스트(Eager Test)
   이것 저것 '없는 거 빼고 전부 다' 검증한다
   어디까지가 픽스처 설치인지, 어디서부터 SUT실행부인지 알기 어렵다
   픽스처 설치나 결과 검증부가 테스트에서 볼 수 없는 정보에 의존한다
   외부 정보를 찾지 않고는 동작을 이해하기 어렵다
   필요이상으로 큰 픽스처를 구축한다
   '픽스처-SUT실행-결과값' 사이의 인과관계 파악이 힘들다
   객체에 전달되는 값 중 무엇이 기대출력에 영향을 주는지 알기 어렵다
   픽스처 설치 로직이 길고, 무엇을 검증하려는지 알기 어렵다
   테스트 검증 코드가 복잡하다
   하드코딩된 값이 어떻게 서로 관련되어 있는지 알기 어렵다
   어떤 값들이 SUT의 동작에 영향을 주는지 알기 어렵다
   검증해야 하는 객체가 아닌 다른 객체와 주로 상호작용한다
애매한 테스트(Obscure Test)
 증상 : 테스트에서 검증하는 동작을 이해하기 힘들다
              미스터리한 손님(Mystery Guest)
   이것 저것 '없는 거 빼고 전부 다' 검증한다
   어디까지가 픽스처 설치인지, 어디서부터 SUT실행부인지 알기 어렵다
   픽스처 설치나 결과 검증부가 테스트에서 볼 수 없는 정보에 의존한다
   외부 정보를 찾지 않고는 동작을 이해하기 어렵다
   필요이상으로 큰 픽스처를 구축한다
   '픽스처-SUT실행-결과값' 사이의 인과관계 파악이 힘들다
   객체에 전달되는 값 중 무엇이 기대출력에 영향을 주는지 알기 어렵다
   픽스처 설치 로직이 길고, 무엇을 검증하려는지 알기 어렵다
   테스트 검증 코드가 복잡하다
   하드코딩된 값이 어떻게 서로 관련되어 있는지 알기 어렵다
   어떤 값들이 SUT의 동작에 영향을 주는지 알기 어렵다
   검증해야 하는 객체가 아닌 다른 객체와 주로 상호작용한다
애매한 테스트(Obscure Test)
 증상 : 테스트에서 검증하는 동작을 이해하기 힘들다
               일반 픽스처(General Fixture)
   이것 저것 '없는 거 빼고 전부 다' 검증한다
   어디까지가 픽스처 설치인지, 어디서부터 SUT실행부인지 알기 어렵다
   픽스처 설치나 결과 검증부가 테스트에서 볼 수 없는 정보에 의존한다
   외부 정보를 찾지 않고는 동작을 이해하기 어렵다
   필요이상으로 큰 픽스처를 구축한다
   '픽스처-SUT실행-결과값' 사이의 인과관계 파악이 힘들다
   객체에 전달되는 값 중 무엇이 기대출력에 영향을 주는지 알기 어렵다
   픽스처 설치 로직이 길고, 무엇을 검증하려는지 알기 어렵다
   테스트 검증 코드가 복잡하다
   하드코딩된 값이 어떻게 서로 관련되어 있는지 알기 어렵다
   어떤 값들이 SUT의 동작에 영향을 주는지 알기 어렵다
   검증해야 하는 객체가 아닌 다른 객체와 주로 상호작용한다
애매한 테스트(Obscure Test)
 증상 : 테스트에서 검증하는 동작을 이해하기 힘들다
             관련 없는 정보(Irrelevant Information)
   이것 저것 '없는 거 빼고 전부 다' 검증한다
   어디까지가 픽스처 설치인지, 어디서부터 SUT실행부인지 알기 어렵다
   픽스처 설치나 결과 검증부가 테스트에서 볼 수 없는 정보에 의존한다
   외부 정보를 찾지 않고는 동작을 이해하기 어렵다
   필요이상으로 큰 픽스처를 구축한다
   '픽스처-SUT실행-결과값' 사이의 인과관계 파악이 힘들다
   객체에 전달되는 값 중 무엇이 기대출력에 영향을 주는지 알기 어렵다
   픽스처 설치 로직이 길고, 무엇을 검증하려는지 알기 어렵다
   테스트 검증 코드가 복잡하다
   하드코딩된 값이 어떻게 서로 관련되어 있는지 알기 어렵다
   어떤 값들이 SUT의 동작에 영향을 주는지 알기 어렵다
   검증해야 하는 객체가 아닌 다른 객체와 주로 상호작용한다
애매한 테스트(Obscure Test)
 증상 : 테스트에서 검증하는 동작을 이해하기 힘들다
        하드 코딩된 테스트 데이터(Hard-Coded Test Data)
   이것 저것 '없는 거 빼고 전부 다' 검증한다
   어디까지가 픽스처 설치인지, 어디서부터 SUT실행부인지 알기 어렵다
   픽스처 설치나 결과 검증부가 테스트에서 볼 수 없는 정보에 의존한다
   외부 정보를 찾지 않고는 동작을 이해하기 어렵다
   필요이상으로 큰 픽스처를 구축한다
   '픽스처-SUT실행-결과값' 사이의 인과관계 파악이 힘들다
   객체에 전달되는 값 중 무엇이 기대출력에 영향을 주는지 알기 어렵다
   픽스처 설치 로직이 길고, 무엇을 검증하려는지 알기 어렵다
   테스트 검증 코드가 복잡하다
   하드코딩된 값이 어떻게 서로 관련되어 있는지 알기 어렵다
   어떤 값들이 SUT의 동작에 영향을 주는지 알기 어렵다
   검증해야 하는 객체가 아닌 다른 객체와 주로 상호작용한다
애매한 테스트(Obscure Test)
 • 증상 : 테스트에서 검증하는 동작을 이해하기 힘들다
                 간접 테스팅(Indirect Testing)
   –   이것 저것 '없는 거 빼고 전부 다' 검증한다
   –   어디까지가 픽스처 설치인지, 어디서부터 SUT실행부인지 알기 어렵다
   –   픽스처 설치나 결과 검증부가 테스트에서 볼 수 없는 정보에 의존한다
   –   외부 정보를 찾지 않고는 동작을 이해하기 어렵다
   –   필요이상으로 큰 픽스처를 구축한다
   –   '픽스처-SUT실행-결과값' 사이의 인과관계 파악이 힘들다
   –   객체에 전달되는 값 중 무엇이 기대출력에 영향을 주는지 알기 어렵다
   –   픽스처 설치 로직이 길고, 무엇을 검증하려는지 알기 어렵다
   –   테스트 검증 코드가 복잡하다
   –   하드코딩된 값이 어떻게 서로 관련되어 있는지 알기 어렵다
   –   어떤 값들이 SUT의 동작에 영향을 주는지 알기 어렵다
   –   검증해야 하는 객체가 아닌 다른 객체와 주로 상호작용한다
애매한 테스트(Obscure Test)
 미치는 영향

   이해하기 힘들고 유지보수가 어렵다
   문서로서의 테스트를 만들기 어렵다
   테스트 유지비용 상승한다
   버그 투성이 테스트가 된다
   테스트 디버깅 데이터를 잃게 된다
   픽스처와 기대결과 사이의 인과관계를 알기 어렵다
   변덕스러운 테스트가 생긴다
   각 테스트에서 픽스처를 어떻게 사용하는지 이해하기 힘들다
   깨지기 쉬운 픽스쳐가 된다
   느린 테스트가 될 수 있다
   공유픽스처를 쓸 때 다른 테스트에서 같은 값을 쓰는 경우 충돌이 생긴다
   깨지기 쉬운 테스트가 된다
   모든 곳을 테스트 하기 불가능하다
애매한 테스트(Obscure Test)
 미치는 영향
               욕심쟁이 테스트(Eager Test)
   이해하기 힘들고 유지보수가 어렵다
   문서로서의 테스트를 만들기 어렵다
   테스트 유지비용 상승한다
   버그 투성이 테스트가 된다
   테스트 디버깅 데이터를 잃게 된다
   픽스처와 기대결과 사이의 인과관계를 알기 어렵다
   변덕스러운 테스트가 생긴다
   각 테스트에서 픽스처를 어떻게 사용하는지 이해하기 힘들다
   깨지기 쉬운 픽스쳐가 된다
   느린 테스트가 될 수 있다
   공유픽스처를 쓸 때 다른 테스트에서 같은 값을 쓰는 경우 충돌이 생긴다
   깨지기 쉬운 테스트가 된다
   모든 곳을 테스트 하기 불가능하다
애매한 테스트(Obscure Test)
 미치는 영향
              미스터리한 손님(Mystery Guest)
   이해하기 힘들고 유지보수가 어렵다
   문서로서의 테스트를 만들기 어렵다
   테스트 유지비용 상승한다
   버그 투성이 테스트가 된다
   테스트 디버깅 데이터를 잃게 된다
   픽스처와 기대결과 사이의 인과관계를 알기 어렵다
   변덕스러운 테스트가 생긴다
   각 테스트에서 픽스처를 어떻게 사용하는지 이해하기 힘들다
   깨지기 쉬운 픽스쳐가 된다
   느린 테스트가 될 수 있다
   공유픽스처를 쓸 때 다른 테스트에서 같은 값을 쓰는 경우 충돌이 생긴다
   깨지기 쉬운 테스트가 된다
   모든 곳을 테스트 하기 불가능하다
애매한 테스트(Obscure Test)
 미치는 영향
               일반 픽스처(General Fixture)
   이해하기 힘들고 유지보수가 어렵다
   문서로서의 테스트를 만들기 어렵다
   테스트 유지비용 상승한다
   버그 투성이 테스트가 된다
   테스트 디버깅 데이터를 잃게 된다
   픽스처와 기대결과 사이의 인과관계를 알기 어렵다
   변덕스러운 테스트가 생긴다
   각 테스트에서 픽스처를 어떻게 사용하는지 이해하기 힘들다
   깨지기 쉬운 픽스쳐가 된다
   느린 테스트가 될 수 있다
   공유픽스처를 쓸 때 다른 테스트에서 같은 값을 쓰는 경우 충돌이 생긴다
   깨지기 쉬운 테스트가 된다
   모든 곳을 테스트 하기 불가능하다
애매한 테스트(Obscure Test)
 미치는 영향
             관련 없는 정보(Irrelevant Information)
   이해하기 힘들고 유지보수가 어렵다
   문서로서의 테스트를 만들기 어렵다
   테스트 유지비용 상승한다
   버그 투성이 테스트가 된다
   테스트 디버깅 데이터를 잃게 된다
   픽스처와 기대결과 사이의 인과관계를 알기 어렵다
   변덕스러운 테스트가 생긴다
   각 테스트에서 픽스처를 어떻게 사용하는지 이해하기 힘들다
   깨지기 쉬운 픽스쳐가 된다
   느린 테스트가 될 수 있다
   공유픽스처를 쓸 때 다른 테스트에서 같은 값을 쓰는 경우 충돌이 생긴다
   깨지기 쉬운 테스트가 된다
   모든 곳을 테스트 하기 불가능하다
애매한 테스트(Obscure Test)
 미치는 영향
          하드 코딩된 테스트 데이터(Hard-Coded Test Data)
   이해하기 힘들고 유지보수가 어렵다
   문서로서의 테스트를 만들기 어렵다
   테스트 유지비용 상승한다
   버그 투성이 테스트가 된다
   테스트 디버깅 데이터를 잃게 된다
   픽스처와 기대결과 사이의 인과관계를 알기 어렵다
   변덕스러운 테스트가 생긴다
   각 테스트에서 픽스처를 어떻게 사용하는지 이해하기 힘들다
   깨지기 쉬운 픽스쳐가 된다
   느린 테스트가 될 수 있다
   공유픽스처를 쓸 때 다른 테스트에서 같은 값을 쓰는 경우 충돌이 생긴다
   깨지기 쉬운 테스트가 된다
   모든 곳을 테스트 하기 불가능하다
애매한 테스트(Obscure Test)
 미치는 영향
               간접 테스팅(Indirect Testing)
   이해하기 힘들고 유지보수가 어렵다
   문서로서의 테스트를 만들기 어렵다
   테스트 유지비용 상승한다
   버그 투성이 테스트가 된다
   테스트 디버깅 데이터를 잃게 된다
   픽스처와 기대결과 사이의 인과관계를 알기 어렵다
   변덕스러운 테스트가 생긴다
   각 테스트에서 픽스처를 어떻게 사용하는지 이해하기 힘들다
   깨지기 쉬운 픽스쳐가 된다
   느린 테스트가 될 수 있다
   공유픽스처를 쓸때 다른 테스트에서 같은 값을 쓰는 경우 충돌이 생긴다
   깨지기 쉬운 테스트가 된다
   모든 곳을 테스트 하기 불가능하다
애매한 테스트(Obscure Test)
 원인

   테스트 메소드에 정보가 너무 많다
   테스트 메소드에 정보가 너무 적다
   코드를 깔끔하고 간단하게 유지하려는 의지가 없다
   코드를 '그냥 인라인으로' 작성한다
   테스트가 외부자원에 의존한다
   여러 테스트를 지원하는 픽스처를 쓴다
   테스테 상관없는 리터럴 값이 너무 많다
   절차형 상태 검증을 쓴다
   잘라 붙여넣기로 테스트 로직을 재사용한다
   테스트에서 접근하려는 클래스의 SUT부분이 private이다
   – 테스트 용이성을 생각하지 않고 설계했다
애매한 테스트(Obscure Test)
 원인
                욕심쟁이 테스트(Eager Test)
   테스트 메소드에 정보가 너무 많다
   테스트 메소드에 정보가 너무 적다
   코드를 깔끔하고 간단하게 유지하려는 의지가 없다
   코드를 '그냥 인라인으로' 작성한다
   테스트가 외부자원에 의존한다
   여러 테스트를 지원하는 픽스처를 쓴다
   테스테 상관없는 리터럴 값이 너무 많다
   절차형 상태 검증을 쓴다
   잘라 붙여넣기로 테스트 로직을 재사용한다
   테스트에서 접근하려는 클래스의 SUT부분이 private이다
   테스트 용이성을 생각하지 않고 설계했다
애매한 테스트(Obscure Test)
 원인
                미스터리한 손님(Mystery Guest)
   테스트 메소드에 정보가 너무 많다
   테스트 메소드에 정보가 너무 적다
   코드를 깔끔하고 간단하게 유지하려는 의지가 없다
   코드를 '그냥 인라인으로' 작성한다
   테스트가 외부자원에 의존한다     SUT 메소드에 전달되는 외부 파일의 내용이 SUT의
   여러 테스트를 지원하는 픽스처를 쓴다 결정
                       동작을
                       리터럴키로 식별되는 DB 레코드를 읽어 객체에 쓴 뒤
   테스테 상관없는 리터럴 값이 너무 많다 테스트에서 사용하거나 SUT에 전달
                       이를
   절차형 상태 검증을 쓴다       파일에서 읽어들인 내용을 기대결과값을 검증하는 단
                       언 메소드 호출에 사용
   잘라 붙여넣기로 테스트 로직을 재사용한다
                       설치 데코레이터로 공유 픽스처를 만들고 결과 검증
   테스트에서 접근하려는 클래스의 SUT부분이 private이다
                       로직에서는 공유 픽스처의 객체들을 변수로 참조
   테스트 용이성을 생각하지 않고 설계했다 설치로 일반 픽스처를 설치하고 테스트 메소
                       암묵적
                         드에서 인스턴스 변수나 클래스 변수로 접근
애매한 테스트(Obscure Test)
 원인
                일반 픽스처(General Fixture)
   테스트 메소드에 정보가 너무 많다
   테스트 메소드에 정보가 너무 적다
   코드를 깔끔하고 간단하게 유지하려는 의지가 없다
   코드를 '그냥 인라인으로' 작성한다
   테스트가 외부자원에 의존한다
   여러 테스트를 지원하는 픽스처를 쓴다
   테스테 상관없는 리터럴 값이 너무 많다
   절차형 상태 검증을 쓴다
   잘라 붙여넣기로 테스트 로직을 재사용한다
   테스트에서 접근하려는 클래스의 SUT부분이 private이다
   테스트 용이성을 생각하지 않고 설계했다
애매한 테스트(Obscure Test)
 원인
             관련 없는 정보(Irrelevant Information)
   테스트 메소드에 정보가 너무 많다
   테스트 메소드에 정보가 너무 적다
   코드를 깔끔하고 간단하게 유지하려는 의지가 없다
   코드를 '그냥 인라인으로' 작성한다
   테스트가 외부자원에 의존한다
   여러 테스트를 지원하는 픽스처를 쓴다
   테스테 상관없는 리터럴 값이 너무 많다
   절차형 상태 검증을 쓴다
   잘라 붙여넣기로 테스트 로직을 재사용한다
   테스트에서 접근하려는 클래스의 SUT부분이 private이다
   테스트 용이성을 생각하지 않고 설계했다
애매한 테스트(Obscure Test)
 원인
         하드 코딩된 테스트 데이터(Hard-Coded Test Data)
   테스트 메소드에 정보가 너무 많다
   테스트 메소드에 정보가 너무 적다
   코드를 깔끔하고 간단하게 유지하려는 의지가 없다
   코드를 '그냥 인라인으로' 작성한다
   테스트가 외부자원에 의존한다
   여러 테스트를 지원하는 픽스처를 쓴다
   테스테 상관없는 리터럴 값이 너무 많다
   절차형 상태 검증을 쓴다
   잘라 붙여넣기로 테스트 로직을 재사용한다
   테스트에서 접근하려는 클래스의 SUT부분이 private이다
   테스트 용이성을 생각하지 않고 설계했다
애매한 테스트(Obscure Test)
 원인
                간접 테스팅(Indirect Testing)
   테스트 메소드에 정보가 너무 많다
   테스트 메소드에 정보가 너무 적다
   코드를 깔끔하고 간단하게 유지하려는 의지가 없다
   코드를 '그냥 인라인으로' 작성한다
   테스트가 외부자원에 의존한다
   여러 테스트를 지원하는 픽스처를 쓴다
   테스테 상관없는 리터럴 값이 너무 많다
   절차형 상태 검증을 쓴다
   잘라 붙여넣기로 테스트 로직을 재사용한다
   테스트에서 접근하려는 클래스의 SUT부분이 private이다
   테스트 용이성을 생각하지 않고 설계했다
애매한 테스트(Obscure Test)
 해결책

   더 좋은 결함 국소화를 제공하는 독립적인 단일 조건 테스트 스위트로 만든다
   인라인 설치로 신선한 픽스처를 쓴다
   픽스처 안의 객체들에 찾기메소드로 접근하는 것을 고려해보자
   파일 이름을 적당히 붙여 안에 어떤 데이터가 들어있는지 짐작할 수 있게 해준다
   최소 픽스처, 신선한 픽스처 사용
   테스트별로 가상의 데이터베이스 샌드박스를 만든다
   관련 있는 정보만 인자로 받는 인자를 받는 생성 메소드 호출
   설치부와 검증부에 필요한 픽스처 값을 적당히 초기화한 상수로 바꾼다
   결과 검증 로직에서 기대 객체로 한번에 단언한다
   복잡한 절차적 검증로직을 숨기는 맞춤 단언문 사용
   리터럴 상수를 다른 걸로 바꿔준다
   별개의 생성값을 써서 테스트가 실행될 때마다 다른 값을 쓰게 보장해줘야 한다
   SUT의 테스트 용이성을 위한 설계를 개선
   SUT를 간접적으로 접근해야만 한다면 SUT API 캡슐화 사용
애매한 테스트(Obscure Test)
 해결책
               욕심쟁이 테스트(Eager Test)
   더 좋은 결함 국소화를 제공하는 독립적인 단일 조건 테스트 스위트로 만든다
   인라인 설치로 신선한 픽스처를 쓴다
   픽스처 안의 객체들에 찾기메소드로 접근하는 것을 고려해보자
   파일 이름을 적당히 붙여 안에 어떤 데이터가 들어있는지 짐작할 수 있게 해준다
   최소 픽스처, 신선한 픽스처 사용
   테스트별로 가상의 데이터베이스 샌드박스를 만든다
   관련 있는 정보만 인자로 받는 인자를 받는 생성 메소드 호출
   설치부와 검증부에 필요한 픽스처 값을 적당히 초기화한 상수로 바꾼다
   결과 검증 로직에서 기대 객체로 한번에 단언한다
   복잡한 절차적 검증로직을 숨기는 맞춤 단언문 사용
   리터럴 상수를 다른 걸로 바꿔준다
   별개의 생성값을 써서 테스트가 실행될 때마다 다른 값을 쓰게 보장해줘야 한다
   SUT의 테스트 용이성을 위한 설계를 개선
   SUT를 간접적으로 접근해야만 한다면 SUT API 캡슐화 사용
애매한 테스트(Obscure Test)
 해결책
              미스터리한 손님(Mystery Guest)
   더 좋은 결함 국소화를 제공하는 독립적인 단일 조건 테스트 스위트로 만든다
   인라인 설치로 신선한 픽스처를 쓴다
   픽스처 안의 객체들에 찾기메소드로 접근하는 것을 고려해보자
   파일 이름을 잘 붙여 안에 어떤 데이터가 들어있는지 짐작할 수 있게 해준다
   최소 픽스처, 신선한 픽스처 사용
   테스트별로 가상의 데이터베이스 샌드박스를 만든다
   관련 있는 정보만 인자로 받는 인자를 받는 생성 메소드 호출
   설치부와 검증부에 필요한 픽스처 값을 적당히 초기화한 상수로 바꾼다
   결과 검증 로직에서 기대 객체로 한번에 단언한다
   복잡한 절차적 검증로직을 숨기는 맞춤 단언문 사용
   리터럴 상수를 다른 걸로 바꿔준다
   별개의 생성값을 써서 테스트가 실행될 때마다 다른 값을 쓰게 보장해줘야 한다
   SUT의 테스트 용이성을 위한 설계를 개선
   SUT를 간접적으로 접근해야만 한다면 SUT API 캡슐화 사용
애매한 테스트(Obscure Test)
 해결책
               일반 픽스처(General Fixture)
   더 좋은 결함 국소화를 제공하는 독립적인 단일 조건 테스트 스위트로 만든다
   인라인 설치로 신선한 픽스처를 쓴다
   픽스처 안의 객체들에 찾기메소드로 접근하는 것을 고려해보자
   파일 이름을 적당히 붙여 안에 어떤 데이터가 들어있는지 짐작할 수 있게 해준다
   최소 픽스처, 신선한 픽스처 사용
   테스트별로 가상의 데이터베이스 샌드박스를 만든다
   관련 있는 정보만 인자로 받는 인자를 받는 생성 메소드 호출
   설치부와 검증부에 필요한 픽스처 값을 적당히 초기화한 상수로 바꾼다
   결과 검증 로직에서 기대 객체로 한번에 단언한다
   복잡한 절차적 검증로직을 숨기는 맞춤 단언문 사용
   리터럴 상수를 다른 걸로 바꿔준다
   별개의 생성값을 써서 테스트가 실행될 때마다 다른 값을 쓰게 보장해줘야 한다
   SUT의 테스트 용이성을 위한 설계를 개선
   SUT를 간접적으로 접근해야만 한다면 SUT API 캡슐화 사용
애매한 테스트(Obscure Test)
 해결책
             관련 없는 정보(Irrelevant Information)
   더 좋은 결함 국소화를 제공하는 독립적인 단일 조건 테스트 스위트로 만든다
   인라인 설치로 신선한 픽스처를 쓴다
   픽스처 안의 객체들에 찾기메소드로 접근하는 것을 고려해보자
   파일 이름을 적당히 붙여 안에 어떤 데이터가 들어있는지 짐작할 수 있게 해준다
   최소 픽스처, 신선한 픽스처 사용
   테스트별로 가상의 데이터베이스 샌드박스를 만든다
   관련 있는 정보만 인자로 받는 인자를 받는 생성 메소드 호출
   설치부와 검증부에 필요한 픽스처 값을 적당히 초기화한 상수로 바꾼다
   결과 검증 로직에서 기대 객체로 한번에 단언한다
   복잡한 절차적 검증로직을 숨기는 맞춤 단언문 사용
   리터럴 상수를 다른 걸로 바꿔준다
   별개의 생성값을 써서 테스트가 실행될 때마다 다른 값을 쓰게 보장해줘야 한다
   SUT의 테스트 용이성을 위한 설계를 개선
   SUT를 간접적으로 접근해야만 한다면 SUT API 캡슐화 사용
애매한 테스트(Obscure Test)
 해결책
        하드 코딩된 테스트 데이터(Hard-Coded Test Data)
   더 좋은 결함 국소화를 제공하는 독립적인 단일 조건 테스트 스위트로 만든다
   인라인 설치로 신선한 픽스처를 쓴다
   픽스처 안의 객체들에 찾기메소드로 접근하는 것을 고려해보자
   파일 이름을 적당히 붙여 안에 어떤 데이터가 들어있는지 짐작할 수 있게 해준다
   최소 픽스처, 신선한 픽스처 사용
   테스트별로 가상의 데이터베이스 샌드박스를 만든다
   관련 있는 정보만 인자로 받는 인자를 받는 생성 메소드 호출
   설치부와 검증부에 필요한 픽스처 값을 적당히 초기화한 상수로 바꾼다
   결과 검증 로직에서 기대 객체로 한번에 단언한다
   복잡한 절차적 검증로직을 숨기는 맞춤 단언문 사용
   리터럴 상수를 다른 걸로 바꿔준다
   별개의 생성값을 써서 테스트가 실행될 때마다 다른 값을 쓰게 보장해줘야 한다
   SUT의 테스트 용이성을 위한 설계를 개선
   SUT를 간접적으로 접근해야만 한다면 SUT API 캡슐화 사용
애매한 테스트(Obscure Test)
 해결책
               간접 테스팅(Indirect Testing)
   더 좋은 결함 국소화를 제공하는 독립적인 단일 조건 테스트 스위트로 만든다
   인라인 설치로 신선한 픽스처를 쓴다
   픽스처 안의 객체들에 찾기메소드로 접근하는 것을 고려해보자
   파일 이름을 적당히 붙여 안에 어떤 데이터가 들어있는지 짐작할 수 있게 해준다
   최소 픽스처, 신선한 픽스처 사용
   테스트별로 가상의 데이터베이스 샌드박스를 만든다
   관련 있는 정보만 인자로 받는 인자를 받는 생성 메소드 호출
   설치부와 검증부에 필요한 픽스처 값을 적당히 초기화한 상수로 바꾼다
   결과 검증 로직에서 기대 객체로 한번에 단언한다
   복잡한 절차적 검증로직을 숨기는 맞춤 단언문 사용
   리터럴 상수를 다른 걸로 바꿔준다
   별개의 생성값을 써서 테스트가 실행될 때마다 다른 값을 쓰게 보장해줘야 한다
   SUT의 테스트 용이성을 위한 설계를 개선
   SUT를 간접적으로 접근해야만 한다면 SUT API 캡슐화 사용
15장에서 다루는 냄새
애매한 테스트
테스트 내 조건문 로직
테스트하기 힘든 코드
테스트 코드 중복
제품 코드 내 테스트 로직
테스트 내 조건문 로직(Conditional Test Logic)
 테스트에 실행 안 될 수도 있는 코드가 있다
   들쑥날쑥한 테스트 코드


 완전 자동 테스트는 다른 코드의 동작을 검증하는 코드다
 완전 자동 테스트 코드가 복잡하다면......?
 테스트를 위한 테스트......?
 테스트가 필요없을 정도로 단순하게 만드는 것이 정답

 테스트 내 조건문 로직은 필요 이상으로 테스트를 복잡하게 만드
 는 요인 중 하나다
테스트 내 조건문 로직(Conditional Test Logic)
 유연한 테스트
   언제 어디서 실행되느냐에 따라 다른 기능을 검증하는 테스트
 검증 조건문 로직
   기대 결과 검증에 조건문 사용
 테스트 내 제품 로직
 복잡한 해체
 여러 테스트 조건
테스트 내 조건문 로직(Conditional Test Logic)
 증상 : 테스트 코드 내에 반복문이나 조건문이 있다

   테스트가 상황에 따라 다른 일을 할 수 있게 조건문 로직이 들어 있다
   테스트의 결과 검증부에 조건문 로직이 들어있다
   픽스처 해체 코드가 복잡하다
   여러 입력값과 그 기대 결과값에 같은 테스트 로직 적용
테스트 내 조건문 로직(Conditional Test Logic)
 미치는 영향

   테스트 코드에서 무엇을 하는지 알기 어렵다
   테스트가 결정론적이지 않아 디버깅하기 어렵다
   어려운 작업에 대해 테스트를 정확하게 작성하기 어렵다
   테스트가 이해하기 어려워 유지보수가 힘들다
   모든 제어경로가 테스트 되었는지 알 수 없다
테스트 내 조건문 로직(Conditional Test Logic)
 원인

   SUT가 올바른 데이터를 반환하지 않았을 때의 if문 처리
   여러 객제를 한꺼번에 검증하기 위해 반복문 사용
   복잡한 객체나 다형성 데이터 구조를 검증
   테스트 픽스처나 기대 객체 초기화시 하나의 테스트에서 여러 다른 경우 검증
   존재하지 않는 픽스처 객체를 해체하지 않기 위해 if문 사용
   환경에 대한 제어능력 부족
   가비지 컬렉션 시스템이 해결해 줄 수 없는 지속적인 자원을 많이 사용
테스트 내 조건문 로직(Conditional Test Logic)
 해결책

   SUT에서 '바꿀 수 있는 의존'을 지원하게 리팩토링한다
   보호 단언문 사용
   복잡한 객체를 검증할 때는 기대객체에 동등 단언문 사용
   테스트용 동등을 정의한 맞춤 단언문 사용
   테스트 유틸리티 메소드나 공통 인자를 받는 테스트 사용
   입력된 값에 대한 계산된 값을 쓴다
   암묵적 해체, 자동 해체 사용
   신선한 픽스처, 테스트 대역을 사용해 지속되는 객체를 쓰지 않는다
15장에서 다루는 냄새
애매한 테스트
테스트 내 조건문 로직
테스트하기 힘든 코드
테스트 코드 중복
제품 코드 내 테스트 로직
테스트하기 힘든 코드(Hard-to-Test Code)
 코드가 테스트 하기 어렵다

  강하게 결합된 코드
  비동기 코드
  테스트할 수 없는 테스트 코드
테스트하기 힘든 코드(Hard-to-Test Code)
 증상

   원래부터 테스트 하기 힘든 코드
   여러 다른 클래스와 함께 테스트 해야만 하는 코드
   직접 메소드 호출로 테스트할 수 없는 클래스
   테스트 메소드의 내용이 복잡하다
   테스트가 올바른지 확신할 수 없다
테스트하기 힘든 코드(Hard-to-Test Code)
 미치는 영향

   코드의 품질을 쉽게 검증할 수 없다
   테스트 문서화에 큰 공을 들이지 않으면 품질 평가를 반복하기 어렵다
   단위 테스트가 어렵다
   테스트가 복잡하고 실행이 느려진다
   버그투성이 테스트가 되기 쉽다
   테스트 유지 비용이 비싸다
   테스트를 제대로 작성하기 어렵다
테스트하기 힘든 코드(Hard-to-Test Code)
 원인

   설계가 조잡하다
   객체지향 설계경험이 부족하다
   액티브 객체와 강하게 결합되어 있다
   데스트코드는 원래 테스트하기 어렵다
테스트하기 힘든 코드(Hard-to-Test Code)
 해결책

   결합을 분리한다 : 테스트 대역, 테스트 스텁, 모의 객체
   '레거시 코드 활용 전략'을 읽어본다
   로직과 비동기 접근 매커니즘 분리 : 대강 만든 객체
   테스트 메소드들 아주 단순하게 만든다
15장에서 다루는 냄새
애매한 테스트
테스트 내 조건문 로직
테스트하기 힘든 코드
테스트 코드 중복
제품 코드 내 테스트 로직
테스트 코드 중복(Test Code Duplication)
 여러 번 반복되는 테스트 코드
   같은 주제에 대해 약간씩 다른 시나리오로 테스트 해야 하는 경우


   '잘라 붙여넣기' 코드 재사용
   바퀴 재발명 하기
테스트 코드 중복(Test Code Duplication)
 증상

   같은 코드가 여러 테스트에서 반복된다
   한 테스트 안에서 비슷한 구문이 반복된다


 미치는 영향

   SUT메소드 의미가 변경되면 모든 복사본에 유지보수 해야한다
   테스트 유지 비용이 늘어난다
테스트 코드 중복(Test Code Duplication)
 원인

   리팩토링 기술이나 경험이 부족
   일정에 대한 압박
   어떤 테스트 유틸리티 메소드가 있는지 모른다


 해결책

   메소트 뽑아내기
   생성 메소드, 찾기 메소드
   맞춤 단언문, 검증 메소드
   '인자 도입' 리팩토링
   테스트 유틸리티 메소드 확인
15장에서 다루는 냄새
애매한 테스트
테스트 내 조건문 로직
테스트하기 힘든 코드
테스트 코드 중복
제품 코드 내 테스트 로직
제품 코드 내 테스트 로직(Test Logic In Production)
 제품 코드에 테스트에서만 실행돼야 하는 코드가 들어있다

   테스트 훅
   테스트 전용
   제품 코드 내 테스트 의존
   동등 오염
제품 코드 내 테스트 로직(Test Logic In Production)
 증상

   순전히 테스트에서만 필요한 로직이 SUT안에 들어 있다
   SUT가 테스트 중일때 다르게 실행되는 로직이 있다
   SUT일부 메소드가 테스트에서만 쓰이고 있다
   실제 private 이어야 하는 속성이 public 으로 돼 있다
   제품 코드만 빌드할 수가 없다
   테스트 실행이 없는 경우 제품 코드를 실행할 수 없다
   테스트에서의 필요로 equals 메소드를 변경
   SUT에서 equals 의 정의를 변경
제품 코드 내 테스트 로직(Test Logic In Production)
 미치는 영향

   제품 상태에서 테스트 코드가 실행되면 심각한 문제가 생길 수 있다
   SUT를 더 복잡하게 만든다
   제품의 실행 크기가 늘어난다
   제품에서 뜻하지 않게 테스트 코드가 실행될 수 있다
   새로운 요구사항을 지원하는 equals 로직을 추가하기 어렵다


 원인

   알려진 값을 리턴해 SUT동작을 결정적으로 만든다
   테스트에 필요한 정보를 클래스로부터 노출
   테스트에 필요한 정보 초기화에 더 많은 제어를 하기 위한 메소드 추가
   모듈간 의존성에 신경을 쓰지 않는다
   테스트용 동등의 개념을 잘 모른다
제품 코드 내 테스트 로직(Test Logic In Production)
 해결책

   바꿀 수 있는 의존 사용 : 스트레티지 패턴
   테스트용 하위클래스를 만들어 SUT의 특정 메소드를 오버라이딩한다
   테스트 전용임을 분명하게 네이밍을 한다
   의존관계를 신중히 관리한다
   equals 수정 대신 맞춤 단언문으로 내장 동등 단언문을 쓰게 한다
   동적 모의 객체 생성 도구를 쓴다면 비교자를 쓴다
   기대 객체의 테스트용 하위 클래스에 equals 메소드를 구현한다
끝

More Related Content

Viewers also liked

PrimesIsInP
PrimesIsInPPrimesIsInP
PrimesIsInPSH Park
 
Introduction to prolog
Introduction to prologIntroduction to prolog
Introduction to prologSH Park
 
4장 스포츠 시뮬레이션 - 단순 축구
4장 스포츠 시뮬레이션 - 단순 축구4장 스포츠 시뮬레이션 - 단순 축구
4장 스포츠 시뮬레이션 - 단순 축구SH Park
 
도메인 주도 설계 - 16 대규모 구조
도메인 주도 설계 - 16 대규모 구조도메인 주도 설계 - 16 대규모 구조
도메인 주도 설계 - 16 대규모 구조SH Park
 
Apprenticeship patterns chapter4
Apprenticeship patterns chapter4Apprenticeship patterns chapter4
Apprenticeship patterns chapter4SH Park
 
프로그래머의 길,멘토에게 묻다 2장
프로그래머의 길,멘토에게 묻다 2장프로그래머의 길,멘토에게 묻다 2장
프로그래머의 길,멘토에게 묻다 2장
hyun soomyung
 
Nodejs_chapter9
Nodejs_chapter9Nodejs_chapter9
Nodejs_chapter9
SH Park
 

Viewers also liked (7)

PrimesIsInP
PrimesIsInPPrimesIsInP
PrimesIsInP
 
Introduction to prolog
Introduction to prologIntroduction to prolog
Introduction to prolog
 
4장 스포츠 시뮬레이션 - 단순 축구
4장 스포츠 시뮬레이션 - 단순 축구4장 스포츠 시뮬레이션 - 단순 축구
4장 스포츠 시뮬레이션 - 단순 축구
 
도메인 주도 설계 - 16 대규모 구조
도메인 주도 설계 - 16 대규모 구조도메인 주도 설계 - 16 대규모 구조
도메인 주도 설계 - 16 대규모 구조
 
Apprenticeship patterns chapter4
Apprenticeship patterns chapter4Apprenticeship patterns chapter4
Apprenticeship patterns chapter4
 
프로그래머의 길,멘토에게 묻다 2장
프로그래머의 길,멘토에게 묻다 2장프로그래머의 길,멘토에게 묻다 2장
프로그래머의 길,멘토에게 묻다 2장
 
Nodejs_chapter9
Nodejs_chapter9Nodejs_chapter9
Nodejs_chapter9
 

Similar to xunittestpatternchapter15

테스트 자동화의 원칙
테스트 자동화의 원칙테스트 자동화의 원칙
테스트 자동화의 원칙codevania
 
Xunittestpatternchapter11
Xunittestpatternchapter11Xunittestpatternchapter11
Xunittestpatternchapter11duaa83
 
X unit 14장
X unit 14장X unit 14장
X unit 14장
Park Min Wook
 
TDD.JUnit.조금더.알기
TDD.JUnit.조금더.알기TDD.JUnit.조금더.알기
TDD.JUnit.조금더.알기
Wonchang Song
 
전자회로설계(설문분석)2014-1
전자회로설계(설문분석)2014-1전자회로설계(설문분석)2014-1
전자회로설계(설문분석)2014-1Yong Heui Cho
 
S66 goos-w7
S66 goos-w7S66 goos-w7
S66 goos-w7
한재 제
 
EMOCON 2015 - 품질과 테스트는 다르다
EMOCON 2015 - 품질과 테스트는 다르다EMOCON 2015 - 품질과 테스트는 다르다
EMOCON 2015 - 품질과 테스트는 다르다
이상한모임
 
S66 goos-w6
S66 goos-w6S66 goos-w6
S66 goos-w6
한재 제
 

Similar to xunittestpatternchapter15 (8)

테스트 자동화의 원칙
테스트 자동화의 원칙테스트 자동화의 원칙
테스트 자동화의 원칙
 
Xunittestpatternchapter11
Xunittestpatternchapter11Xunittestpatternchapter11
Xunittestpatternchapter11
 
X unit 14장
X unit 14장X unit 14장
X unit 14장
 
TDD.JUnit.조금더.알기
TDD.JUnit.조금더.알기TDD.JUnit.조금더.알기
TDD.JUnit.조금더.알기
 
전자회로설계(설문분석)2014-1
전자회로설계(설문분석)2014-1전자회로설계(설문분석)2014-1
전자회로설계(설문분석)2014-1
 
S66 goos-w7
S66 goos-w7S66 goos-w7
S66 goos-w7
 
EMOCON 2015 - 품질과 테스트는 다르다
EMOCON 2015 - 품질과 테스트는 다르다EMOCON 2015 - 품질과 테스트는 다르다
EMOCON 2015 - 품질과 테스트는 다르다
 
S66 goos-w6
S66 goos-w6S66 goos-w6
S66 goos-w6
 

xunittestpatternchapter15

  • 1. xUnit Test Pattern 15장. 코드 냄새 박상혁 http://pixelmine.tistory.com 아꿈사 http://andstudy.com
  • 2. 15장에서 다루는 냄새 애매한 테스트 테스트 내 조건문 로직 테스트하기 힘든 코드 테스트 코드 중복 제품 코드 내 테스트 로직
  • 3. 15장에서 다루는 냄새 애매한 테스트 테스트 내 조건문 로직 테스트하기 힘든 코드 테스트 코드 중복 제품 코드 내 테스트 로직
  • 4. 애매한 테스트(Obscure Test) 테스트를 한 눈에 이해하기 어렵다 긴 테스트, 복잡한 테스트, 장황한 테스트 자동테스트의 목표 1. SUT가 어떻게 동작해야 하는가에 대한 문서역할 2. 실행해볼 수 있는 자체 검증 명세 테스트를 실행할 수 있게 구현하다 보면 복잡해지기 때문에 이 두 가지 목표를 동시에 만족하기 어렵다.
  • 5. 애매한 테스트(Obscure Test) 욕심쟁이 테스트 하나의 메소드에서 너무 많은 기능을 검증하려는 테스트 미스터리한 손님 픽스처와 검증로직간의 인과 관계가 보이지 않는 테스트 일반 픽스처 기능 검증에 필요 이상으로 큰 픽스처를 생성하거나 참조한다 관련 없는 정보 정보가 너무 많아 실제 동작에 영향을 미치는 것이 무엇인지 파악하기 힘들다 하드코딩된 테스트 데이터 데이터 값이 하드 코딩돼 있어 입력과 기대 결과값 사이의 인과 관계가 애매하다 간접 테스팅 테스트 메소드와 SUT가 다른 객체를 통해 간접적으로 상호작용한다
  • 6. 애매한 테스트(Obscure Test) 증상 : 테스트에서 검증하는 동작을 이해하기 힘들다 이것 저것 '없는 거 빼고 전부 다' 검증한다 어디까지가 픽스처 설치인지, 어디서부터 SUT실행부인지 알기 어렵다 픽스처 설치나 결과 검증부가 테스트에서 볼 수 없는 정보에 의존한다 외부 정보를 찾지 않고는 동작을 이해하기 어렵다 필요이상으로 큰 픽스처를 구축한다 '픽스처-SUT실행-결과값' 사이의 인과관계 파악이 힘들다 객체에 전달되는 값 중 무엇이 기대출력에 영향을 주는지 알기 어렵다 픽스처 설치 로직이 길고, 무엇을 검증하려는지 알기 어렵다 테스트 검증 코드가 복잡하다 하드코딩된 값이 어떻게 서로 관련되어 있는지 알기 어렵다 어떤 값들이 SUT의 동작에 영향을 주는지 알기 어렵다 검증해야 하는 객체가 아닌 다른 객체와 주로 상호작용한다
  • 7. 애매한 테스트(Obscure Test) 증상 : 테스트에서 검증하는 동작을 이해하기 힘들다 욕심쟁이 테스트(Eager Test) 이것 저것 '없는 거 빼고 전부 다' 검증한다 어디까지가 픽스처 설치인지, 어디서부터 SUT실행부인지 알기 어렵다 픽스처 설치나 결과 검증부가 테스트에서 볼 수 없는 정보에 의존한다 외부 정보를 찾지 않고는 동작을 이해하기 어렵다 필요이상으로 큰 픽스처를 구축한다 '픽스처-SUT실행-결과값' 사이의 인과관계 파악이 힘들다 객체에 전달되는 값 중 무엇이 기대출력에 영향을 주는지 알기 어렵다 픽스처 설치 로직이 길고, 무엇을 검증하려는지 알기 어렵다 테스트 검증 코드가 복잡하다 하드코딩된 값이 어떻게 서로 관련되어 있는지 알기 어렵다 어떤 값들이 SUT의 동작에 영향을 주는지 알기 어렵다 검증해야 하는 객체가 아닌 다른 객체와 주로 상호작용한다
  • 8. 애매한 테스트(Obscure Test) 증상 : 테스트에서 검증하는 동작을 이해하기 힘들다 미스터리한 손님(Mystery Guest) 이것 저것 '없는 거 빼고 전부 다' 검증한다 어디까지가 픽스처 설치인지, 어디서부터 SUT실행부인지 알기 어렵다 픽스처 설치나 결과 검증부가 테스트에서 볼 수 없는 정보에 의존한다 외부 정보를 찾지 않고는 동작을 이해하기 어렵다 필요이상으로 큰 픽스처를 구축한다 '픽스처-SUT실행-결과값' 사이의 인과관계 파악이 힘들다 객체에 전달되는 값 중 무엇이 기대출력에 영향을 주는지 알기 어렵다 픽스처 설치 로직이 길고, 무엇을 검증하려는지 알기 어렵다 테스트 검증 코드가 복잡하다 하드코딩된 값이 어떻게 서로 관련되어 있는지 알기 어렵다 어떤 값들이 SUT의 동작에 영향을 주는지 알기 어렵다 검증해야 하는 객체가 아닌 다른 객체와 주로 상호작용한다
  • 9. 애매한 테스트(Obscure Test) 증상 : 테스트에서 검증하는 동작을 이해하기 힘들다 일반 픽스처(General Fixture) 이것 저것 '없는 거 빼고 전부 다' 검증한다 어디까지가 픽스처 설치인지, 어디서부터 SUT실행부인지 알기 어렵다 픽스처 설치나 결과 검증부가 테스트에서 볼 수 없는 정보에 의존한다 외부 정보를 찾지 않고는 동작을 이해하기 어렵다 필요이상으로 큰 픽스처를 구축한다 '픽스처-SUT실행-결과값' 사이의 인과관계 파악이 힘들다 객체에 전달되는 값 중 무엇이 기대출력에 영향을 주는지 알기 어렵다 픽스처 설치 로직이 길고, 무엇을 검증하려는지 알기 어렵다 테스트 검증 코드가 복잡하다 하드코딩된 값이 어떻게 서로 관련되어 있는지 알기 어렵다 어떤 값들이 SUT의 동작에 영향을 주는지 알기 어렵다 검증해야 하는 객체가 아닌 다른 객체와 주로 상호작용한다
  • 10. 애매한 테스트(Obscure Test) 증상 : 테스트에서 검증하는 동작을 이해하기 힘들다 관련 없는 정보(Irrelevant Information) 이것 저것 '없는 거 빼고 전부 다' 검증한다 어디까지가 픽스처 설치인지, 어디서부터 SUT실행부인지 알기 어렵다 픽스처 설치나 결과 검증부가 테스트에서 볼 수 없는 정보에 의존한다 외부 정보를 찾지 않고는 동작을 이해하기 어렵다 필요이상으로 큰 픽스처를 구축한다 '픽스처-SUT실행-결과값' 사이의 인과관계 파악이 힘들다 객체에 전달되는 값 중 무엇이 기대출력에 영향을 주는지 알기 어렵다 픽스처 설치 로직이 길고, 무엇을 검증하려는지 알기 어렵다 테스트 검증 코드가 복잡하다 하드코딩된 값이 어떻게 서로 관련되어 있는지 알기 어렵다 어떤 값들이 SUT의 동작에 영향을 주는지 알기 어렵다 검증해야 하는 객체가 아닌 다른 객체와 주로 상호작용한다
  • 11. 애매한 테스트(Obscure Test) 증상 : 테스트에서 검증하는 동작을 이해하기 힘들다 하드 코딩된 테스트 데이터(Hard-Coded Test Data) 이것 저것 '없는 거 빼고 전부 다' 검증한다 어디까지가 픽스처 설치인지, 어디서부터 SUT실행부인지 알기 어렵다 픽스처 설치나 결과 검증부가 테스트에서 볼 수 없는 정보에 의존한다 외부 정보를 찾지 않고는 동작을 이해하기 어렵다 필요이상으로 큰 픽스처를 구축한다 '픽스처-SUT실행-결과값' 사이의 인과관계 파악이 힘들다 객체에 전달되는 값 중 무엇이 기대출력에 영향을 주는지 알기 어렵다 픽스처 설치 로직이 길고, 무엇을 검증하려는지 알기 어렵다 테스트 검증 코드가 복잡하다 하드코딩된 값이 어떻게 서로 관련되어 있는지 알기 어렵다 어떤 값들이 SUT의 동작에 영향을 주는지 알기 어렵다 검증해야 하는 객체가 아닌 다른 객체와 주로 상호작용한다
  • 12. 애매한 테스트(Obscure Test) • 증상 : 테스트에서 검증하는 동작을 이해하기 힘들다 간접 테스팅(Indirect Testing) – 이것 저것 '없는 거 빼고 전부 다' 검증한다 – 어디까지가 픽스처 설치인지, 어디서부터 SUT실행부인지 알기 어렵다 – 픽스처 설치나 결과 검증부가 테스트에서 볼 수 없는 정보에 의존한다 – 외부 정보를 찾지 않고는 동작을 이해하기 어렵다 – 필요이상으로 큰 픽스처를 구축한다 – '픽스처-SUT실행-결과값' 사이의 인과관계 파악이 힘들다 – 객체에 전달되는 값 중 무엇이 기대출력에 영향을 주는지 알기 어렵다 – 픽스처 설치 로직이 길고, 무엇을 검증하려는지 알기 어렵다 – 테스트 검증 코드가 복잡하다 – 하드코딩된 값이 어떻게 서로 관련되어 있는지 알기 어렵다 – 어떤 값들이 SUT의 동작에 영향을 주는지 알기 어렵다 – 검증해야 하는 객체가 아닌 다른 객체와 주로 상호작용한다
  • 13. 애매한 테스트(Obscure Test) 미치는 영향 이해하기 힘들고 유지보수가 어렵다 문서로서의 테스트를 만들기 어렵다 테스트 유지비용 상승한다 버그 투성이 테스트가 된다 테스트 디버깅 데이터를 잃게 된다 픽스처와 기대결과 사이의 인과관계를 알기 어렵다 변덕스러운 테스트가 생긴다 각 테스트에서 픽스처를 어떻게 사용하는지 이해하기 힘들다 깨지기 쉬운 픽스쳐가 된다 느린 테스트가 될 수 있다 공유픽스처를 쓸 때 다른 테스트에서 같은 값을 쓰는 경우 충돌이 생긴다 깨지기 쉬운 테스트가 된다 모든 곳을 테스트 하기 불가능하다
  • 14. 애매한 테스트(Obscure Test) 미치는 영향 욕심쟁이 테스트(Eager Test) 이해하기 힘들고 유지보수가 어렵다 문서로서의 테스트를 만들기 어렵다 테스트 유지비용 상승한다 버그 투성이 테스트가 된다 테스트 디버깅 데이터를 잃게 된다 픽스처와 기대결과 사이의 인과관계를 알기 어렵다 변덕스러운 테스트가 생긴다 각 테스트에서 픽스처를 어떻게 사용하는지 이해하기 힘들다 깨지기 쉬운 픽스쳐가 된다 느린 테스트가 될 수 있다 공유픽스처를 쓸 때 다른 테스트에서 같은 값을 쓰는 경우 충돌이 생긴다 깨지기 쉬운 테스트가 된다 모든 곳을 테스트 하기 불가능하다
  • 15. 애매한 테스트(Obscure Test) 미치는 영향 미스터리한 손님(Mystery Guest) 이해하기 힘들고 유지보수가 어렵다 문서로서의 테스트를 만들기 어렵다 테스트 유지비용 상승한다 버그 투성이 테스트가 된다 테스트 디버깅 데이터를 잃게 된다 픽스처와 기대결과 사이의 인과관계를 알기 어렵다 변덕스러운 테스트가 생긴다 각 테스트에서 픽스처를 어떻게 사용하는지 이해하기 힘들다 깨지기 쉬운 픽스쳐가 된다 느린 테스트가 될 수 있다 공유픽스처를 쓸 때 다른 테스트에서 같은 값을 쓰는 경우 충돌이 생긴다 깨지기 쉬운 테스트가 된다 모든 곳을 테스트 하기 불가능하다
  • 16. 애매한 테스트(Obscure Test) 미치는 영향 일반 픽스처(General Fixture) 이해하기 힘들고 유지보수가 어렵다 문서로서의 테스트를 만들기 어렵다 테스트 유지비용 상승한다 버그 투성이 테스트가 된다 테스트 디버깅 데이터를 잃게 된다 픽스처와 기대결과 사이의 인과관계를 알기 어렵다 변덕스러운 테스트가 생긴다 각 테스트에서 픽스처를 어떻게 사용하는지 이해하기 힘들다 깨지기 쉬운 픽스쳐가 된다 느린 테스트가 될 수 있다 공유픽스처를 쓸 때 다른 테스트에서 같은 값을 쓰는 경우 충돌이 생긴다 깨지기 쉬운 테스트가 된다 모든 곳을 테스트 하기 불가능하다
  • 17. 애매한 테스트(Obscure Test) 미치는 영향 관련 없는 정보(Irrelevant Information) 이해하기 힘들고 유지보수가 어렵다 문서로서의 테스트를 만들기 어렵다 테스트 유지비용 상승한다 버그 투성이 테스트가 된다 테스트 디버깅 데이터를 잃게 된다 픽스처와 기대결과 사이의 인과관계를 알기 어렵다 변덕스러운 테스트가 생긴다 각 테스트에서 픽스처를 어떻게 사용하는지 이해하기 힘들다 깨지기 쉬운 픽스쳐가 된다 느린 테스트가 될 수 있다 공유픽스처를 쓸 때 다른 테스트에서 같은 값을 쓰는 경우 충돌이 생긴다 깨지기 쉬운 테스트가 된다 모든 곳을 테스트 하기 불가능하다
  • 18. 애매한 테스트(Obscure Test) 미치는 영향 하드 코딩된 테스트 데이터(Hard-Coded Test Data) 이해하기 힘들고 유지보수가 어렵다 문서로서의 테스트를 만들기 어렵다 테스트 유지비용 상승한다 버그 투성이 테스트가 된다 테스트 디버깅 데이터를 잃게 된다 픽스처와 기대결과 사이의 인과관계를 알기 어렵다 변덕스러운 테스트가 생긴다 각 테스트에서 픽스처를 어떻게 사용하는지 이해하기 힘들다 깨지기 쉬운 픽스쳐가 된다 느린 테스트가 될 수 있다 공유픽스처를 쓸 때 다른 테스트에서 같은 값을 쓰는 경우 충돌이 생긴다 깨지기 쉬운 테스트가 된다 모든 곳을 테스트 하기 불가능하다
  • 19. 애매한 테스트(Obscure Test) 미치는 영향 간접 테스팅(Indirect Testing) 이해하기 힘들고 유지보수가 어렵다 문서로서의 테스트를 만들기 어렵다 테스트 유지비용 상승한다 버그 투성이 테스트가 된다 테스트 디버깅 데이터를 잃게 된다 픽스처와 기대결과 사이의 인과관계를 알기 어렵다 변덕스러운 테스트가 생긴다 각 테스트에서 픽스처를 어떻게 사용하는지 이해하기 힘들다 깨지기 쉬운 픽스쳐가 된다 느린 테스트가 될 수 있다 공유픽스처를 쓸때 다른 테스트에서 같은 값을 쓰는 경우 충돌이 생긴다 깨지기 쉬운 테스트가 된다 모든 곳을 테스트 하기 불가능하다
  • 20. 애매한 테스트(Obscure Test) 원인 테스트 메소드에 정보가 너무 많다 테스트 메소드에 정보가 너무 적다 코드를 깔끔하고 간단하게 유지하려는 의지가 없다 코드를 '그냥 인라인으로' 작성한다 테스트가 외부자원에 의존한다 여러 테스트를 지원하는 픽스처를 쓴다 테스테 상관없는 리터럴 값이 너무 많다 절차형 상태 검증을 쓴다 잘라 붙여넣기로 테스트 로직을 재사용한다 테스트에서 접근하려는 클래스의 SUT부분이 private이다 – 테스트 용이성을 생각하지 않고 설계했다
  • 21. 애매한 테스트(Obscure Test) 원인 욕심쟁이 테스트(Eager Test) 테스트 메소드에 정보가 너무 많다 테스트 메소드에 정보가 너무 적다 코드를 깔끔하고 간단하게 유지하려는 의지가 없다 코드를 '그냥 인라인으로' 작성한다 테스트가 외부자원에 의존한다 여러 테스트를 지원하는 픽스처를 쓴다 테스테 상관없는 리터럴 값이 너무 많다 절차형 상태 검증을 쓴다 잘라 붙여넣기로 테스트 로직을 재사용한다 테스트에서 접근하려는 클래스의 SUT부분이 private이다 테스트 용이성을 생각하지 않고 설계했다
  • 22. 애매한 테스트(Obscure Test) 원인 미스터리한 손님(Mystery Guest) 테스트 메소드에 정보가 너무 많다 테스트 메소드에 정보가 너무 적다 코드를 깔끔하고 간단하게 유지하려는 의지가 없다 코드를 '그냥 인라인으로' 작성한다 테스트가 외부자원에 의존한다 SUT 메소드에 전달되는 외부 파일의 내용이 SUT의 여러 테스트를 지원하는 픽스처를 쓴다 결정 동작을 리터럴키로 식별되는 DB 레코드를 읽어 객체에 쓴 뒤 테스테 상관없는 리터럴 값이 너무 많다 테스트에서 사용하거나 SUT에 전달 이를 절차형 상태 검증을 쓴다 파일에서 읽어들인 내용을 기대결과값을 검증하는 단 언 메소드 호출에 사용 잘라 붙여넣기로 테스트 로직을 재사용한다 설치 데코레이터로 공유 픽스처를 만들고 결과 검증 테스트에서 접근하려는 클래스의 SUT부분이 private이다 로직에서는 공유 픽스처의 객체들을 변수로 참조 테스트 용이성을 생각하지 않고 설계했다 설치로 일반 픽스처를 설치하고 테스트 메소 암묵적 드에서 인스턴스 변수나 클래스 변수로 접근
  • 23. 애매한 테스트(Obscure Test) 원인 일반 픽스처(General Fixture) 테스트 메소드에 정보가 너무 많다 테스트 메소드에 정보가 너무 적다 코드를 깔끔하고 간단하게 유지하려는 의지가 없다 코드를 '그냥 인라인으로' 작성한다 테스트가 외부자원에 의존한다 여러 테스트를 지원하는 픽스처를 쓴다 테스테 상관없는 리터럴 값이 너무 많다 절차형 상태 검증을 쓴다 잘라 붙여넣기로 테스트 로직을 재사용한다 테스트에서 접근하려는 클래스의 SUT부분이 private이다 테스트 용이성을 생각하지 않고 설계했다
  • 24. 애매한 테스트(Obscure Test) 원인 관련 없는 정보(Irrelevant Information) 테스트 메소드에 정보가 너무 많다 테스트 메소드에 정보가 너무 적다 코드를 깔끔하고 간단하게 유지하려는 의지가 없다 코드를 '그냥 인라인으로' 작성한다 테스트가 외부자원에 의존한다 여러 테스트를 지원하는 픽스처를 쓴다 테스테 상관없는 리터럴 값이 너무 많다 절차형 상태 검증을 쓴다 잘라 붙여넣기로 테스트 로직을 재사용한다 테스트에서 접근하려는 클래스의 SUT부분이 private이다 테스트 용이성을 생각하지 않고 설계했다
  • 25. 애매한 테스트(Obscure Test) 원인 하드 코딩된 테스트 데이터(Hard-Coded Test Data) 테스트 메소드에 정보가 너무 많다 테스트 메소드에 정보가 너무 적다 코드를 깔끔하고 간단하게 유지하려는 의지가 없다 코드를 '그냥 인라인으로' 작성한다 테스트가 외부자원에 의존한다 여러 테스트를 지원하는 픽스처를 쓴다 테스테 상관없는 리터럴 값이 너무 많다 절차형 상태 검증을 쓴다 잘라 붙여넣기로 테스트 로직을 재사용한다 테스트에서 접근하려는 클래스의 SUT부분이 private이다 테스트 용이성을 생각하지 않고 설계했다
  • 26. 애매한 테스트(Obscure Test) 원인 간접 테스팅(Indirect Testing) 테스트 메소드에 정보가 너무 많다 테스트 메소드에 정보가 너무 적다 코드를 깔끔하고 간단하게 유지하려는 의지가 없다 코드를 '그냥 인라인으로' 작성한다 테스트가 외부자원에 의존한다 여러 테스트를 지원하는 픽스처를 쓴다 테스테 상관없는 리터럴 값이 너무 많다 절차형 상태 검증을 쓴다 잘라 붙여넣기로 테스트 로직을 재사용한다 테스트에서 접근하려는 클래스의 SUT부분이 private이다 테스트 용이성을 생각하지 않고 설계했다
  • 27. 애매한 테스트(Obscure Test) 해결책 더 좋은 결함 국소화를 제공하는 독립적인 단일 조건 테스트 스위트로 만든다 인라인 설치로 신선한 픽스처를 쓴다 픽스처 안의 객체들에 찾기메소드로 접근하는 것을 고려해보자 파일 이름을 적당히 붙여 안에 어떤 데이터가 들어있는지 짐작할 수 있게 해준다 최소 픽스처, 신선한 픽스처 사용 테스트별로 가상의 데이터베이스 샌드박스를 만든다 관련 있는 정보만 인자로 받는 인자를 받는 생성 메소드 호출 설치부와 검증부에 필요한 픽스처 값을 적당히 초기화한 상수로 바꾼다 결과 검증 로직에서 기대 객체로 한번에 단언한다 복잡한 절차적 검증로직을 숨기는 맞춤 단언문 사용 리터럴 상수를 다른 걸로 바꿔준다 별개의 생성값을 써서 테스트가 실행될 때마다 다른 값을 쓰게 보장해줘야 한다 SUT의 테스트 용이성을 위한 설계를 개선 SUT를 간접적으로 접근해야만 한다면 SUT API 캡슐화 사용
  • 28. 애매한 테스트(Obscure Test) 해결책 욕심쟁이 테스트(Eager Test) 더 좋은 결함 국소화를 제공하는 독립적인 단일 조건 테스트 스위트로 만든다 인라인 설치로 신선한 픽스처를 쓴다 픽스처 안의 객체들에 찾기메소드로 접근하는 것을 고려해보자 파일 이름을 적당히 붙여 안에 어떤 데이터가 들어있는지 짐작할 수 있게 해준다 최소 픽스처, 신선한 픽스처 사용 테스트별로 가상의 데이터베이스 샌드박스를 만든다 관련 있는 정보만 인자로 받는 인자를 받는 생성 메소드 호출 설치부와 검증부에 필요한 픽스처 값을 적당히 초기화한 상수로 바꾼다 결과 검증 로직에서 기대 객체로 한번에 단언한다 복잡한 절차적 검증로직을 숨기는 맞춤 단언문 사용 리터럴 상수를 다른 걸로 바꿔준다 별개의 생성값을 써서 테스트가 실행될 때마다 다른 값을 쓰게 보장해줘야 한다 SUT의 테스트 용이성을 위한 설계를 개선 SUT를 간접적으로 접근해야만 한다면 SUT API 캡슐화 사용
  • 29. 애매한 테스트(Obscure Test) 해결책 미스터리한 손님(Mystery Guest) 더 좋은 결함 국소화를 제공하는 독립적인 단일 조건 테스트 스위트로 만든다 인라인 설치로 신선한 픽스처를 쓴다 픽스처 안의 객체들에 찾기메소드로 접근하는 것을 고려해보자 파일 이름을 잘 붙여 안에 어떤 데이터가 들어있는지 짐작할 수 있게 해준다 최소 픽스처, 신선한 픽스처 사용 테스트별로 가상의 데이터베이스 샌드박스를 만든다 관련 있는 정보만 인자로 받는 인자를 받는 생성 메소드 호출 설치부와 검증부에 필요한 픽스처 값을 적당히 초기화한 상수로 바꾼다 결과 검증 로직에서 기대 객체로 한번에 단언한다 복잡한 절차적 검증로직을 숨기는 맞춤 단언문 사용 리터럴 상수를 다른 걸로 바꿔준다 별개의 생성값을 써서 테스트가 실행될 때마다 다른 값을 쓰게 보장해줘야 한다 SUT의 테스트 용이성을 위한 설계를 개선 SUT를 간접적으로 접근해야만 한다면 SUT API 캡슐화 사용
  • 30. 애매한 테스트(Obscure Test) 해결책 일반 픽스처(General Fixture) 더 좋은 결함 국소화를 제공하는 독립적인 단일 조건 테스트 스위트로 만든다 인라인 설치로 신선한 픽스처를 쓴다 픽스처 안의 객체들에 찾기메소드로 접근하는 것을 고려해보자 파일 이름을 적당히 붙여 안에 어떤 데이터가 들어있는지 짐작할 수 있게 해준다 최소 픽스처, 신선한 픽스처 사용 테스트별로 가상의 데이터베이스 샌드박스를 만든다 관련 있는 정보만 인자로 받는 인자를 받는 생성 메소드 호출 설치부와 검증부에 필요한 픽스처 값을 적당히 초기화한 상수로 바꾼다 결과 검증 로직에서 기대 객체로 한번에 단언한다 복잡한 절차적 검증로직을 숨기는 맞춤 단언문 사용 리터럴 상수를 다른 걸로 바꿔준다 별개의 생성값을 써서 테스트가 실행될 때마다 다른 값을 쓰게 보장해줘야 한다 SUT의 테스트 용이성을 위한 설계를 개선 SUT를 간접적으로 접근해야만 한다면 SUT API 캡슐화 사용
  • 31. 애매한 테스트(Obscure Test) 해결책 관련 없는 정보(Irrelevant Information) 더 좋은 결함 국소화를 제공하는 독립적인 단일 조건 테스트 스위트로 만든다 인라인 설치로 신선한 픽스처를 쓴다 픽스처 안의 객체들에 찾기메소드로 접근하는 것을 고려해보자 파일 이름을 적당히 붙여 안에 어떤 데이터가 들어있는지 짐작할 수 있게 해준다 최소 픽스처, 신선한 픽스처 사용 테스트별로 가상의 데이터베이스 샌드박스를 만든다 관련 있는 정보만 인자로 받는 인자를 받는 생성 메소드 호출 설치부와 검증부에 필요한 픽스처 값을 적당히 초기화한 상수로 바꾼다 결과 검증 로직에서 기대 객체로 한번에 단언한다 복잡한 절차적 검증로직을 숨기는 맞춤 단언문 사용 리터럴 상수를 다른 걸로 바꿔준다 별개의 생성값을 써서 테스트가 실행될 때마다 다른 값을 쓰게 보장해줘야 한다 SUT의 테스트 용이성을 위한 설계를 개선 SUT를 간접적으로 접근해야만 한다면 SUT API 캡슐화 사용
  • 32. 애매한 테스트(Obscure Test) 해결책 하드 코딩된 테스트 데이터(Hard-Coded Test Data) 더 좋은 결함 국소화를 제공하는 독립적인 단일 조건 테스트 스위트로 만든다 인라인 설치로 신선한 픽스처를 쓴다 픽스처 안의 객체들에 찾기메소드로 접근하는 것을 고려해보자 파일 이름을 적당히 붙여 안에 어떤 데이터가 들어있는지 짐작할 수 있게 해준다 최소 픽스처, 신선한 픽스처 사용 테스트별로 가상의 데이터베이스 샌드박스를 만든다 관련 있는 정보만 인자로 받는 인자를 받는 생성 메소드 호출 설치부와 검증부에 필요한 픽스처 값을 적당히 초기화한 상수로 바꾼다 결과 검증 로직에서 기대 객체로 한번에 단언한다 복잡한 절차적 검증로직을 숨기는 맞춤 단언문 사용 리터럴 상수를 다른 걸로 바꿔준다 별개의 생성값을 써서 테스트가 실행될 때마다 다른 값을 쓰게 보장해줘야 한다 SUT의 테스트 용이성을 위한 설계를 개선 SUT를 간접적으로 접근해야만 한다면 SUT API 캡슐화 사용
  • 33. 애매한 테스트(Obscure Test) 해결책 간접 테스팅(Indirect Testing) 더 좋은 결함 국소화를 제공하는 독립적인 단일 조건 테스트 스위트로 만든다 인라인 설치로 신선한 픽스처를 쓴다 픽스처 안의 객체들에 찾기메소드로 접근하는 것을 고려해보자 파일 이름을 적당히 붙여 안에 어떤 데이터가 들어있는지 짐작할 수 있게 해준다 최소 픽스처, 신선한 픽스처 사용 테스트별로 가상의 데이터베이스 샌드박스를 만든다 관련 있는 정보만 인자로 받는 인자를 받는 생성 메소드 호출 설치부와 검증부에 필요한 픽스처 값을 적당히 초기화한 상수로 바꾼다 결과 검증 로직에서 기대 객체로 한번에 단언한다 복잡한 절차적 검증로직을 숨기는 맞춤 단언문 사용 리터럴 상수를 다른 걸로 바꿔준다 별개의 생성값을 써서 테스트가 실행될 때마다 다른 값을 쓰게 보장해줘야 한다 SUT의 테스트 용이성을 위한 설계를 개선 SUT를 간접적으로 접근해야만 한다면 SUT API 캡슐화 사용
  • 34. 15장에서 다루는 냄새 애매한 테스트 테스트 내 조건문 로직 테스트하기 힘든 코드 테스트 코드 중복 제품 코드 내 테스트 로직
  • 35. 테스트 내 조건문 로직(Conditional Test Logic) 테스트에 실행 안 될 수도 있는 코드가 있다 들쑥날쑥한 테스트 코드 완전 자동 테스트는 다른 코드의 동작을 검증하는 코드다 완전 자동 테스트 코드가 복잡하다면......? 테스트를 위한 테스트......? 테스트가 필요없을 정도로 단순하게 만드는 것이 정답 테스트 내 조건문 로직은 필요 이상으로 테스트를 복잡하게 만드 는 요인 중 하나다
  • 36. 테스트 내 조건문 로직(Conditional Test Logic) 유연한 테스트 언제 어디서 실행되느냐에 따라 다른 기능을 검증하는 테스트 검증 조건문 로직 기대 결과 검증에 조건문 사용 테스트 내 제품 로직 복잡한 해체 여러 테스트 조건
  • 37. 테스트 내 조건문 로직(Conditional Test Logic) 증상 : 테스트 코드 내에 반복문이나 조건문이 있다 테스트가 상황에 따라 다른 일을 할 수 있게 조건문 로직이 들어 있다 테스트의 결과 검증부에 조건문 로직이 들어있다 픽스처 해체 코드가 복잡하다 여러 입력값과 그 기대 결과값에 같은 테스트 로직 적용
  • 38. 테스트 내 조건문 로직(Conditional Test Logic) 미치는 영향 테스트 코드에서 무엇을 하는지 알기 어렵다 테스트가 결정론적이지 않아 디버깅하기 어렵다 어려운 작업에 대해 테스트를 정확하게 작성하기 어렵다 테스트가 이해하기 어려워 유지보수가 힘들다 모든 제어경로가 테스트 되었는지 알 수 없다
  • 39. 테스트 내 조건문 로직(Conditional Test Logic) 원인 SUT가 올바른 데이터를 반환하지 않았을 때의 if문 처리 여러 객제를 한꺼번에 검증하기 위해 반복문 사용 복잡한 객체나 다형성 데이터 구조를 검증 테스트 픽스처나 기대 객체 초기화시 하나의 테스트에서 여러 다른 경우 검증 존재하지 않는 픽스처 객체를 해체하지 않기 위해 if문 사용 환경에 대한 제어능력 부족 가비지 컬렉션 시스템이 해결해 줄 수 없는 지속적인 자원을 많이 사용
  • 40. 테스트 내 조건문 로직(Conditional Test Logic) 해결책 SUT에서 '바꿀 수 있는 의존'을 지원하게 리팩토링한다 보호 단언문 사용 복잡한 객체를 검증할 때는 기대객체에 동등 단언문 사용 테스트용 동등을 정의한 맞춤 단언문 사용 테스트 유틸리티 메소드나 공통 인자를 받는 테스트 사용 입력된 값에 대한 계산된 값을 쓴다 암묵적 해체, 자동 해체 사용 신선한 픽스처, 테스트 대역을 사용해 지속되는 객체를 쓰지 않는다
  • 41. 15장에서 다루는 냄새 애매한 테스트 테스트 내 조건문 로직 테스트하기 힘든 코드 테스트 코드 중복 제품 코드 내 테스트 로직
  • 42. 테스트하기 힘든 코드(Hard-to-Test Code) 코드가 테스트 하기 어렵다 강하게 결합된 코드 비동기 코드 테스트할 수 없는 테스트 코드
  • 43. 테스트하기 힘든 코드(Hard-to-Test Code) 증상 원래부터 테스트 하기 힘든 코드 여러 다른 클래스와 함께 테스트 해야만 하는 코드 직접 메소드 호출로 테스트할 수 없는 클래스 테스트 메소드의 내용이 복잡하다 테스트가 올바른지 확신할 수 없다
  • 44. 테스트하기 힘든 코드(Hard-to-Test Code) 미치는 영향 코드의 품질을 쉽게 검증할 수 없다 테스트 문서화에 큰 공을 들이지 않으면 품질 평가를 반복하기 어렵다 단위 테스트가 어렵다 테스트가 복잡하고 실행이 느려진다 버그투성이 테스트가 되기 쉽다 테스트 유지 비용이 비싸다 테스트를 제대로 작성하기 어렵다
  • 45. 테스트하기 힘든 코드(Hard-to-Test Code) 원인 설계가 조잡하다 객체지향 설계경험이 부족하다 액티브 객체와 강하게 결합되어 있다 데스트코드는 원래 테스트하기 어렵다
  • 46. 테스트하기 힘든 코드(Hard-to-Test Code) 해결책 결합을 분리한다 : 테스트 대역, 테스트 스텁, 모의 객체 '레거시 코드 활용 전략'을 읽어본다 로직과 비동기 접근 매커니즘 분리 : 대강 만든 객체 테스트 메소드들 아주 단순하게 만든다
  • 47. 15장에서 다루는 냄새 애매한 테스트 테스트 내 조건문 로직 테스트하기 힘든 코드 테스트 코드 중복 제품 코드 내 테스트 로직
  • 48. 테스트 코드 중복(Test Code Duplication) 여러 번 반복되는 테스트 코드 같은 주제에 대해 약간씩 다른 시나리오로 테스트 해야 하는 경우 '잘라 붙여넣기' 코드 재사용 바퀴 재발명 하기
  • 49. 테스트 코드 중복(Test Code Duplication) 증상 같은 코드가 여러 테스트에서 반복된다 한 테스트 안에서 비슷한 구문이 반복된다 미치는 영향 SUT메소드 의미가 변경되면 모든 복사본에 유지보수 해야한다 테스트 유지 비용이 늘어난다
  • 50. 테스트 코드 중복(Test Code Duplication) 원인 리팩토링 기술이나 경험이 부족 일정에 대한 압박 어떤 테스트 유틸리티 메소드가 있는지 모른다 해결책 메소트 뽑아내기 생성 메소드, 찾기 메소드 맞춤 단언문, 검증 메소드 '인자 도입' 리팩토링 테스트 유틸리티 메소드 확인
  • 51. 15장에서 다루는 냄새 애매한 테스트 테스트 내 조건문 로직 테스트하기 힘든 코드 테스트 코드 중복 제품 코드 내 테스트 로직
  • 52. 제품 코드 내 테스트 로직(Test Logic In Production) 제품 코드에 테스트에서만 실행돼야 하는 코드가 들어있다 테스트 훅 테스트 전용 제품 코드 내 테스트 의존 동등 오염
  • 53. 제품 코드 내 테스트 로직(Test Logic In Production) 증상 순전히 테스트에서만 필요한 로직이 SUT안에 들어 있다 SUT가 테스트 중일때 다르게 실행되는 로직이 있다 SUT일부 메소드가 테스트에서만 쓰이고 있다 실제 private 이어야 하는 속성이 public 으로 돼 있다 제품 코드만 빌드할 수가 없다 테스트 실행이 없는 경우 제품 코드를 실행할 수 없다 테스트에서의 필요로 equals 메소드를 변경 SUT에서 equals 의 정의를 변경
  • 54. 제품 코드 내 테스트 로직(Test Logic In Production) 미치는 영향 제품 상태에서 테스트 코드가 실행되면 심각한 문제가 생길 수 있다 SUT를 더 복잡하게 만든다 제품의 실행 크기가 늘어난다 제품에서 뜻하지 않게 테스트 코드가 실행될 수 있다 새로운 요구사항을 지원하는 equals 로직을 추가하기 어렵다 원인 알려진 값을 리턴해 SUT동작을 결정적으로 만든다 테스트에 필요한 정보를 클래스로부터 노출 테스트에 필요한 정보 초기화에 더 많은 제어를 하기 위한 메소드 추가 모듈간 의존성에 신경을 쓰지 않는다 테스트용 동등의 개념을 잘 모른다
  • 55. 제품 코드 내 테스트 로직(Test Logic In Production) 해결책 바꿀 수 있는 의존 사용 : 스트레티지 패턴 테스트용 하위클래스를 만들어 SUT의 특정 메소드를 오버라이딩한다 테스트 전용임을 분명하게 네이밍을 한다 의존관계를 신중히 관리한다 equals 수정 대신 맞춤 단언문으로 내장 동등 단언문을 쓰게 한다 동적 모의 객체 생성 도구를 쓴다면 비교자를 쓴다 기대 객체의 테스트용 하위 클래스에 equals 메소드를 구현한다
  • 56.