2010/06/05 15:21
테스트 자동화의 원칙 테스트기법/xUnit테스트패턴2010/06/05 15:21
세계 최초의 법전을 알고 계시나요? 바로 함무라비 법전입니다. (수메르 법전이라는 설도 있으나 여기서는 언급하지 않겠습니다.) 고대 바빌로니아의 함무라비 왕이 제정한 법전입니다. 왜 이러한 법전을 만들게 되었을까요? 통치의 일관성이나 사회(또는 국가) 전체가 일정한 관계를 유지하기 위해서는 질서가 필요하게 되었고, 그것을 위해서 만들어진 질서가 바로 법입니다.
테스트를 먼저 작성하면 디버깅을 줄여주어서 테스트 자동화에 드는 노력을 충분히 보상해줄 뿐만 아니라 테스트하기 쉬운 설계가 자연스럽게 나오게 됩니다.
테스트하기 쉽게 설계하지 않으면 나중에 테스트를 도입하는 것은 굉장한 노력이 듭니다. 레거시 코드에서 자동화 테스트를 도입하고자 하면 처음부터 테스트하기 쉽게 설계했을 때보다 훨씬 많은 노력이 듭니다.
되도록 public으로 공개된 인터페이스를 통해서 테스트를 진행하세요. 테스트 유틸리티 등으로 리플렉션을 이용하여 데이터를 조작하거나 모의객체를 사용하여 동작 검증을 많이 한다면 결합도가 높고 깨지기 쉬운 테스트가 됩니다.
해당 테스트가 어떠한 것을 검증하고자 하는지 의도를 들어내는 것이 중요합니다. 즉, 테스트를 읽었을 때 이것이 어떤 테스트인지 한눈에 알아볼 수 있도록 해야합니다. 그렇게 하려면 테스트코드가 길지 않아야 하며, 테스트 내에 조건문이 있어도 안됩니다.
테스트를 효과적으로 만들기 위해서 모의 객체나 테스트를 위한 하위 클래스를 만들수 있습니다. 이 때 주의할 점은 테스트 대상이 아닌 다른 것들(다른 인터페이스를 호출하는 것)은 대체해도 되지만 테스트 대상 자체(SUT)를 변경하지는 말아야 합니다. 이를 변경하는 것은 실제 제품코드가 아닌 테스트용 제품코드를 만들어 테스트하는 것이기 때문입니다.
테스트는 혼자서 실행될 수 있어야 합니다. 통합테스트 또는 인수테스트라면 모를까 단위테스트에 있어서는 반드시 독립적으로 동작을 할 수 있어야 합니다. 단위테스트는 빠른 피드백과 작은 유지비용을 유지하여 최대한 효과를 거두는 것이 중요한대 테스트가 독립적으로 동작하지 않으면 유지비용이 커져 테스트의 효과가 반감하게 됩니다.
테스트는 외부 환경에 영향을 받아서는 안됩니다. 외부환경에 영향을 받게 되면 테스트하기 힘들뿐만 아니라 테스트 결과의 일관성을 해치기 때문에 테스트 결과를 신뢰할 수 없게 됩니다.
만약 테스트를 할 때 모든 조합 또는 시나리오에 대해서 테스트하기란 불가능합니다. 따라서 작성해야할 테스트를 잘 선택하는 것이 중요합니다. 필요할 경우 적절한 테스팅 기법을 동원하는 것이 좋습니다. 특정 기능에 의존하는 테스트의 수를 최대한 작게 만들어야 합니다.
공중그네타기 연습을 하는데 안전망에 구멍이 많이 뚫려있다면 연습을 하기 꺼려질 것입니다. 마찬가지로 테스트 할 수 없는 코드가 많을수록 리팩토링을 하기도 힘들어지고 버그가 발생할 확률이 높아집니다.
테스트는 시스템의 동작을 검증하는 행위이기 때문에 테스트 대상이 되는 시스템에 테스트 코드를 넣지 마세요.
테스트 메소드 하나에 여러가지 경우의 수를 테스트하면 테스트 의도가 드러나지 않습니다. 또한 유지보수하기도 어려워지며, 테스트를 읽는 것이 매우 힘들어지죠. 따라서 각 스크립트 기반 테스트는 반드시 한 가지 테스트 조건만 검증하길 바랍니다. 결함 국소화를 위해서라도 테스트는 한가지 조건만 검증하는 것이 좋습니다.
복잡한 애플리케이션은 수많은 작은 동작들을 결합하여 하나의 동작을 하기도 합니다. 이를 한꺼번에 검증하지 말고 각각의 작은 동작들을 따로따로 테스트하는 것이 중요합니다. 11번째 원칙과 마찬가지로 하나의 테스트가 너무 많은 것을 테스트하려고 해서는 안됩니다. (이는 결국 하나의 클래스가 너무 많은 책임을 지니는 것과 동일합니다.)
테스트를 작성하고 수정하는 데 드는 노력이 해당 기능을 구현하는 데 드는 노력보다 더 들어서는 안됩니다. 일반적인 단위테스트이거나 DBUnit을 이용한 DAO 테스트라면 TDD를 적극적으로 이용하세요. 만약 모의객체를 이용하는 테스트라면 TDD를 사실상 하기는 힘듭니다. 이때는 구현을 먼저하세요.
갑자기 법전 이야기를 왜 하냐구요? 지난 포스트에서 테스트 자동화의 철학에 따라서 어떻게 자동화할 것인지에 많은 영향을 준다는 점을 알아보았습니다.(참고 : [Test/xUnit Test Patterns] - 테스트 자동화의 철학) 이러한 상황에서 테스트 작성시 일정한 질서를 유지하기 위해서는 반드시 테스트 자동화를 위한 원칙이 존재해야 한다는 것이지요. 그래야 테스트를 읽는 사람도 유지보수를 하는 사람도 쉽게 테스트 코드에 적응을 할 수 있을테니까요.
그럼 테스트 자동화의 원칙에 대해서 하나하나 알아가보겠습니다.
1. 테스트를 먼저 작성하라.
2. 테스트하기 쉽게 설계하라.
3. 정문을 먼저 사용하라.
public 인터페이스로 객체를 테스트하고 상태 검증으로 제대로 동작하는지 확인할 것을 권장합니다.
4. 의도를 드러내라.
이를 위해서 의도가 드러나는 테스트 이름의 테스트 유틸리티 메소드를 적극적으로 사용하시기 바랍니다. 또한 테스트 메소드에서 어떤 값이 입력되서 어떤 값이 출력되는지 잘 알아볼 수 있도록 테스트 코드를 리팩토링하시는 것도 중요합니다.
5. SUT를 고치지 마라.
6. 테스트를 독립적으로 유지하라.
이를 위해서 신선한 픽스처를 설치하는 것이 중요합니다.
7. SUT를 격리하라.
예를 들어, 특정 운영체제에 종속적이거나 시간에 변화에 영향을 받는 시스템이라면 테스트는 갑자기 깨질수 있습니다. 그렇기때문에 외부 환경과 SUT(테스트 대상)을 분리하는 것이 좋습니다.
의존 주입(DI)나 모의 객체 등을 잘 이용하면 SUT를 분리하고 테스트를 좀 더 반복 가능하고 견고하게 만들 수 있습니다.
8. 겹치는 테스트를 최소화하라.
9. 테스트할 수 없는 코드를 최소화하라.
되도록 환경과 테스트 대상을 잘 분리하고 변하는 부분과 변하지 않는 부분을 잘 가려내서 가능한한 많은 코드가 테스트 될 수 있도록 하세요.
10. 테스트 로직을 제품 코드에 넣지 마라.
11. 테스트별로 하나의 조건만 검증하라.
12. 따로 테스트 하라.
13. 효과와 책임을 적당하게 맞추어라.
테스트를 작성해서 얻는 이득이 적다면(예를 들어, 상위 레이어의 메소드를 그대로 호출하는 인터페이스와 같은 경우) 굳이 테스트를 만들 필요가 없습니다.
지금까지 테스트 자동화의 원칙에 대해서 알아보았습니다. 모든 원칙이나 패턴이 그렇듯이 무작정 지키려는 것은 의미가 없습니다. 원칙에서 요구하는 의도를 정확히 파악하고, 그 의도에 맞다고 판단이 되면 따르세요.
빠르게 이동해야하는 고속도로에서 무작정 준법정신을 지켜 최소속도만 유지하고 간다면 교통은 마비될 것입니다. 적당히 속도를 내는 것이 현실적으로 중요합니다.(물론 법규를 지키는 한도내에서 해야겠죠 ^^)
자신만의 테스트 자동화 원칙을 세우고 그 룰에 따르시기 바랍니다.
'테스트기법 > xUnit테스트패턴' 카테고리의 다른 글
| 테스트 자동화의 원칙 (2) | 2010/06/05 |
|---|---|
| 테스트 자동화의 철학 (0) | 2010/04/21 |
| 테스트 자동화의 목표 (0) | 2010/04/14 |

