클라이언트/ 서버/ 엔지니어 " 게임 개발자"를 향한 매일의 공부일지

나의 첫 테스트 코드 1 - 왜 테스트 코드가 필요할까? 본문

웹 · 앱 개발/디버깅

나의 첫 테스트 코드 1 - 왜 테스트 코드가 필요할까?

huenuri 2024. 7. 30. 11:04

3단원 학습에 들어가본다. 원래는 오늘 오후에 이 단원을 모두 학습하려고 했는데 가족들과 시간을 보내다보니 오후 시간이 많이 지나갔다. 그래도 이런 시간도 정말 소중하니 아까워하지 않는다.
이 단원은 아주 길지는 않아서 저녁시간 전까지 학습할 수 있을 것 같다. 하지만 언제나 난 계획보다 더 많은 시간 걸리므로 초과될 수 도 있다. 그러면 바로 학습에 들어가보자.

조금 전에 미션 문제가 얼마나 어렵던지 건너뛰고 싶었지만 그래도 2/3 이상 풀어서 뿌듯하다. 이제는 디버깅을 만나도 당황하지 않고 어떻게 해결할 수 있을지 고민하고 질문해보게 된다.
3단원을 마치고나면 스스로 테스트 코드도 작성하며 디버깅 실력이 한층 상승할 것으로 기대한다.


 

 

이론 1 - 왜 테스트 코드가 필요한가요?

 

예시 1

 

 

 

 

 

이 함수가 어느 상황에서나 잘 동작하는지 확인할 필요가 있다. 그러나 이 함수는 numbers가 비어있을 때 에러를 낸다. 그렇기에 테스트 코드를 통해 맞게 짠 코드인지 에러인지 확인해볼 수 있다.

 

 

 

 

예시 2

average 함수를 다르게 바꾸어보았다. 숫자의 길이가 있는 경우만 평균값을 구하고, 아니면 애러 메시지를 출력하는 코드이다.
이렇게 작성한 코드를 다음과 같이 수정하려고 한다.

 

 

 

 

코드를 수정했지만 동일하게 동작하기를 원한다.

 

 

 

 

코드를 수정했을 때 원래 코드와 수정한 코드가 동일하게 동작하는지 확인해보고 싶을 때 테스트 코드를 사용한다.

 

 

 

 

 


 

이론 2 - 유닛 테스트

 

유닛 테스트란 무엇인가?

유닛 테스트에서 유닛은 가장 작은 단위를 뜻한다. 유닛 테스트는 함수 하나가 잘 작동하는지 확인하는 함수이다.

 

 

 

 

우리는 함수의 인자와 리턴값을 확인하게 된다. 인자에 맞추어 리턴값이 바뀌어 설계되고 있는지 확인하는 것이 유닛 테스트이다.

 

 

 

예시 1

is_palindrome이라는 함수는 text라는 매개변수를 받고 있다. 어떤 text가 회문인지 확인하는 함수이다. 회문이란 앞으로 읽어도 뒤로 읽어도 똑같은 단어나 문장을 말한다. 영어로는 level, 우리말로는 수박이박수, 토마토 등이 있다.
이 함수는 회문이면 true 아니면 false를 리턴한다.

 

 

 

테스트 함수를 2개를 짜보았다. assert는 분홍색으로 되어있는데 이것은 파이썬의 기본 함수라는 뜻이다. assert 괄호 안의 내용이 true라면 아무 일도 일어나지 않는다. 하지만 false라면 에러를 보내면서 프로그램은 종료된다.
만약 이 테스트를 통과하지 않는다면 assert문이 false가 되도록 test문을 짜보면 된다. 이 함수를 잘못 짜서 assert문이 false가 되면 프로그램이 종료되는 것이다.

lever는 회문이 아니므로 이 함수는 false가 되고, false와 같기에 결과적으로 함수는 true가 된다.
다양한 인자를 넣어보며 잘 작동하는지 실험해볼 수 있다. 하나의 함수에서 작동한다고 이 함수가 올바르다고 말할 수는 없다.

 

 

 

 

예시 2

assert에서 빈 문자열이 들어온다. 이 빈 문자열은 회문일까? 이 문장도 앞에서 뒤에서 읽어도 알파벳 순서가 같다. 순서가 같다고 반드시 회문이라고 할 수 있을까? 점과 띄어쓰기의 여부도 다르다.
이것은 프로그래머의 설계에 따라 달라지는 부분이다.

 

 

 

 

유닛 테스트의 결과

이 말은 역도 성립이 되는데, 어떤 출력을 의도하는지에 따라 테스트 작성이 바뀌게 된다. 프로그램을 설계했다면 자신이 어떤 테스트를 작성을 할지 설계할 수 있다.
일반적으로 설계 -> 코드 짜기 -> 설계를 한다고 생각하지만, 어떤 경우에는 설계 후에 코드와 테스트의 순서를 바꾸기도 한다.

이것을 Test-Driven Development라고 이야기한다. 테스트를 먼저 짜고 코드를 돌려보면 이 코드의 부족함, 예외 상황 등을 쉽게 확인할 수 있다. 이 또한 개발자의 선택에 따라 달려있는데, 중요한 것은 테스트가 설계를 반영한다는 것이다. 그렇기에 테스트 코드를 잘 작성해야 한다.


 

실습 1 - Palindrome 테스트

문제 설명

주어진 문자열에서 대소문자, 공백, 특수문자는 무시하고, “다시 합창합시다!”와 같은 문장도 빈 문자열도 회문으로 취급하고 있다.
helper라는 함수도 main 함수도 잘 들어있음을 확인했다.

 

 

 

 

 

문자열 "madam"에 대하여 회문이므로 true하고 있다. 각 문자열마다 테스트가 설계되어 있는데 이대로 작성을 해주면 될 것이다.
출력 코드가 없다는 말은 테스트를 잘 작성했다는 말이다. 그럼 이제 영상을 끄고 혼자서 이 문제를 풀어보자!

 

 

 

 

직접 풀어보기

 

에러 코드가 안뜨는 걸 보니 테스트 코드가 잘 작성이 된 걸 알 수 있다.

 

 


 

첫번째 단원 학습을 마치고

테스트 코드가 왜 필요한지 확실히 알게 되었다. 에러 코드를 줄이기 위해서는 먼저 테스트 코드를 작성하기도 하며 코드를 먼저 작성하기도 하는 등 이 둘은 서로 연관되어 있었다.
나도 프로그램을 짜게 되면 버그가 많은데 앞으로는 이러한 버그를 줄일 방안으로 테스트 코드를 짜는 것도 한번 고려해보려고 한다.

지금은 내가 알고 있는 프로그래밍 지식이 많지 않지만, 나중에 프로그램을 만들 때는 이 작업은 반드시 필요한 작업임을 이 수업을 통해 배울 수 있었다.
실습 문제에서 회문을 작성하는 작업은 정말 재미있었다. 오랜만에 내가 풀 수 있는 문제를 만나서 반가웠다. 앞으로 나의 디버깅 실력도 한층 좋아질거라 기대해본다~