Good programmer 5 - Refactoring

in #kr-dev7 years ago

이번에는 테스트 프로그램을 정교하게 수정하고, 실제로 리팩토링을 해 봅니다.

refacto.png

입력과 출력을 가지고 테스트 프로그램을 완성해 봅시다.
test.c 코드입니다.

https://gist.github.com/doojinkang/c2db89aa4a547c940538afb42b3ce483

$ gcc -o test test.c
$ gcc -o lotto lotto.c
$ echo "4" | ./lotto | ./test

"4" 가 lotto 의 입력으로 들어가서 그 출력을 다시 test 가 받는 파이프입니다.
결과가 아무것도 나오지 않는 이유는 프로그램에 문제가 없기 때문입니다.

만일 lotto.c 를 리팩토링 하다가 실수 하는 경우라면
위의 테스트를 수행한 결과에 Test Fail 이 출력되고 버퍼에 있는 3개의 글자가 표시될 것입니다.

위의 테스트는 한번만 수행하는데, 랜덤이 있는 경우는 안심이 되지 않네요...
그래서 자동화 빌드 및 테스트 쉘 스크립트를 작성합니다.

#!/bin/bash

function compile() {
    gcc -o $1 $2
    if [ 0 != $? ]; then
        echo " Compile failure : $1"
        exit
    fi
}

function verify() {
    for i in {3..5}
    do
        echo "Testing 10 times for " $i
        for j in {1..10}
        do
            echo $i | ./lotto | ./test
        done
    done
}

compile "lotto" "lotto.c"
compile "test" "test.c"
verify

이 스크립트는 두개의 소스를 컴파일 하고
컴파일 오류가 있으면 에러를 출력하고 끝냅니다.

그리고 verify 를 하는데, 입력값이 3 ~ 5까지 각각 10번씩 테스트를 수행합니다.
이정도로 만족하지 못한다면 값을 변경하면 되겠지요?

리팩토링을 실제로 해보는 동영상입니다.

asciicast

  1. 처음에는 변수를 정리합니다. 그리고 테스트
  2. int input = get_count() 로 바꾸고 싶은데, 일단 함수만 만들고 테스트
  3. 컴파일 잘되는 것을 보고 함수로 replace 후 테스트
  4. 변수 r 의 scope 을 for 안으로 변경합니다. 그리고 테스트
  5. 여기서 좀 고민되는데, flag 를 없애고 싶습니다.
    어떤 형태로 바뀔 수 있는지 한번 생각해 보고요... 일단은 주석처리
    원하는 코드를 카피하고 새로운 함수 has_dup 를 만들고 카피합니다.
    이 함수가 컴파일 되는지 확인해야겠지요? 테스트로 가능합니다.
  6. 컴파일 에러가 생깁니다. 고쳐야죠~~~
    한참 생각해 봅니다. 어떻게 코드를 간단하게 할 수 있을지...
    flag 와 같은 변수는 함수로 만들면 제거할 수 있습니다.
  7. 컴파일이 잘 되면 원래 코드를 함수로 고치고 테스트
    또 컴파일 오류 수정 후 테스트
    이번엔 변수명을 잘못 썼네요... 이러한 실수는 테스트가 잘 막아줍니다.
  8. 어렵쇼~~~잘 된것 같은데 오류가 발생하네요... i 를 증가시키는 부분에서 오류가 났씁니다.
  9. build.sh 를 강화해서 100번씩 테스트 하도록 합니다.
    잘 되는 군요...

코딩을 잘하고 싶다면,
테스트와 리팩토링을 명확하게 할 수 있어야 합니다.
그냥 코딩하는 것보다 훨씬 더 많은 것을 이해해야 합니다.
그러기에 깊이가 생길 수 밖에 없지요.

이 경우에는 어쩔 수 없이 shell script 를 이용해서 테스트를 만들었습니다만,
이런 경우는 바람직하지 않습니다.
정말 간단한 코드인 것 같은데, 리팩토링을 쉽게 할 수 없을 겁니다.
이러한 테스트를 인수 테스트라고 하는 것 같네요. (Acceptance Test)

유닛테스트 도구를 사용해서 함수단위의 테스트를 만들면서 개발을 진행하되
이러한 인수 테스트에 대한 대비도 반드시 해야 합니다.

어떤 조직에서는 테스트 부서를 별도로 두고 있는데,
유닛테스트는 개발 담당자가 해야 합니다.
테스트 부서를 별도로 두는 것은
거대한 프로그램에서 각종 인수테스트나 스트레스 테스트를 디자인하고 실행하기 위함이지만,
사실 이것도 개발에서 커버하는 것이 더 낫지 않을까 생각되는군요.

Sort:  

thanks for the valuable information...
upvoted and followed...!!!

같은 분야이시군요~~

이런 일을 하시나요?

저는 컴퓨터과 학생입니다.^^

리펙토링 좋은 책이긴한데 초보가 보기에는 정주행이 쉽지 않죠. 어느정도 프로그래밍에 익숙해 진 다음에 봐야 더 와닿는 책인것 같아요

Congratulations @agile! You received a personal award!

Happy Birthday! - You are on the Steem blockchain for 2 years!

Click here to view your Board

Support SteemitBoard's project! Vote for its witness and get one more award!

Congratulations @agile! You received a personal award!

Happy Birthday! - You are on the Steem blockchain for 3 years!

You can view your badges on your Steem Board and compare to others on the Steem Ranking

Vote for @Steemitboard as a witness to get one more award and increased upvotes!