본문 바로가기

Theory

TDD 간단하게 알아보기(Test Drivent Development)

TDD란

TDD = Test Driven Development

→ 테스트가 개발을 이끌어 나간다.

TDD 사이클 (Test Drivent Development Cycle)

아래 사이클을 NodeJs에서 가장 많이 사용하는 Mocha를 이용해서 간단한 예제를 살펴보겠다.

TDD와 함께하는 짝수/홀수 판별 프로그램

짝수면 "Event"을, 홀수면 "Odd"를 return하는 프로그램을 작성하여라.

  1. RED

 

const assert = require('assert'); describe('짝수/홀수 판별', function () { function solution(num) { var answer = ''; return answer; } it('홀수(정답)', function () { assert.equal(solution(5), "Odd"); assert.equal(solution(7), "Odd"); }); it('짝수(정답)', function () { assert.equal(solution(2), "Even"); assert.equal(solution(0), "Even"); }); });

실패하는 코드를 만든다.

TIP) 테스트 케이스를 작성할 때 모든 테스트 케이스에 대해 고려를 하는 것이 좋다. 예를 들어 이 문제 같은 경우에 정답이 짝수인 케이스만 넣는 것 보다 정답이 홀수인 경우 - 짝수인 경우 같이 모든 경우를 넣는 것이 좋다.

당연하겠지만 오류가 난다.

  1. GREEN

 

const assert = require('assert');  describe('짝수/홀수 판별', function () { function solution(num) { switch (num) { case 0 : case 2 : return "Even"; case 5 : case 7 : return "Odd"; default : return 0; } } it('홀수(정답)', function () { assert.equal(solution(5), "Odd"); assert.equal(solution(7), "Odd"); }); it('짝수(정답)', function () { assert.equal(solution(2), "Even"); assert.equal(solution(0), "Even"); }); });

이런식으로 성공할 수 있는 최소한의 코드를 넣는다.

if문을 써도되고, 삼항연산자를 써도 상관없지만, 가장 간편할 것 같은 switch-case문으로 만들었다.


통과했다. (물론 테스트 케이스를 수정하거나 추가하면 오류가 발생한다.)

3. REFACTOR


const assert = require('assert');

describe('짝수/홀수 판별', function () {
    function solution(num) {

       // 2로 나눈 나머지 값이 0이면 Event을, 아니라면 Odd를 리턴해준다.
	var answer = EvenOrOdd(num);
			

        switch (num) {
            case 0 :
            case 2 :
                return "Even";
            case 5 :
            case 7 :
                return "Odd";
            default :
                return 0;
        }
    

      function EvenOrOdd(num){
      }

}


    it('홀수(정답)', function () {
        assert.equal(solution(5), "Odd");
        assert.equal(solution(7), "Odd");
    });

    it('짝수(정답)', function () {
        assert.equal(solution(2), "Even");
        assert.equal(solution(0), "Even");
    });

});

의사 코드를 짜주고 이를 실행할 함수를 생성했다.


  1. RED

const assert = require('assert');
describe('짝수/홀수 판별', function () {
        function solution(num) {
    
    	// 2로 나눈 나머지 값이 0이면 Event을, 아니라면 Odd를 리턴해준다.
            var answer = EvenOrOdd(num);
    			
    
            switch (num) {
                case 0 :
                case 2 :
                    return "Even";
                case 5 :
                case 7 :
                    return "Odd";
                default :
                    return 0;
            }
        
    		function EvenOrOdd(num){
					
		     return 0;    			
    		}
          }

	it('EvenOrOdd 테스트', function () {
            assert.equal(EvenOrOdd(5), "Odd");
            assert.equal(EvenOrOdd(6), "Even");
        });

    
        it('홀수(정답)', function () {
            assert.equal(solution(5), "Odd");
            assert.equal(solution(7), "Odd");
        });
    
        it('짝수(정답)', function () {
            assert.equal(solution(2), "Even");
            assert.equal(solution(0), "Even");
        });
    
    });

EvenOrOdd 테스트에서 실패한다. 다시 RED 상태가 되었다.


2. GREEN


        
const assert = require('assert');
describe('짝수/홀수 판별', function () {
            function solution(num) {
        
        	// 2로 나눈 나머지 값이 0이면 Event을, 아니라면 Odd를 리턴해준다.
        	var answer = EvenOrOdd(num);
        			
        
                switch (num) {
                    case 0 :
                    case 2 :
                        return "Even";
                    case 5 :
                    case 7 :
                        return "Odd";
                    default :
                        return 0;
                }
            
             function EvenOrOdd(num){

		  num == 5 ? return "Odd" : return "Even";

              }

          }
        
    	    it('EvenOrOdd 테스트', function () {
                assert.equal(EvenOrOdd(5), "Odd");
                assert.equal(EvenOrOdd(6), "Even");
            });
    
        
            it('홀수(정답)', function () {
                assert.equal(solution(5), "Odd");
                assert.equal(solution(7), "Odd");
            });
        
            it('짝수(정답)', function () {
                assert.equal(solution(2), "Even");
                assert.equal(solution(0), "Even");
            });
        
        });

통과하는 가장 짧은 코드를 완성해준다. (GREEN)


3. REFACTOR

        
const assert = require('assert');
describe('짝수/홀수 판별', function () {
            function solution(num) {
        
        	// 2로 나눈 나머지 값이 0이면 Event을, 아니라면 Odd를 리턴해준다.
        	var answer = EvenOrOdd(num);

	        return answer;
            }

	     function EvenOrOdd(num){
    					
		num % 2 == 0 ? answer = "Even" : answer = "Odd";
    					
		return answer;
	      }

          }
        

    	    it('EvenOrOdd 테스트', function () {
                assert.equal(EvenOrOdd(5), "Odd");
                assert.equal(EvenOrOdd(6), "Even");
            });
    
        
            it('홀수(정답)', function () {
                assert.equal(solution(5), "Odd");
                assert.equal(solution(7), "Odd");
            });
        
            it('짝수(정답)', function () {
                assert.equal(solution(2), "Even");
                assert.equal(solution(0), "Even");
            });
        
        });

결과는 변화시키지 않고 내부의 로직을 변경했다.

main의 return 값도 바꾸었다.

통과했다. (맞는 테스트 케이스를 추가해도 오류가 나지 않는다.)

TDD가 가지는 장점

  1. 코드가 맞는 길로 가고 있는지 확인할 수 있다.
    • 테스트를 통과하는지의 여부에 따라 제대로 하고 있는지를 알 수 있다.
  2. 협력이 한 층 더 쉬워진다.
    • TDD를 거친 코드는 깔끔하고 이해가 쉽기 때문에 협력에 많은 도움을 준다.
  3. 결함이 줄어든다.
    • 테스트를 돌리며 진행하기 때문에 버그를 없앨 수 있기 때문이다

TDD가 가지는 단점

  1. 개발 시간이 증가한다.
    • 평균적으로 10~30%까지 개발 시간이 증가한다.
  2. 어렵다.
    • 기존 방식을 벗어나야 하기 때문이다.

참고 문헌

[Agile] TDD(테스트 주도 개발)란 - Heee's Development Blog