소프트 웨어를 테스트 하는 것은 매우 중요한 절차로 개발 과정에서 여러 부분에서 테스트를 하는 방법이 존재한다. 이번에는 이러한 테스트에 관련해서 정리를 하려고 한다.
프로그램을 검증하는데는 크게 단위테스트, 통합 테스트, 인수 테스트 등이 존재한다. 이외에도 많은 것들이 있겠지만 가장 많이 쓰이는 이 3가지를 정리하려고 한다.
단위 테스트
단위 테스트는 응응 프로그램에서 테스트 가능한 가장 작은 소프트웨어를 실행하여 예상대로 동작하는지 확인하는 테스트이다.
가장 작은 소프트웨어란 무엇일까? 자바의 입장에서 생각하면 단순한 클래스 또는 메소드 수준일 것이다. 이렇게 가장 작은 단위에 대해 검증을 진행하는 것이 어떠한 장점을 가질까? 애초에 이러한 테스트가 생기게 된 이유가 무엇일까?
TDD 프로세스에 대해 생각해보면 단위 테스트의 목적이 좀 더 명확해진다.
TDD
먼저 TDD는 테스트 케이스를 작성 한 후 실제 코드를 개발하여 리팩토링 하는 절차를 의미한다.
그림 1은 학교 과제를 수행할 때 주로 수행하는 방법이다. 이러한 방법은 정신없이 코드 개발을 해놓고 테스트를 만들게 되는데 이때 여러 문제가 발생하는데 주로 테스트 케이스가 빠지거나 추상적인 테스트 케이스는 코드 내에 어떤 문제가 발생하는지 발견하는데 오랜 시간이 걸리게 된다.
즉, 기존의 프로세스는 코드의 결과가 상황이나 여러 원인 때문에 불확실성이 높아질때 사용하기가 점점 더 어려워 질것이다. 좀 더 구체적으로 TDD를 사용해야하는 상황을 정리해보자면
- 처음 해보는 프로그램 주제
- 고객의 요구조건이 수시로 바뀔 수 있는 프로젝트
- 개발하는 중에 코드 수정이 많이 바뀔 수 있는 경우
- 내가 개발한 코드에 대한 유지보수를 진행할 사람이 정해지지 않은 경우
위의 상황은 모두 불확실성이 높다고 이야기 될 수 있는 환경이다. 이러한 환경에서 그림 1처럼 기존의 방식으로 코드를 작성하다보면 어느순간 내가 길을 잃어 헤매게 되는게 벌써부터 상상이 된다.
그러면 이러한 상황에서 어떠한 프로세스로 프로그램을 만들어 나가야할까?
최대한 프로그램의 최종 요구사항을 쪼개서 여러 Task화 시켜서 이들에 대해서 하나씩 처리하면서 진행하는 블록쌓기 처럼 진행이 되어야 할 것이다. TDD는 이러한 Task에 대한 테스트 케이스를 먼저 작성하고 이들에 대해 성공을 초점을 두어 코드를 작성한다.
이런식으로 TDD 프로세스로 코드를 만들어 가면 아래의 장점을 가지게 된다
- 튼튼한 객체 지향 코드 생산
TDD는 기능별 모듈화가 이뤄진 상황을 기반으로 개발을 진행하기 때문에 객체 지향적인 개발에 사용하기 용이하게 된다. - 재설계 시간의 단축
이건 마치 study planner를 작성하고 공부를 하는 것과 비슷한 효과다. 내가 지금 하는 것의 목표가 명확하면 다른 기능들에 대해 신경을 쓰면서 집중이 분산되지 않을 것이다. - 디버깅 시간의 단축
테스트 케이스가 성공을 못하면 해당 테스트 케이스가 수행되는 지점에서 문제가 발생한것은 명확하기 때문이다.
물론 이런 방식의 코드는 전체적인 코드의 길이를 증가 시킬 수 있고 개발속도가 느려질 수 있지만 좋은 코드를 만드는데 큰 도움이 될 프로세스임은 명확하다.
이렇게 TDD에 대해서 알아보았다. 우리가 TDD기반의 프로세스로 프로그램을 개발할 때 그럼 테스트 케이스는 어떻게 선정할까?
이러한 관점에 단위 테스트에 대한 논의가 이뤄진 것으로 생각된다.
앞써 말했듯이 단위 테스트는 프로그램에 대한 가장 작은 단위를 대상으로 테스트 케이스를 작성하고 이를 검증하는 테스트 방법이다. 이렇게 가장 작은 단위로 테스트 케이스를 작성하면 TDD에서 가지는 장점을 그대로 가져올 수 있다.
가장 작은 단위에 대해 테스트를 진행한다고 하면 해당 테스트를 담당하는 메소드나 클래스가 모듈화가 되어있어야 할것이다. 이는 튼튼한 객체지향 코드를 생산 해내는데에 당연한 이점이 될 수 밖에 없다. 또한 단위테스트로 테스트 케이스를 설정할 경우 디버깅에 대한 대상도 가장 작은 단위인 메소드나 클래스가 될 수 밖에 없다. 이는 점검을 해야하는 대상이 좀 더 명확해진다는 점에서 TDD의 장점을 좀 더 강화시켜준다.
그럼 무조건 잘게 나눠서 테스트를 하는게 좋을까? 물론 그것은 아닐 것이다.
많이들 이야기하기로 테스트 케이스는 다음 FIRST라는 5가지 규칙을 따라야 한다고 한다.
- Fast : 테스트는 빠르게 동작할 수 있어야한다.
- Independent : 테스트는 독립적이며 서로 의존적이면 안된다.
- Repeatable : 어느 환경에서도 반복적일 수 있어야한다.
- Self-Validating : 테스트의 결과는 boolean타입으로 나와야한다.
- Timely : 테스트하려는 실제 코드를 구현하기 직전에 구현해야한다.
무조건 잘게 나누는 것이 좋은 것은 아니지만 다음 5가지 규칙을 따르게 만들기 위해서는 Unit Test가 가장 적합하다고 볼 수 있을 것이다.
통합 테스트
통합 테스트는 단위 테스트 보다 더 큰 동작을 달성하기 위해 여러 모듈을 모아 이들이 의도대로 협력하는지 확인하는 테스트이다.
이는 DB에 접근하거나 전체 코드와 다양한 환경이 제대로 동작하는지 검증하는데 수행하는 테스트로 해당 테스트가 잡아낼 수 있는 문제상황으로는 주로 환경 버그가 존재한다.(ex, 싱글코어 환경에서는 잘 수행되던 프로그램이 멀티코어 환경에서 문제가 되는 경우)
물론 통합테스트는 단위 테스트의 장점을 가지지 못하지만 위에서 말한 환경버그를 찾아내는 데에는 효과적이라고 이야기 될 수 있을 것이다.
인수 테스트
소프트웨어 인수를 목적으로 하는 테스트로 실제 사용자 관점에서 테스트를 하는 경우를 의미한다. 따라서 앞에서 말한 테스트와 달리 E2E(End to End)형식을 이용해서 확인하게 된다. 이를 위해서는 프로젝트에 참여한 사람들이 토의를 통해 시나리오를 만들고 해당 시나리오에 의거해서 개발자들이 테스트를 돌리게 된다.
참조
https://ko.wikipedia.org/wiki/%EC%9C%A0%EB%8B%9B_%ED%85%8C%EC%8A%A4%ED%8A%B8
http://clipsoft.co.kr/wp/blog/tddtest-driven-development-방법론/
'Computer Science' 카테고리의 다른 글
웹 서버와 WAS (0) | 2021.12.29 |
---|---|
오버라이딩 vs 오버로딩 (0) | 2021.12.28 |
상속과 다형성 (0) | 2021.12.27 |