서론
이전 포스팅에서 테스트 코드의 필요성을 느꼈다는 글을 적었습니다.
이에 대한 최근 근황을 작성해보려고 합니다.
흐려지는 동기
테스트 코드가 아니어도 이미 많은 업무를 처리하다 보니 테스트 코드를 작성하는 동기가 점점 흐려졌습니다. (외면하게 되었다는 게 맞겠네요... 🥲) 이 흐려지는 동기를 해결하기 위해 저는 테스트 코드 작성을 팀의 레벨로 올려서 진행했습니다.
저희 회사는 1명이 프로젝트를 온전히 담당하는 구조라서 같은 프로젝트를 진행하는 안드로이드 개발자와 이야기를 나누어보았습니다.
다행히 안드로이드 개발자분도 "테스트 코드를 작성하고 싶은데 혼자 하려니 계속 미루게 된다"는 똑같은 고민을 하고 있었습니다.
저는 같은 앱이 다른 테스트 시나리오를 가져가야 할지 고민하고 있었기에, 안드로이드 개발자와 테스트 시나리오를 공유하며 함께 진행하기로 결정했습니다. 이렇게 두 명이 서로의 동기가 되어주고 서로 조언을 주고받으며 협업한 결과, 흐려지던 동기를 어느 정도 해결할 수 있었습니다.
어떤 걸 테스트할 것인가
안드로이드 개발자와 무엇을 테스트할지 논의한 결과, 로직을 테스트하는 것으로 쉽게 결론이 모아졌습니다.
UI는 자주 변경되기 때문에 테스트의 실효성을 저희 모두 크게 느끼지 못했습니다.
로직은 UI보다 변경되는 지점이 적고,
사이드이펙트처럼 예상치 못한 문제가 발생했을 때 발견하기도 어렵기 때문에 테스트 코드라는 방어막을 세우기로 했습니다.
그리고 저희 둘 모두 같은 비효율을 경험하고 있었습니다.
로직을 테스트하기 위해 앱을 실행하고 하나하나 눌러보며 동작을 확인하는 과정이 무척 비효율적이었기 때문입니다.
예를 들어, 내 서재 화면에서 한 번에 요청 가능한 도서 다운로드 수는 총 20권입니다.
20권의 도서를 다운로드 요청하면 더 이상 도서 다운로드를 요청할 수 없다는 알림이 표시됩니다.
이를 직접 테스트하려면 다운로드 완료한 도서를 지우고 20권의 도서를 하나씩 눌러서 다운로드를 요청한 뒤 알림을 확인해야 했습니다.
테스트 코드로는 몇 초 만에 검증이 가능한 것을 직접 테스트하면 3~4분이 넘게 소요되었습니다.
이런 비효율을 해결하고 싶었기에 로직 테스트를 결심했습니다.
테스트 시나리오 작성
테스트 시나리오를 문서화할 때는 또 다른 고민이 있었습니다. 간결하면서도 의미가 명확하고 통일성 있게 작성하는 방법이 필요했습니다. 같은 프로젝트 담당자가 아니더라도 이해할 수 있는 문장을 작성하고 싶다는 공감대가 있었기 때문입니다. 저희는 테스트 대상을 정확히 파악하고 사용자 관점에서 문장을 작성하기로 결정했습니다.
위 예시를 이어서 설명하면, 해당 시나리오는 두 개의 테스트로 나눌 수 있습니다. 도서 다운로드는 최대 20권까지 가능하다는 것과 최대 요청을 넘으면 알림을 표시한다는 것입니다. 이렇게 두 가지로 나누니 간결성과 명확성을 모두 확보할 수 있었습니다.
이를 문장으로 작성하면 다음과 같습니다:
1. 도서 다운로드 요청 개수가 20권 이하라면 다운로드 대기열에 추가된다.
2. 도서 다운로드 요청 개수가 20권을 초과하면 에러 알림을 표시한다.
이렇게 작성하니 주어, 조건, 결과가 통일성 있게 표현되었습니다.
또한 Lokalise 서비스 도입으로 알림 문자열도 확인할 수 있게 되어, 두 번째 테스트는 "도서 다운로드 요청 개수가 20권을 초과하면 'download_failed_message' 메시지를 알림으로 표시한다"로 더 구체적으로 표현할 수 있었습니다.
이렇게 하여 다른 서비스 담당자도 이해할 수 있고, 하나의 로직만 테스트하며, 역할을 명확하게 담은 간결한 시나리오를 작성할 수 있었습니다.
테스트가 즉시 가능한 것과 아닌 것
테스트 시나리오를 작성하고 보니 바로 테스트할 수 있는 항목이 많지 않았습니다.
로직을 테스트하기 위해서는 UI 코드와 로직이 분리되어 있어야 하고, 네트워킹 동작도 독립적으로 분리되어야 했기 때문입니다.
하지만 현실의 코드는 모든 것이 한데 뭉쳐있는 MVC 구조였고, 이는 안드로이드도 마찬가지 상황이었습니다. (MVC라고 하는 것도 미안한 화면이 많았습니다 ㅋㅋ)
저희는 테스트 코드를 작성하기에 앞서 시나리오를 세 가지로 분류했습니다:
1. 이미 테스트 코드가 있는 것
2. 테스트 코드를 바로 작성할 수 있는 것
3. 구조 개선이나 역할 분리가 선행되어야 하는 것
1번은 거의 없었고, 2번도 적었으며, 대부분이 3번에 해당했지만,
이렇게 표로 정리하니 해야 할 일들이 명확하게 보였습니다.
오히려 이 과정에서 코드 개선에 대한 동기가 더욱 강해졌고, 리팩토링의 우선순위도 자연스럽게 정립되었습니다.
이전에는 즉흥적으로 진행하던 코드 개선이, 이제는 우선순위에 따라 계획적으로 진행될 수 있었습니다.
명확한 시나리오가 있었기에 구조 개선의 방향도 분명했고, 개선된 코드에 대해 테스트를 작성하면서 느끼는 성취감도 컸습니다.
처음에는 당장 테스트할 수 있는 부분이 적다는 것이 아쉬웠지만, 점진적인 구조 개선을 통해 자연스럽게 테스트 가능한 코드가 늘어났고, 이는 코드에 대한 확신과 안정감으로 이어졌습니다.
마무리
테스트 코드 작성은 혼자서는 시작하기 어려운 여정이었지만, 팀 차원의 접근으로 해결할 수 있었습니다.
같은 고민을 하던 동료와 함께 테스트 시나리오를 공유하고, 무엇을 테스트할지 결정하며, 코드 구조를 개선해 나가는 과정은 매우 값진 경험이었습니다. (지금도 열심히 하고 있고요 ㅎㅎ)
특히 처음부터 완벽한 테스트 환경을 기대하기보다
현재 상황을 정확히 파악하고 점진적으로 개선해 나가는 접근이 효과적이었습니다.
테스트 코드 작성을 통해 얻은 것은 단순히 버그 방지나 코드 품질 향상만이 아닙니다.
동료와의 협업이 강화되었고 코드 구조에 대한 더 나은 고민을 할 수 있었으며 체계적인 리팩토링의 기회도 얻을 수 있었습니다.
이제는 테스트 코드 작성이 부담스러운 추가 업무가 아닌, 개발 과정의 자연스러운 한 부분으로 자리 잡았습니다.
여러분도 주변에 테스트 코드 작성을 망설이는 동료가 있다면 함께 시작해 보면 어떨까요?
또 다른 재미를 느낄 수 있을 겁니다 ㅎㅎ
다음 글은 지금도 열심히 고민 중인 "역할 분리"에 대한 경험을 공유해 보겠습니다.
감사합니다.
아직은 초보 개발자입니다.
더 효율적인 코드 훈수 환영합니다!
공감과 댓글 부탁드립니다.