Header

  1. View current page

    딥뿔이 자라나는 노트

Profile_image?t=1225424611&type=big
나를 바꾼 똑똑한 생활 습관, 스프링노트 - 여러분도 지금 시작해보세요!
71

Test Double

아래 내용은 오픈마루 루비 스터디(7/31)에서 공유하기 위해 작성한 내용입니다.

 

단위 테스트(Unit Test)?

단위테스트에 대한 오해

  • 단위 테스트는 회귀 테스트(regression test)나 수용성 테스트(acceptance test)가 아니다(그 역할을 약간 도울 뿐).
  • 단위 테스트는 시스템 유닛을 잘 디자인하기 위한 도구다.

 

현재 개발 중인 유닛을 잘 만드는데 집중하기 위해, 다른 건 일단 잊자.

Test Double은 내 머릿속의 지우개!

 

Test Double

SUT(System Under Testing)가 의존하는 구현체의 일부를 "테스트에서만 사용하는 것"으로 바꾼다.

 

Test%20Double.gif

그림 출처: http://xunitpatterns.com/Test%20Double.html

 

  • Dummy

    • 누구든 필요없으니 자리 좀 채워줘
  • Fake

    • 매번 myID에 호출하지말고, 개발환경에 가짜 myID 하나 두지?
  • Stubs

    • 거, 테스트할때마다 메일 좀 안 보내면 안돼? 메일 보내는 부분만 바꿔치기하면 되잖아
  • Mocks

    • 너는 어떤 메시지를 주고 받는지 잘 감시해서 나한테 알려줘야해

 

Verification

테스트는 검증(verification)의 과정이다. 검증은 2가지 방법으로 할 수 있다.

 

  • 상태(state) 검증

    • 300원 인출했어. 너 이제 500원 있는거 맞지?
  • 행위(behavior) 검증

    • 나는 분명히 너한테 300원 인출하라고 시켰다. 알아서 잘 처리할거라 믿어!

 

Mock과 Stub의 차이는 어떤 검증 방법의 차이.

 

TDD 고전주의자

왠만하면 실제 객체를 그냥 사용하자. 불가피한 경우(ex. 네트워크 통신)는 스텁을 만든다.

 

아래는 acts_as_cached_test.rb. ActsAsCached의 일부를 스텁으로 대체한다.

 

  1. class CacheCache < Hash
      def setted?(name)
        not self[:set][name].nil?
      end
    end

    $cache_cache = CacheCache.new

    module ActsAsCached
      module Disabled
        def set_cache_with_disabled(*args)
          key = cache_key(args.first)#.tap{|x| p x}
          $cache_cache[:set][key] = args[1]
          args[1]
        end
      end
    end

 

그리고 상태를 검증한다.

 

  1. it "should cache tag_list" do
      @note.tag_list(@user)
      cache_store.should be_setted("Note:4:tag_list")
    end

 

TDD 뫅주의자

뭔가 특별한 행위를 하는 객체가 있다면 항상 mock을 사용한다.

 

  1.   it "should refresh recent pages cache" do
        flexmock(Page).should_receive(:set_cache).once.
          with('/recent_pages/7/ko', any, any).and_return []
       
        get :recent_pages, :id => 7, :refresh => true, :lang => 'ko'
      end

 

여기서 좀 더 발전하면, 객체들의 행위들을 잘 관찰하고, 검증하면 개발을 잘 할 수 있다고 믿는 BDD(행위 주도 개발)에 다다른다. BDD는 TDD의 용어를 행위 중심으로 개정한 뫅주의자들의 작품이다.

 

고전주의자 vs. 뫅주의자

양쪽 모두 자신들의 논지가 있다. 하지만 뫅주의자들이 설득의 필요를 더 느끼므로 이 쪽 논리가 더 발전되어 있다. 고씨와 뫅씨의 대화를 들어보자.

 

  • 뫅: mock 쵝오!~ mock만이 단위테스트를 진정으로 고립시키는 유일한 방법이야. 어이 고씨, 당신이 하고 있는건 단위테스트가 아니야. 그건 미니 통합 테스트라규~
  • 고: 그게 현실이야 이 친구야. 당신 왕따 아니야? 다른 모듈이 수정되도 당신은 모르고 있을것 같아. 그럼 그게 더 큰 문제일껄?
  • 왁: 모듈 하나가 깨지면, 거기에 연관된 모든 테스트가 연쇄적으로 깨져버릴꺼여. 그러면 어떤 모듈이 문제가 되는지 빨리 알아챌 수 있겠어? 아마 이 테스트, 저 테스트 돌아다니면서 한참을 헤매야 할껄?
  • 고: 모르는 소리! 난 내 시스템을 잘 알고 있다구~ 그깟 에러 금방 고쳐주지! 뫅씨 테스트 코드는 너무 장황해서 읽기가 힘들어. 뭐 그렇게 서론이 길어? 게다가 테스트만 봐도 실제 구현 코드가 보일 정도라. 그건 중복이고 불필요한 노력이라구. 리팩토링도 힘들겠고 말이지
  • 뫅: 테스트만 봐도 구현이 보이는건 장점이야 이 친구야. 테스트가 진정한 문서로 거듭나고 있다는 의미지! 이렇게 실용적인 스펙을 본 적이 있나? 그리고 요즘 세상이 좋아져서 그깟 커플링은 느슨하게 만들수도 있다구.
  • 고: 도대체 그렇게 고생해가면서 mock을 지킬려는 진짜 의도가 머야? 뇌물 먹었어?
  • 뫅: 무식한 사람 같으니. mock은 디자인에 도움이 된다구! 일명 있다치고 접근법이지. 잘 들어봐. 처음 개발을 시작할 때 참 막막하잖아? 그니까 먼저 사용자눈에 보이는 UI 부분부터 만드는거야. 도메인 모델은 있다 치는거지. UI를 다 만들면 그 다음에 있다쳤던 모델을 스펙대로 만들기만 하면 된다는 말이야. 이게 얼마나 큰 도움이 되는 줄 알아? 이게 바로 outside-in 접근법이란 말이지. 당신 보니까 모델이랑 UI 오가느라 정신 없던데 그래서 오래 살겠나?
  • 고: 훗, 요즘은 레이어 별로 개발하는데 익숙치 않은 사람이 어딨나? MVC는 기본이라구. 이미 몸에 익어서 하나도 어색하지 않아. 
  • 뫅: 당신 코드를 보니 불필요한 질의 메서드가 많던걸? 그거 테스트에서만 쓸꺼 아닌가? 뭐하러 만드나? Tell Don't Ask 원칙도 모르나?
  • 고: 이게 다 완벽한 도메인 모델을 만드는데 도움이 되는거라구. 그리고 이런건 사소한 문제일 뿐이야.

 

이 논쟁을 마치려면 손석희씨가 필요할 것 같다. 좀 더 잘 정리된 문서를 원하면 Mocks Aren't Stubs을 읽어보도록.

 

 

 

History

Last edited on 08/13/2008 14:14 by deepblue

Comments (0)

You must log in to leave a comment. Please sign in.