완전 TDD 대신 테스트 가능성: 로봇 Agent를 운영 가능한 코드로 만드는 원칙
로봇 소프트웨어 개발에서는 종종 “일단 기능부터 붙이자"가 기본값이 된다. 현장 이슈가 급하고 하드웨어 변수가 많기 때문이다.
하지만 운영 단계에서 가장 비싼 비용은 기능 부족이 아니라 검증 불가능한 변경이다.
그래서 나는 완전한 TDD보다 먼저 테스트 가능한 구조를 목표로 잡았다.
문제 정의
당시 개발 환경은 아래 리스크를 동시에 갖고 있었다.
- ROS 의존성이 커서 단위 테스트 범위를 잡기 어려움
- 기능 추가 속도는 빠른데 회귀 검증 체계가 부족함
- 배포 절차보다 코드 구현이 앞서 진행되는 경향
이 상황에서 “테스트 코드를 많이 쓰자"만 외치면 실패한다.
먼저 시스템 경계를 나눠서 어디까지 자동 검증할 수 있는지를 정해야 한다.
원칙: 완전 TDD가 아니라 테스트 가능성 극대화
실제로 세운 원칙은 간단했다.
- ROS 바깥 로직은 반드시 단위 테스트 가능해야 한다.
pytest기반 최소 검증셋이 통과되어야 다음 개발로 진행한다.- 배포 프로세스와 테스트 환경 구축을 기능 추가보다 먼저 완료한다.
핵심은 방법론 이름이 아니라 운영 가능한 리듬을 만드는 것이었다.
구조적 선택
테스트 가능성을 높이기 위해 아래를 우선했다.
- 도메인 로직과 ROS 연동 코드를 분리
- 외부 입력/출력을 어댑터로 분리해 목(mock) 가능하게 구성
- 인증/등록/로깅 같은 운영 기능을 독립 모듈로 분해
이렇게 해두면 하드웨어가 없어도 핵심 로직 검증이 가능해지고, 실제 장비 테스트는 통합 단계에 집중할 수 있다.
테스트 전략(실무형)
1) 테스트 피라미드 단순화
- 단위 테스트: 상태 전이/정책 판단
- 계약 테스트: 외부 API/브로커 인터페이스
- 통합 테스트: ROS 어댑터 + 런타임 연결
2) CI 게이트
- 필수: lint + unit + contract
- 선택: HIL(hardware-in-the-loop) nightly
3) 실패 처리 기준
- flaky 테스트는 즉시 quarantine
- 배포 차단 테스트는 소수 핵심만 유지
적용 범위
이 원칙은 특정 로봇 한 대에 묶인 개발이 아니라,
ROS + Python 환경이면 재사용 가능한 Agent를 목표로 할 때 더 효과가 크다.
즉, 재사용성과 운영성을 동시에 가져가려면 기능 구현보다 먼저 테스트 가능한 구조를 만드는 쪽이 결과적으로 빠르다.
참고 및 인용
참고: 테스트 피라미드 원칙은 자동화 테스트의 비용 대비 효과를 계층적으로 설명한다. The Practical Test Pyramid
참고: pytest는 파이썬 서비스에서 빠른 단위/계약 테스트를 구성하는 표준 도구다. pytest Documentation
참고: ROS 테스트 가이드는 런타임 의존 구성 요소를 단계적으로 검증하는 접근을 제시한다. ROS Testing Tutorials
시리즈
- 1편: 운영 가능한 로봇 Agent는 프로비저닝에서 시작된다
- 2편: 앱 서버 병목에서 MQTT 브로커 분리까지
- 3편(현재 글): 기능보다 먼저 테스트 가능한 구조
- 4편: 로봇 WebRTC 스트리밍 장애를 푸는 방법