etc/TDD

켄트백의 TDD 3회차 스터디 18장-24장(~200p)

빠니몽 2023. 6. 27. 17:02

06.27.2023

 

1. 전체 코드 공유 (The final code)

class TestCase:
    def __init__(self, name):
        self.name = name
    
    def run(self, result):
        result.testStarted()
        self.setUp()
        try:
            method = getattr(self, self.name)
            method()
        except:
            result.testFailed()
        self.tearDown()

    def setUp(self):
        pass
    
    def tearDown(self):
        pass

class WasRun(TestCase):
    def __init__(self, name):
        self.wasRun = None
        TestCase.__init__(self, name)
        
    def setUp(self):
        self.log = "setUp "  
        
    def testMethod(self):
        self.log = self.log + "testMethod "
    
    def tearDown(self):
        self.log = self.log + "tearDown "
        
    def testBrokenMethod(self):
        raise Exception

class TestResult:
    def __init__(self):
        self.runCount = 0
        self.failureCount = 0
    
    def testStarted(self):
        self.runCount = self.runCount + 1
    
    def testFailed(self):
        self.failureCount = self.failureCount + 1
    
    def summary(self):
        return "%d run, %d failed" % (self.runCount, self.failureCount)

class TestSuite:
    def __init__(self):
        self.tests = []
    
    def add(self, test):
        self.tests.append(test)
    
    def run(self, result):
        for test in self.tests:
            test.run(result)

class TestCaseTest(TestCase):
    def setUp(self):
        self.result = TestResult()

    def testTemplateMethod(self):
        test = WasRun("testMethod")
        test.run(self.result)
        assert(test.log == "setUp testMethod tearDown ")
    
    def testResult(self):
        test = WasRun("testMethod")
        test.run(self.result)
        assert("1 run, 0 failed" == self.result.summary())
        
    def testFailedResult(self):
        test = WasRun("testBrokenMethod")
        test.run(self.result)
        assert("1 run, 1 failed" == self.result.summary())
    
    def testResultFormatting(self):
        self.result.testStarted()
        self.result.testFailed()
        assert("1 run, 1 failed" == self.result.summary())
        
    def testSuite(self):
        suite = TestSuite()
        suite.add(WasRun("testMethod"))
        suite.add(WasRun("teestBrokenMethod"))
        suite.run(self.result)
        assert("2 run, 1 failed" == self.result.summary())

suite = TestSuite()
suite.add(TestCaseTest("testTemplateMethod"))
suite.add(TestCaseTest("testResult"))
suite.add(TestCaseTest("testFailedFormatting"))
suite.add(TestCaseTest("testFailedReuslt"))
result = TestResult()
suite.run(result)
print(result.summary())

 

2. 플러거블 셀렉터 패턴 (Pluggable Selector pattern)

호출될 메소드의 이름을 클래스 내에 저장하고, 리플렉션을 이용해 그 메소드를 호출하는 패턴.
하나의 상위클래스를 여러개의 하위클래스가 상속받고 있고, 하위클래스들이 상속받지 않은 각각 다른 메소드들을 가지고 있을 때 사용될 수 있는 패턴입니다.
167페이지에 중간 코드를 보면 testRunning, testMethod와 같은 메소드들이 name을 통해 호출됩니다.

다만 사용해야하는 순간은 한정되어있습니다.

  • 테스트 대상 클래스가 어떤 명칭의 테스트 함수를 구현하게 될지 알 수 없을 때
  • 서로 다른 메소드가 한 개씩만 존재할 때와 같은 직관적인 상황에서 코드를 정리하고 싶을 때