Testability의 이해와 향상 방안
A사 techbard
서론
프로젝트를 바탕으로 업무를 진행해야 하는 많은 IT 관련 종사자와 마찬가지로 QA나 테스터 또한 프로젝트의 성과나 결과에 많은 영향을 받게 되며, 프로젝트를 통해 자신의 존재 가치를 증명해야 하는 숙명을 지니고 있다고 할 수 있다. 일반적으로, 이러한 프로젝트의 목표는 상당 부분 달성하기 어려우며 극한 상황에서의 인내와 이전에 경험한 다른 프로젝트에서 얻은 노하우들을 필요로 하게 된다. 특히, 갈수록 치열해지는 경쟁으로 인해 프로젝트를 제 시간 안에 효율적으로 완료할 수 있는지에 대한 중요성은 날이 갈수록 더해지고 있다. 이번 기고에서는 QA나 테스터의 관점에서 프로젝트를 성공시키기 위해 관심을 가져야 하는 요소인 Testability를 살펴 보고 이에 대한 향상 방안에 대해서 고민해 보도록 한다.
Testability란 무엇인가?
일반적인 Testability의 정의는 다음과 같다.
“소프트웨어 제품의 가시성(Observability)과 제어성(Controllability)을 의미한다.” 1)
“비기능적인(non-functional) 요구 사항이다.” 2)
“기능이나 코드의 테스트가 손쉬운지를 판단하는 특성이다.” 2)
“테스트를 시스템적으로 수행할 수 있도록 하기 위해 소프트웨어에 미리 준비된 어떤 것이다.” 2)
즉, Testability는 일반적으로 테스팅 활동으로 불리는 모든 영역에 걸쳐 영향을 주고 받게되며, 테스팅 활동은 그 자체로는 성립하지 않거나 독립적으로는 존재하지 못하고 개발팀, 프로젝트 매니저 등 기타 프로젝트 관련자들과의 상호 작용이나 관계에서만 의미가 있게 되므로, Testability 또한 포괄하는 범위가 매우 광범위하다고 할 수 있다. 그러므로, Testability와 관련한 모든 이슈를 다루기 보다는 현실적으로 많이 겪게 되는 상황과 연관된 이슈만을 다루도록 한다. 이 기고에서의 Testability는 “테스팅을 효율적이고 효과적으로 수행하게 하는 모든 방법”이라고 정의하도록 한다.
Testability가 왜 중요한가?
앞서 살펴 보았듯이, 소프트웨어 제품 테스팅 관점에서 프로젝트의 목표는 제 시간 안에 출시되어야 하며, 가능한 한 버그가 적은(또는 심각한 버그가 적은) 상태의 제품을 출시하는 것이다. 또한 무사히 제품 출시 과정을 겪었다 하더라도 이후의 유지 보수, 개정판 출시 등의 일련의 과정 또한 무시할 수 있는 작업이 아니다. 이러한 작업에는 대개 많은 지원 비용, 유지 보수 비용이 발생하게 마련이다. 따라서, 제품 출시 과정 상의 Testability의 성격과 제품 출시 이후의 Testability의 성격은 달라질 수 있다.
제품 출시 과정 중에 발생하는 테스팅 활동은 프로젝트의 성격에 따라 수 많은 방법론이 있을 수 있으나, 최소한의 테스트 활동을 통해 최대한의 결점을 검출해 내야 한다는 목표는 동일하다. 따라서, Testability의 개념이 Test Effectiveness, Test Efficiency에 지대한 영향을 미친다는 점은 확실하다. 제품의 상태에 대한 파악이 용이하고 제어된 환경에서 제품을 구동할 수 있으며, 간단한 방법으로 제품의 모드를 변경하는 등의 일련의 활동을 통해서 제품을 좀 더 다양한 입력 조건/동작 조건하에 놓이게 하면 할수록 문제를 발견해 낼 확률이 더욱 높아지기 때문이다.
특히, 제품의 출시 이후에 반드시 수행될 수 밖에 없는 Regression Testing/Re-Testing 등에서 동일한 테스트를 여러 번 반복해야 하는 상황인 경우, 이 사실은 더욱 극명하게 드러나는데 Testability가 향상되고 높을수록 적은 리소스로 테스트를 수행할 수 있음은 물론이고 테스트 자동화의 구현이 용이하기 때문이다. 이러한 일련의 상황을 통해서 많은 이득을 얻을 수 있음은 물론이고, 품질에 대한 확신을 가지기 쉬울 것이라는 점은 분명하다.
그림 1. Testability가 영향을 주는 요소들
Testability의 단계별 향상 방안
Testability의 향상 방안을 알아보기 전에 일반적인 제품 개발 프로세스에 대해서 알아보도록 하자. 각 상황에 따라 요구되는 Testability의 특성이 다르기 때문이다.
요구 사항 수집 – 분석 – 디자인 – 코딩 – 테스팅 – 구현 – 유지보수 |
표 1. 일반적인 제품 개발 프로세스(System Development Life Cycle)
1) SRS 작성 단계 : 요구 사항을 수집하여 “요구 사항 문서”를 작성, 리뷰, 확정하는 단계이다. 요구 사항에는 기능적 요구 사항 뿐 아니라 비 기능적인 요구 사항 또한 정의될 수 있다. 따라서, 이 단계에서 Testability를 향상 시킬 수 있는 개발팀의 협조를 약속 받거나(명시적인 요구 사항이 아니더라도), 프로젝트 매니저에게 Testability를 높이기 위해 개발팀에서 해주어야 하는 관련 작업에 대해서 설명하고 동의를 구해야 한다.
2) 디자인 단계 : 앞 단계에서 개발팀 및 PM 등 프로젝트 관련자와 Testability의 향상에 대해서 동의를 구한 상태라면, 이 단계에서는 테스터의 지식 수준이나 제품의 성격, 프로젝트의 상황에 따라서 사용할 수 있는 테스팅 인터페이스나, 제품 내의 테스트 코드 또는 부가적인 테스팅 툴에 대한 요구 스펙을 정해 개발팀에 전달해야 한다. 프로젝트의 막바지에 도달할수록 여러 불확정 요소들이 돌출되어 예상 대비 실제 달성이 더뎌질 수 있으므로, 개발팀의 리소스가 투입되어야 하는 이러한 작업에 대해서 프로젝트 초기부터 요구 사항으로 반영하는 것이 보다 Testability를 높일 수 있는 방법이기도 하다.
3) 코딩 단계 : 앞의 단계에서 개발 관련 인원 모두의 합의가 이루어져 있고(Testability를 향상하기로), 테스트를 손쉽게 하기 위한 구체적인 방안들도 개발팀에 전달되어 있는 상태라면 이제 실제로 제품 내에 그 요구 사항을 반영하던가, 제품의 일부 기능을 동작시킬 수 있는 스텁, 드라이버 또는 커스텀 테스팅 툴을 제작하는 단계이다.
4) 테스팅 단계 : 제품의 제작과 Testability를 높이기 위한 부가적인 작업이 완료되었다면 이제 미리 준비된 여러 방법들을 이용해서 실제로 제품을 테스팅하는 단계이다. 이 과정을 통해 개발팀에서 테스팅 인터페이스를 잘못 구현했거나, 제품 내에 테스팅을 쉽게 하기 위한 코드를 삽입했는데 그것이 본래 구현되어야 할 스펙상의 제품 기능에 영향을 미치거나 하는 상황이 발생할 수 있다. 따라서, 실제 제품 테스팅에 이를 사용하기 이전에 Testability를 개선하기 위해 개발팀에서 준비한 내용을 사전 검증하는 과정이 반드시 필요하다.
Testability 향상을 위한 상세 방안
Testability를 방해하는 상황
앞에서도 언급했듯이 Testability를 높이는 요구는 거의 테스터가 하게 되며, 그 시점은 스펙이 작성될 때 요구되는 것이 가장 좋다. 다만, 이 경우에 개발팀에서의 나름의 논리로 인해 이것이 좌절될 수도 있는데, 필자의 경험으로 보아 대강 다음의 상황이 가능할 것이다.
상황1) 제품 개발의 궁극적인 목표는 최종 사용자(End-User)를 편하게 해주어야 하는 것이다. 왜 테스터가 편하게 테스팅 할 수 있도록 개발팀에서 부가적인 작업을 해주어야 하나?
해결1) 이런 상황은 일단 개발 조직의 성숙도가 높지 않다고 판단할 수 있다. 왜냐하면, 개발 과정은 전적으로 개발팀의 몫이고 이후의 테스팅 과정은 모두 테스트/QA팀의 책임이라는 생각이 그들을 지배하고 있다고 볼 수 있기 때문이다. 특히나, 개발 조직에서는 테스팅이 상당한 비용을 소모하는 개발 활동의 일부라는 생각을 하지 못할 수 있기 때문에, 개발 관련 인원 모두(테스터 또한) 공동의 목표를 향해 프로젝트에서 각자 나름의 파트에서 최선을 다하는 것이라는 인식을 이해시키고, 따라서 테스터의 업무가 효율적으로 이루어 지도록 개발팀에서 지원하는 것이 오히려 좋은 제품과 일정 준수에 도움이 된다는 점을 서로 공유하고 있어야 한다. 상황에 따라 테스터 만으로는 이러한 인식을 공유하기가 어려울 수 있다. 이 경우 테스트 매니저나 프로젝트 매니저의 지원이 필요한 것은 물론이다.
상황2) 제품 개발 일정도 빠듯한 상황이어서 Testability 개선 요구를 들어줄 수 없다.
해결2) 이런 상황에서는 원론적인 답 밖에는 없는 것 같다. 프로젝트의 요구 사항 정의와 일정 계획에 제품 기능 구현뿐 아니라 Testability를 높이기 위한 작업들도 공식적인 업무로 추가했어야 했다. 아마 요구 했더라도 구두 상으로만 확답을 받거나 한 경우 제품의 기능 구현 과정이 계획보다 늦어지게 되면 Testability를 위한 개발팀 작업의 우선 순위가 떨어질 수도 있을 것이다.
상황3) 이미 구현되어 있는 코드에 테스트 코드를 추가하는 경우의 부작용(Side-effect)를 알 수 없기 때문에 테스트 코드를 추가하는 것은 안 된다.
해결3) 이 경우 Testability 개선을 위한 활동이 공식 업무로 계획되어 있었으나 개발팀에서 이를 잊어 버리고 작업을 진행해 왔을 수 있다. 틈틈이 개발팀의 작업 과정을 테스터가 살펴보고 테스팅을 위해 구현하기로 약속한 기능들의 구현 일정과 내용을 확인하도록 한다.
상황4) 테스트 코드나 Testability를 개선하기 위한 개발 활동들은 공식적인 개발 업무가 아닌 개인적인 활동으로 업무로 인정 받지 못한다.
해결4) 개발자나 테스터가 해결할 수 있는 문제가 아니다. 프로젝트에 대한 책임을 지고 있거나 그 보다 더 많은 책임을 가지고 있는 인원이 결정을 해야 한다. 실제 스펙 기능을 구현한 코드가 아닌 경우에라도 공식적인 업무로 인정 받아야 한다. 왜냐하면, 테스트를 용이하게 하거나 디버깅을 용이하게 하거나 그러한 사항을 고려하거나 하는 일련의 모든 활동의 목적이 결국은 문제가 적고, 제 시간에 잘 테스트된 제품을 출시하기 위한 행동이기 때문이다.
Testability를 향상시키는 구체적인 방안
이제부터 좀더 상세하게 Testability를 높이기 위한 방안을 알아보겠다. 제품 개발에 관련된 주체별로 해야 하는 역할과 할 수 있는 범위가 달라질 수 있으므로 이에 대해서 좀 더 알아보자.
방법 |
주체 |
정책의 수립, 판단, 그룹별 이슈 조정 |
매니저 |
Testability 향상을 위한 코딩 측면에서의 지원 |
개발자 |
테스팅 프로세스의 개선, Testability의 요구 및 활용 |
테스터 |
표 2. Testability를 향상시키기 위한 주체별 역할
매니저 : 많은 경우 스펙이나 요구 사항 문서는 시간이 지나면서 점점 더 쓸모 없어 지게 된다. 개발 과정이 진행될수록 초기에 생각하지 못했던 상황이나 검증되지 않았던 부분이 드러나기 때문으로, 이 경우 요구 사항 문서는 버전 1.0에서 더 이상 올라가지 않는 경우가 많다. 스펙은 테스터가 테스팅 활동을 수행하는데 있어 바이블과 같은 문서이므로 이것이 현재 개발활동과 괴리가 있게 되면 테스터의 판단 또한 자의적이고 임의적으로 흐를 수 밖에 없다. 매니저는 Testability를 향상시키기 위해 스펙 문서의 빈번한 업데이트 및 실제 개발 내용과의 동기화에 신경을 써야 한다.
많은 경우 프로젝트를 구성하는 것은 사람이며, 프로젝트의 결과로서 성공 여부를 판단할 수 있다고 하겠지만, 이에 영향을 미치는 중요한 요인 또한 사람과 사람 사이의 관계이다. 프로젝트 구성원들 모두는 나와 다른 역할을 가진 구성원에 대해서 좀 더 이해하고 의사 소통이 빈번히 이루어질 때 실수나 오류의 가능성도 줄어 들 수 있다. 따라서, 매니저가 프로젝트의 각 구성원들 간의 의사 소통에 직접 관심을 가져야 하며, 그렇게 됨으로써 Testability의 개선에 영향을 줄 수 있다. 다만, 개발자와 테스터간의 개인적인 친분으로만 업무가 진행된다면 테스터들이 객관적인 시각을 잃어버려 문제를 명확하게 지적하기 어려워 질 수 있다. 따라서, 활발하고 부드럽게 의사 소통이 진행되지만 테스터로서의 시각을 유지할 수 있는 방법이 요구된다. 매니저가 직접 실천할 수 있는 활동들에는 다음이 있을 수 있다.
테스트 팀과 개발팀 간의 공식적인 의사 소통 방법을 마련한다.
가능한 한 초기에 테스터를 프로젝트에 포함시킨다.
필요한 경우 각 그룹의 이메일을 다른 그룹으로 포워딩한다. 이는 개발팀의 일원이라는 소속감을 증대시켜 줄 것이다.
일체감을 형성할 수 있거나, 긴장을 완화시키거나, 많은 얘기를 나눌 수 있는 비 공식적인 외부 활동을 마련해 본다. (영화 보러 가기, 볼링, 도미노 쌓기 등)
개발자 : 실제 구체적으로 Testability를 향상하기 위해 중요한 역할을 하며, 코딩을 함에 있어서 테스트 코드의 추가를 용이하게 하는 구조적인 코드를 작성하거나 코딩 규칙을 준수함으로써 Testability를 높일 수 있다. 또한, 테스터가 테스트를 용이하게 하기 위한 부가적인 옵션이나 스위치를 제공해서 반복적인 테스트를 용이하게 하거나 기능을 분리해서 각각 테스트 할 수 있게 하거나, 별도의 커스텀 툴을 제공해서 결과 확인을 용이하게 하는 활동이 가능하다. 개발자가 Testability를 높일 수 있는 활동에는 다음과 같은 것이 있을 수 있다.
활동 |
역할 |
자가 테스트 코드(assertion)의 활용 |
테스트의 결과를 보다 쉽게 알 수 있게 한다. |
테스팅 인터페이스의 제작 |
실제 테스팅 해야 하는 요소가 UI 인터페이스를 이용해야만 접근할 수 있는 기능이더라도, 테스터가 쉽게 이용할 수 있는 테스팅 인터페이스를 구현하면 반복 테스트가 가능하게 되거나 다양한 방식으로 제품을 동작시켜 볼 수 있게 된다.(UI로는 불가능한) |
구현된 로직, 알고리즘에 대한 정보 제공 |
설계 문서나 코드에 추가된 주석문에 대한 정보를 제공함으로써 테스터가 부가적인 테스트 케이스를 생성해 내고 제품이 직면하게 되는 여러 상황을 가정할 수 있게 한다. |
테스트 자동화와 지역화(Localization)에 대한 촉진 방법 제공 |
테스트 자동화는 일반적으로 자동화 구현 툴에 의거해 구현되는 경우가 많은데 구현 툴에서 인식하는 UI 요소를 이용해 제품을 구현하게 되면 테스트 자동화를 용이하게 할 수 있다. 특히, 다국어 기능을 구현해야 하는 경우 사전에 약속된 방식으로 구현하면 다국어에 능숙하지 않은 테스터에게 많은 도움이 될 수 있다. 이때, String Table을 제공하는 것도 좋은 방법이 될 수 있다. |
표 3. 개발자가 Testability를 높일 수 있는 활동들
테스터 : 개발팀에 테스팅 인터페이스나 테스트 툴에 대한 요구 사항을 명확하게 요구 해야 한다. 또한, 제품을 구성하고 있는 기반 기술, 제품의 특성 등에 대해서 좀 더 심도 있게 이해하고 있어야 한다. 특히, 제품의 비즈니스 로직을 이해하는 것이 중요하다. 개발자가 디버깅을 위해 사용하는 환경에 능숙하다면 많은 도움이 될 수 있다. 많은 경우 테스팅 후에 문제가 발견되고 이의 원인을 분석하는 과정이 개발 과정에서 매우 많이 발생할 수 있으므로 테스터 역시 디버깅 환경에 익숙해 지고 그런 환경에서 테스팅을 진행할 수 있게 되면, 개발팀의 시간을 많이 절약할 수 있고 테스터 역시 버그를 찾아낼 가능성이 높아진다. 테스팅 과정에서 수 많은 툴의 도움을 받을 수도 있는데 이에 대해서는 아래의 표를 참고한다. 버그 리포트를 명확하게 작성하는 것도 Testability를 개선할 수 있다. 필자는 경험적으로 버그를 발견한 경우 그것이 2번 이상 재현이 가능한 경우에만 리포트를 하였다. 이전에 한 번만 발견된 버그를 리포트 했다가 실제로 개발자와 동석해서 재현해 보는 과정에서 재현이 되지 않아 서로 간에 시간을 낭비한 경우가 있었기 때문이다. 만일 한 번 밖에 재현되지 않는 버그를 발견했다면 더 이상 재현되지 않는 버그로 리포트를 하라. 이것을 어떻게 처리할 것인지는 차후 결정될 것이다. 이 상황에서 테스터의 임무는 버그의 원인을 찾아내는데 도움이 되는 정보(스텝, 기타 특이 상황 등)를 최대한 전달하는 것이다. 테스터가 양치기 소년이 되어서는 안 된다. 또 테스터가 팀 작업으로 테스팅을 진행하는 경우 버그 리포트의 작성 방법이나, 기술 형태가 일관성을 가지도록 노력한다. 테스터는 프로젝트 관련자들에게 신뢰와 일관성을 줄 수 있어야 한다. 버그 리포트를 작성하는 가이드를 만들어 이를 준수하도록 하는 것도 좋은 방법이다.
툴 |
용도 |
제품의 상태 및 시스템의 상태 확인 툴 |
제품의 기능을 파악하거나 기능의 오동작 여부를 쉽게 파악할 수 있게 한다. 이 경우 일반적인 운영 환경의 정보를 제공하는 툴과 특정 제품의 상태 및 정보를 제공하는 툴로 나눌 수 있다. |
로깅 툴 |
제품의 동작을 상세히 파악할 수 있게 하거나 이전 버전에서의 로그와 비교해서 차이점을 손쉽게 알아낼 수 있게 한다. |
오류 시뮬레이터 |
일반적으로 개발자가 코드를 작성하는 경우 오류에 대한 처리에 능숙하지 못할 수 있다. 따라서, 기능이 동작할 수 없을 것으로 예상되는 환경에서의 동작을 확인할 필요가 있는데, 이러한 상황은 만들어 내기 대단히 어렵다. 따라서, 디스크 용량 부족, 미디어 에러, 메모리 부족 등의 상황을 손쉽게 만들어 낼 수 있는 툴이 Testability를 향상시킬 수 있다. |
오류 덤프 툴 |
윈도우와 같은 운영 환경에서는 Exception이라고 불리는 에러가 발생하는 경우 그 내용을 파일로 저장해 주는 기능을 제공한다. 이러한 기능을 이용하면 오류를 쉽게 찾아낼 수 있거나 원인 파악이 용이해 진다. |
표 4. Testability 향상에 도움이 되는 툴
기타 고려 사항
윈도우 환경을 지원하는 제품의 경우 제품을 컴파일 하는 옵션에 따라 디버그 빌드와 릴리즈 빌드로 나누어 제공될 수 있다. 이에 대한 유효성에 대해서는 많이 논의되지 않았고, 검증도 부족한 상황이지만, 개발팀 과의 협의를 통해 어떤 형태의 빌드를 가지고 테스트 할 지를 정하는 것도 고려해볼 요소이다. 다만, 최종 출시에 사용되는 빌드는 릴리즈 빌드이므로 이것으로 테스트를 수행해야 하지 않는가? 하는 의문이 있을 수 있다. 따라서, 다수의 빌드를 테스트 하는 경우 상황에 따라 디버그 빌드와 릴리즈 빌드를 바꾸어 가며 테스트 하는 방법이 있을 수 있다.
마치며
프로젝트의 성공 책임과 역할은 몇몇 사람에게만 있지 않다. 프로젝트 구성원 모두가 각자의 영역에서 맡은 바 임무를 성실히 수행해 나갈 때만 성공이 보장된다고 할 수 있다. 특히, 국내 소프트웨어 업계의 특성상 소수의 테스터가 다수의 개발팀이 작업한 결과를 가지고 업무를 수행해야 하며, 테스팅을 고려하지 않은 제품 개발 방식으로 인해 어려움을 겪는 상황이 많은 것 같다. 더구나, 프로젝트의 막바지로 갈수록 테스팅 활동 자체가 병목이 되는 상황에서는 Testability를 향상시키는 것이 프로젝트의 성공 가능성을 높인다는 인식을 공유할 필요가 있다. 이제부터 라도 Testability에 대해서 개발팀이나 PM과 얘기를 나누어 보도록 하자. 열린 마음을 가지고 설득한다면 원하는 바를 이룰 수 있을 것이다.
- 끝 –
참고 문헌)
Lessons Learned In Software Testing: A Context-Driven Approach by Cem Kaner, James Bach, Bret Pettichord
Testing Testability by Ipsita Chatterjee
http://www.stickyminds.com/sitewide.asp?ObjectId=8077&Function=DETAILBROWSE&ObjectType=ART
Improving Software Testability by Joy Shafer
http://www.veritest.com/tn/gp_intro.asp?kb=product_cert&wp=testability
Design for Testability by Bret Pettichord
http://www.io.com/~wazmo/papers/ design_for_testability_PNSQC.pdf
댓글 영역