통화 예시는 이제 끝났다. 이제는 xUnit에 대한 예시를 위해 python에서의 TDD의 좀 더 교묘한 활용을 보게된다.

chapter 18

크기를 넓혀서 테스트 뿐 아니라 테스트 프레임워크를 만들어 테스트를 해보도록 한다.
테스트 프레임워크를 만드는데도, 가장 먼저 할 일은 테스트를 작성하는 것이다.
파이썬을 사용한다고해도, 이전에 배웠던 TDD의 기본 로직은 변하지 않는다. 똑같이 테스트와 구현, 중복 제거를 진행한다.

getattr

파이썬에선 메서드의 이름을 함수처럼 다룰 수 있는데, 이를 활용해 테스트 코드를 보다 간단히 할 수 있다.

class wasRun:
    def __init(self, name):
        self.wasRun = None
        self.name = name
    def run(self):
        method = getattr(self, self.name)
        method()
    def testMethod(self):
        self.wasRun = 1

test = wasRun("testMethod")
test.run()

위와 같은 코드에서, testMethod를 name으로 넣고, run()에서 getattr()를 통해 받아서 실행하게 할 수 있다.
이 후 run() 코드를 상위 클래스에 두어 모든 테스트에서 run()을 통해 테스트를 진행할 수 있도록 구현할 수 있다.

TestCaseTest

class TestCase:
    def __init__(self, name):
        self.name = name
    def run(self):
        method = getattr(self, self.name)
        method()

class WasRun(TestCase):
    def __init__(self, name):
        self.wasRun = None
        TestCase.__init__(self, name)
    def testMethod(self):
        self.wasRun = 1

class TestCaseTest(TestCase):
    def testRunning(self):
        test = wasRun("testMethod")
        assert(not test.wasRun)
        test.run()
        assert(test.wasRun)

TestCaseTest("testRunning").run()

처음 완성한 테스트는 위와 같다. test가 run했는지를 확인하기 위한 테스트인데, test F/W을 만드는데 test를 하고 있는 미묘한 상황이다.

chapter 19

3A (pattern)

테스트를 작성하다보면 발견하게되는 공통된 패턴.

  1. arrange(준비) - 객체를 생성한다.
  2. act(행동) - 어떤 자극을 준다.
  3. assert(확인) - 결과를 검사한다.

성능과 격리

테스트를 작성하다보면 3A 패턴을 확인하게되고, 여러 테스트에서 1번 arrange가 동일하게 사용되는 경우를 확인할 수 있다.
예를 들면, 7과 9의 사칙연산에서 각 사칙연산 테스트는 4개지만, 7과 9는 모든 테스트에서 사용된다. 이러한 객체들을 새로 생성하는가에 대해 두 가지 제약이 상충한다.

  1. 성능 - 테스트가 될 수 있는한 빨리 실행되길 원함. 여러 테스트에서 같은 객체를 사용한다면, 하나의 객체 생성으로 모든 테스트에서 사용하게 함.
  2. 격리 - 하나의 테스트의 성공과 실패가 다른 테스트에 영향을 주지 않길 원함.

이런 제약에서 당연히 테스트 커플링을 만들지 않는 방향으로 가는 것이 좋다.
테스트 커플링이 발생하면, A 테스트 후 B 테스트시 성공하더라도 B 테스트 후 A 테스트 시 실패하는 등 예기치 못한 동작들이 발생하기 쉽다.

chapter 20

중복이 여러 개 생길 때까지 기다리는 것이 아니라 바로바로 중복이 나올 때마다 리팩토링을 한다. (켄트 백 방식)

chapter 21

테스트 구현 순서

  1. 테스트를 통해 얻을 수 있는 것이 있고, 테스트를 만들 수 잇다는 확신이 드는 것부터 만든다.
  2. 테스트를 하나 성공시켰는데, 그 다음 테스트를 만들면서 문제가 생기면 다시 돌아가서 생각해보도록 한다.
    • 모든 테스트가 성공하던 시점을 체크포인트로 삼는 것.

필요한 것을 빠르게

TDD의 기본은 필요한 것들을 빠르게 만드는 것이다. 진짜가 될 가짜 구현을 만드는 것.

  1. 어떤 것이 필요한지를 확인한다.
    • 예를들면 Test에 testBrokenMethod()를 예상하여 만든다.
  2. 필요한 것을 빠르게 만든다.
    • test broken 상태는 많은 경우와 처리방식이 있겠지만, raise Exception 같이 핸들링하지 않고 우선 빠르게 생성한다. 아직 예외를 잡고 고치지 않았지만, 분명 선언을 한다는 것이 중요하다.

chapter 23

collecting parameter

매개변수 수집이라고 번역된 이 패턴은 메서드가 매개변수를 받아서 처리하는 것.
예를 들면, 아래와 같은 코드처럼 적용이 된다. (별 것도 아닌데 거창하게 적어놨다..)

  • 장점은 run()이 명시적으로 return하지 않아도 된다는 점이다.
  • 하지만 저 목적보단 메서드가 명확한지, 논리적인지가 중요하다. 여기선 run()이 할당하는 부분과, 할당 후 테스트를 수행하는 부분으로 나뉘는데 이는 좋지 않으므로 할당을 위에서 해주는 방식으로 수정한다.
    ```python #1 def run(self): result = TestResult() … #use

#2 def run(self, result): … #use ```

chapter 24

xUnit

xUnit은 30개 이상의 프로그래밍 언어에 포팅되어 있고, 아마 사용하려는 언어에 이미 되어있을 것.
앞선 실습처럼 xUnit을 직접 구현함으로써 얻을 수 있는 것이 있다.

  1. 숙달: 직접 만들어보면, xUnit을 이해하기 쉬움.
  2. 탐험: 새로운 언어를 접할 때, 간단한 xUnit을 만듦으로서 기능들을 경험.
  • 마틴 파울러: 소프트웨어 공학 역사에 이토록 많은 사람이 이렇게 짧은 코드로 이토록 큰 은혜를 입은 적이 없었다.

TDD python

하나 하나 따라가지 않았지만, python에서 TDD를 사용하는 방법은 java에서와 유사했다.
동일하게 TDD의 원칙에 따라 테스트와 함께 코드를 작성해나갔고,
다른점은 python의 언어 특징에 맞게 리팩토링 및 수정이 진행되었다는 점이다.