반응형

애자일 프로세스의 개발 방법론으로써 TDD(Test Driven Development)가 소개되고 또한 좋다고 하지만

실제 프로젝트에 적용하기에는 다소 어려운 것 같습니다.


1. 코드의 산출물로 유닛 테스트 코드를 짜는 문화가 있는 경우

2. 이미 프로젝트가 어느 정도 진행되어 있는 경우

3. 마음의 여유가 부족할 때(?)

....(수많은 TDD에 관한 오해와 진실, 장점과 단점들...)


TDD를 적용하기 힘든 주된 이유는 '실무에 매진하고 있어 TDD로 개발 방법을 바꾸기 어려운 상태, 즉 엄두가 나지 않는 상태'라고 생각합니다. 만약 TDD를 공부해보고 싶다? 이러면 실무와 상관 없는 간단한 프로그램을 짜면 되겠죠. 그런데 어떤 프로그램을 짜야할지 생각하는 것부터가 참 귀찮은 일이네요. 누군가가 간단한 프로젝트를 제시해주고 TDD 기반으로 개발할 수 있으면서, 사람들과 코드 리뷰도 진행할 수 있는 서비스를 제공해주면 참 좋지 않을까요? 


온라인 Coding dojo 사이트를 소개합니다. 작은 프로그램을 만들면서 TDD를 익힐 수있는 사이트입니다. dojo는 무술 훈련을 하는 '도장'이란 뜻입니다.


http://cyber-dojo.org/ 

1. 사이트 구성은 간단합니다. practice session 생성, 기존 practice session에 입장 기능이 있습니다.

practice session을 만들고 간단한 TDD 개발을 시작해보겠습니다.




2. 언어도 대부분 지원되네요. 전 Python으로 해보겠습니다.



3. 1~100의 수를 출력하면서 3의 배수에선 Fizz, 5의 배수에선 Buzz를 출력하는 Fizz Buzz program을 만들어보겠습니다.



4. OK를 누르면 다음과 같이 Session ID가 발급이 됩니다. Session ID는 다른 사람이 Practice session으로 함께 참여할 수 있는 ID입니다.



5. 세션을 시작합니다.



6. 제 동물 캐릭터가 보이네요. 다른 사용자와 함께 세션을 이용하면 동물로 서로를 식별할 수 있습니다.



7. 드디어 코딩을 할 수 있는 공간에 왔습니다.

좌측 sidebar에는 개발자 소스코드나 테스트 코드 파일을 생성/수정/삭제를 할 수 있는 버튼들이 있습니다.




8. test를 눌러보면 역시 테스트는 실패합니다.

TDD는 테스트를 먼저 만들고 실패하는 것이 특징입니다. 실패하면 실패 후 문제가 되는 조건을 최소한으로 수정하면서 테스트케이스를 늘려나가면 됩니다.




아래 순서대로 진행 해보겠습니다.

1. 테스트 스크립트 짠 후 실행/실패 하기

2. 테스트를 만족시키는 코드 구현하기

3. 리팩토링


문제. 1~100의 수를 출력하면서 3의 배수에선 Fizz, 5의 배수에선 Buzz를 출력하는 Fizz Buzz program을 만들기.

코드 복사 할 일이 있을까 싶어 화면 캡처가 아닌 코드를 Ctrl + C,V 하였습니다.


1. 테스트 스크립트 짠 후 실행/실패 하기


3의 배수를 넣었을 때 'Fizz'를 출력하는지 검증하는 테스트 코드를 짰습니다.

import fizzbuzz

import unittest


class TestFizzBuzz(unittest.TestCase):


    def test_print_Fizz_by_multiple_of_three(self):

        fizz_buzz = fizzbuzz.FizzBuzz()


        # m3 : A multiple of three

        m3 = 3

        while m3 <= 100:

            self.assertEqual(fizz_buzz.get(m3), 'Fizz')

            m3 = m3 + 3


if __name__ == '__main__':

    unittest.main()


아직 get 함수를 만들지 않아서 문제가 발생합니다.

get 함수를 만들겠습니다.

======================================================================

ERROR: test_print_Fizz_by_multiple_of_three (test_hiker.TestFizzBuzz)

----------------------------------------------------------------------

Traceback (most recent call last):

  File "./test_hiker.py", line 11, in test_print_Fizz_by_multiple_of_three

    self.assertEqual(fizz_buzz.get(i), 'Fizz')

AttributeError: 'FizzBuzz' object has no attribute 'get'


----------------------------------------------------------------------

Ran 1 test in 0.000s


FAILED (errors=1)


2. 테스트 스크립트를 만족시키는 코드 구현하기


get 함수를 만들었습니다.

 class FizzBuzz:


    def get(self, num):

        return num


여전히 테스트 코드를 만족시키지 못하고 실패합니다.

======================================================================

FAIL: test_print_Fizz_by_multiple_of_three (test_hiker.TestFizzBuzz)

----------------------------------------------------------------------

Traceback (most recent call last):

  File "./test_hiker.py", line 12, in test_print_Fizz_by_multiple_of_three

    self.assertEqual(fizz_buzz.get(m3), 'Fizz')

AssertionError: 3 != 'Fizz'


----------------------------------------------------------------------

Ran 1 test in 0.001s


FAILED (failures=1)


코드를 수정하고 다시 테스트를 돌려보겠습니다.

 class FizzBuzz:


    def get(self, num):

        if num % 3 == 0:

            return 'Fizz'



----------------------------------------------------------------------

Ran 1 test in 0.000s


OK

테스트가 성공했습니다만 100이하 중 3의 배수만 처리할 뿐 많은 문제가 아직 해결되지 않았습니다.

기타 요구사항에 대해서도 테스트케이스를 만들고 검증해야합니다.


3. 리팩토링

흔히 여러 요구사항에 대한 Feature를 구현하다 보면 스파게티 코드가 만들어질 수도 있습니다.

Feature를 추가할 때마다 리팩토링을 하면서 축적된 테스트 코드를 돌리면 자연스럽게 코드가 좋은 방향으로 구성되는 것을 보실 수 있을 것입니다.

리팩토링은 생략했습니다.


coding dojo 웹 사이트에서 TDD를 연습해봤습니다.


http://cyber-dojo.org/ 



반응형

'잡동사니' 카테고리의 다른 글

2020.11 순천만 습지  (0) 2020.12.30
[MySQL] LENGTH vs CHAR_LENGTH  (0) 2016.10.12
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • shared트위터 공유하기
  • shared
  • 카카오스토리 공유하기