•
레거시 코드를 취급할 때 우리는 객체의 기존 동작에 대한 테스트 루틴을 작성해, 안전망을 제공해 주어야 한다.
문서화 테스트
•
필요한 테스트 루틴을 어떻게 작성해야 할까?
•
한 가지 방법은 소프트웨어가 해야 하는 일을 찾은 후 이에 기반한 테스트 루틴을 작성하는 것이다.
◦
기존의 문서들을 모두 탐독해서 레거시 시스템에 대한 기대치를 찾은 후 이에 기반한 테스트 루틴을 작성하는 것이다.
•
그러나 대부분의 레거시 시스템에게 기대되는 바는 어떻게 동작해야 하는지보다 실제로 어떻게 동작하고 있는가가 더 중요하다.
◦
변경 작업을 명확히 하기 위해 테스트 루틴을 정확한 위치에 작성하는 것이다.
•
기존 동작 유지에 사용하는 테스트를 저자는 문서화 테스트라고 부른다. 문서화 테스트는 코드 실제 동작의 특징을 나타내는 테스트다.
◦
시스템이 이 작업을 수행한다거나 이 작업을 수행하는 것 같다가 아닌 시스템의 현재 동작을 그대로 문서화하는 테스트다.
•
문서화 테스트를 작서앟는 순서는 다음과 같다.
1.
테스트 하네스 내에서 대상 코드를 호출한다.
2.
실패할 것임을 알고 있는 검증문을 작성한다.
3.
실패 결과로부터 실제 동작을 확인한다.
4.
코드가 구현할 동작을 기대할 수 있도록 테스트 루틴을 변경한다.
5.
위 과정은 반복한다.
•
이런 테스트는 소프트웨어가 반드시 따라할 규칙을 의미하는 것이 아니다. 버그를 찾는 것이 목적이 아니기 때문이다.
•
시스템의 현재 동작과의 차이로 나타나는 버그를 나중에 찾기 위한 구조를 만드는 것이 목적이다.
•
이처럼 시스템의 실제 동작을 문서화하기 때문에, 문서화 테스트라고 부른다.
클래스 문서화
•
특정 클래스를 대상으로 무엇을 테스트해야 할지 결정하고 싶다고 하자. 어떻게 해야 할까?
•
가장 먼저 해야 할 일은 상위 수준에서 클래스의 동작을 파악하는 것이다. 해당 클래스가 사용되는 조임 지점마다 간단한 동작부터 복잡한 동작까지 다양한 용법이 존재할 것이다.
•
저자의 경험에 따르면 다음의 기준을 따르는 것이 좋다.
1.
로직이 엉켜 있는 부분을 찾는다. 코드에 이해할 수 없는 부분이 있다면 감지 변수를 사용해 해당 부분을 문서화할 것을 검토한다. 즉 코드의 특정 부분이 실행되는지 확인하기 위해 감지 변수를 사용한다.
2.
클래스나 메소드의 책임을 파악했으면 일단 작업을 멈춘 후, 실패를 일으킬 수 있는 것들의 목록을 만든다. 그리고 그러한 실패를 일으키는 테스트 루틴을 작성할 수 있는지 고려한다.
3.
테스트 루틴에 전달되는 입력 값을 검토한다. 극단적인 값이 주어질 경우 어떤 일이 벌어질 지 확인해야 한다.
4.
객체가 살아있는 동안 항상 참이어야 하는 조건이 존재하는 지 확인한다. 이런 조건을 불변 조건이라고 부르며 이를 테스트하기 위한 루틴을 작성해야 한다.
•
불변 조건을 발견하기 위해 클래스를 리팩토링해야 할 수도 있다.
•
이런 문서화 테스트는 결국 명세로써 사용되어지기 때문에 가독성이 중요하다.
◦
테스트 순서의 배열 등을 의식적으로 읽기 쉽게 만들어 두어야 한다.
정해진 목표가 있는 테스트
•
코드의 특정 부분을 이해하기 위한 문서화 테스트 루틴을 작성했다면 변경 대상의 범위를 보고 테스트 루틴이 그 범위를 포함하는 지 확인해야 한다.
•
조건 분기가 포함된 테스트 루틴을 작성할 때는 해당 분기를 실행하지 않고 테스트가 통과될 가능성이 있는지 주의 깊게 관찰해야 한다.
◦
확신이 서지 않는다면 감지 변수나 디버거를 통해 직접 확인해보는 것도 방법이다.
문서화 테스트를 작성하기 위한 경험칙
1.
변경 대상 부분을 위한 테스트 루틴을 작성한다. 코드의 동작을 이해하는 데 필요해 보이는 테스트 케이스를 가급적 많이 사용한다.
2.
테스트 루틴을 작성한 후, 변경하려는 구체적인 코드들을 조사하고 이에 관련된 테스트 루틴을 작성한다.
3.
기능을 추출하거나 이동할 경우, 기존의 동작이나 동작 간의 관계를 검증하는 테스트를 개별적으로 작성한다. 이를 통해 이동 대상 코드가 실행되는지, 그리고 적절히 관계를 유지하는 지 검증한다. 검증이 끝난 후 코드를 이동한다.