# 일반적인 테스트 오류 사례와 해결 방안

#### 테스트 환경 설정 오류

ROS2 Humble 기반 프로젝트에서 테스트를 수행할 때 가장 빈번하게 발생하는 문제 중 하나는 테스트 환경 설정이 올바르지 않은 경우이다. 예를 들어 의존성이 제대로 설치되지 않았거나, ROS2의 워크스페이스 설정이 잘못되어 테스트 대상 노드가 런칭되지 않는 상황 등이 해당된다.

* **빈번한 증상**
  * `colcon build` 후 `colcon test` 명령어 실행 시 테스트 대상 패키지를 찾지 못함
  * 테스트 실행 시 의존성 패키지가 로드되지 않아 노드가 시작되지 않음
  * 테스트를 위한 launch 파일에서 잘못된 파라미터나 노드 이름이 명시되어 실행 불가
* **해결 방안**
  1. **워크스페이스 재설정**: 테스트 전 `source ~/ros2_humble/install/setup.bash` 를 다시 수행하여 환경 변수를 재설정한다.
  2. **패키지 의존성 확인**: 패키지 내 `package.xml`과 `CMakeLists.txt`에서 필요한 의존성 목록이 누락되지 않았는지 확인한다.
  3. **테스트용 Launch 파일 검증**: 잘못된 파라미터나 토픽 이름으로 인해 테스트가 실패하는 경우가 많으므로, 실제 구동 환경과 동일한 설정인지 사전에 꼼꼼히 확인한다.
  4. **ROS\_DOMAIN\_ID 확인**: 도커 환경이나 여러 장비에서 테스트를 수행할 경우, `ROS_DOMAIN_ID`가 서로 달라 노드가 통신하지 못하는 사례가 있으므로 동일하게 설정한다.

#### 메시지 타입/토픽 불일치

ROS2 노드 간 통신은 메시지 타입과 토픽 이름이 일치해야 한다. 테스트 코드에서 Publish/Subscribe 설정이 실제 노드와 다르면 메시지를 주고받지 못해 결과적으로 테스트가 실패한다.

* **빈번한 증상**
  * 테스트에서 메시지 콜백 함수가 호출되지 않음
  * 노드가 ‘unknown message type’ 에러를 출력함
  * Publish된 메시지는 정상적이나, Subscription이 받지 못함
* **해결 방안**
  1. **토픽 이름 재확인**: `ros2 topic list` 명령어로 실제 런칭된 노드에서 사용하는 토픽 이름을 확인하고, 테스트 코드에서 구독/발행하는 토픽 이름이 일치하는지 검증한다.
  2. **메시지 타입 점검**: `ros2 interface show <메시지타입>`을 통해 실제 메시지 필드와 일치하는지 확인하고, 테스트 코드에서 `std_msgs/msg/String` 과 같이 정확한 타입을 지정했는지 살핀다.
  3. **QoS 설정**: 메시지 타입이 같아도 QoS 설정이 불일치하면 메시지가 전달되지 않을 수 있다. 특히 reliable vs best effort, transient local vs volatile 설정 확인이 필요하다.

#### 동기/비동기 테스트 문제

테스트에서 자주 발생하는 문제 중 하나는 메시지를 비동기로 주고받는 로직을 확인할 때 “기다리지 않고 결과를 바로 확인”하여 발생하는 타이밍 오류이다. 예를 들어, 메시지를 발행한 직후 곧바로 구독 결과를 검증하려고 하면 콜백 함수가 아직 처리되지 않은 상태여서 테스트가 실패하는 경우가 있다.

* **빈번한 증상**
  * 간헐적으로 테스트가 성공하거나 실패함(플레이크 테스트)
  * 특정 메시지의 수신/처리가 누락되어 테스트 결과가 달라짐
  * 테스트 코드에서의 sleep 구문이 지나치게 길거나 짧아, 타임아웃 문제가 발생
* **해결 방안**
  1. **콜백 처리 대기**: Google Test 등을 사용할 때 `EXPECT_TRUE(조건);` 또는 `ASSERT_TRUE(조건);` 전에 callback이 충분히 호출되도록, 적절한 spin 및 sleep을 사용하거나 `std::future`를 통해 이벤트가 완료될 때까지 기다린다.
  2. **테스트 프레임워크 내 타임아웃 사용**: `$1$초 이내에 메시지가 수신되지 않으면 실패` 와 같은 조건을 명시하고, 비동기 처리가 가능하도록 타임아웃 설정을 적용한다.
  3. **콜백 내 검증 로직 분리**: 콜백 함수 내부에서 직접 테스트 결과를 검증하면 비동기 처리를 확실히 할 수 있다. 예를 들어 콜백에서 수신 상태를 `bool` 플래그로 관리하고, 마지막에 해당 플래그를 확인하여 테스트 결론을 낸다.

#### 의존성 있는 단위 테스트

단위 테스트(Unit Test)는 원칙적으로 테스트 대상 함수 혹은 클래스 외의 의존성이 없도록 만드는 것이 이상적이다. 그러나 ROS2 프로젝트에서는 노드 간 통신, 파라미터 서버 등 다양한 요소에 대한 의존성이 생길 수 있어, 순수 단위 테스트가 어려워진다. 이러한 환경에서 테스트를 작성할 때 의존성을 최소화하지 못하면 “유닛 테스트”가 아니라 사실상 “통합 테스트”가 되어버려, 오류 추적이 어려워진다.

* **빈번한 증상**
  * 단위 테스트에서 노드 런칭이 필요해 테스트가 오래 걸림
  * 테스트 실패 시 정확히 어느 부분에서 실패했는지 추적하기 어렵고, 다른 노드 또는 환경의 영향으로 인해 불필요한 문제 발생
  * 파라미터 또는 콜백 설정이 서로 달라, 테스트 노드와 실제 노드 동작이 달라지는 상황
* **해결 방안**
  1. **Mocking 기법 활용**: ROS2 C++ 단위 테스트 시, 노드나 파라미터 서버를 직접 띄우지 않고 Mock 객체를 사용해 통신 결과를 시뮬레이션한다.
  2. **로직 분리**: ROS2와 직접적으로 연결된 부분(통신, 파라미터)과 순수 로직을 철저히 분리하여, 순수 로직만 따로 단위 테스트한다. 통신 인터페이스는 별도의 Integration Test나 System Test에서 검증한다.
  3. **테스트 더블(Stub, Fake) 작성**: 실제 노드를 대체할 가짜 노드를 만들어 메시지를 수신/발행하고, 해당 노드만으로 테스트를 수행할 수 있도록 구조를 설계한다.

#### 메시지 시퀀스 오류

ROS2를 이용해 메시지를 연속적으로 주고받을 때, 특정 순서가 중요한 프로토콜이나 알고리즘을 테스트하는 경우 메시지가 의도된 순서대로 오지 않아 오류가 발생하기도 한다. 특히 분산 환경에서 메시지가 유실되거나 지연될 수 있으므로, 예측 불가능한 순서 문제로 인해 테스트가 실패하는 사례가 많다.

* **빈번한 증상**
  * 메시지 A를 처리하기 전에 메시지 B가 먼저 옴
  * 순서에 의존적 로직(예: 상태머신)에서 알 수 없는 상태로 전이되거나, 예외처리 로직이 작동하여 테스트 실패
  * 로컬 환경에서는 잘 되지만 네트워크 지연이 있는 실제 환경에서는 실패
* **해결 방안**
  1. **순서 제어 프로토콜 구성**: 메시지마다 시퀀스 번호나 타임스탬프를 부여하여, 수신 측에서 순서를 확인하고 재정렬하는 로직을 테스트 대상 코드에 포함한다.
  2. **상태머신 기반 접근**: $A \rightarrow B \rightarrow C$ 순서로 처리해야 할 때, 상태머신을 두어 현재 상태에서 올바른 메시지를 기다리는 구조로 만든다. 테스트 시에도 상태 전이를 검증하며 원하는 순서가 맞는지 확인한다.
  3. **테스트별 네트워크 조건 모사**: 네트워크 지연이나 패킷 유실 시나리오를 가정하여, 테스트 시 Docker 컨테이너 혹은 네트워크 에뮬레이터(예: netem)를 사용해 환경을 모사한다.

#### 동시성(Concurrency) 문제

ROS2는 멀티스레딩과 함께 콜백 그룹, 실행기(Executor) 등 다양한 메커니즘을 통해 노드가 동시에 여러 콜백을 처리할 수 있게 한다. 이때 테스트 환경에서도 동시성 문제가 발생할 수 있다. 예컨대, 특정 콜백이 다른 콜백의 결과를 사용해야 하는 로직이 있는데, 테스트 시점에 순서가 바뀌어 기대와 다른 동작을 하게 된다.

* **빈번한 증상**
  * 테스트 결과가 일정하지 않고 간헐적으로 실패(플레이크 현상)
  * 특정 함수(또는 콜백)에서 공유 자원(예: 전역 변수, static 변수)에 접근할 때, 경쟁 상태(Race Condition) 발생
  * 조건변수(Condition Variable)나 세마포어를 사용한 동기화 로직이 누락되어 교착상태(Deadlock)에 빠짐
* **해결 방안**
  1. **콜백 그룹과 실행기 설정 명시화**: ROS2에서 콜백 그룹(Callback Group)과 실행기(Executor)를 적절히 분리/할당하여, 서로 의존성이 있는 콜백이 다른 스레드에서 동시에 실행되지 않도록 한다.
  2. **뮤텍스(Mutex) 적용**: 공유 자원에 접근할 때는 $std::mutex$ 나 $std::recursive\_mutex$ 등을 사용해 동기화를 보장한다. 락 범위가 최소가 되도록 코드를 구조화해 교착 상태를 방지한다.
  3. **테스트에서 스레드 스케줄링 제어**: 필요하다면 단위 테스트나 통합 테스트 시점에서 스레드 스케줄러를 제한하거나(예: 단일 코어 사용), 테스트 프레임워크에서 제공하는 `join()`, `detach()` 등을 적절히 사용해 테스트가 예측 가능한 시점에 종료되도록 한다.

#### 메모리 누수(Memory Leak)

ROS2 자체는 C++ 기반으로 개발되는 경우가 많으며, 테스트 중 반복적으로 객체를 생성/소멸하면서 메모리가 누수될 수 있다. 메모리 누수는 단기간에는 잘 드러나지 않을 수 있지만, 장기간 실행되는 노드에서는 심각한 문제로 이어진다.

* **빈번한 증상**
  * 테스트 자체는 통과하지만, 장기간 실행 시 리소스가 부족해지는 문제 발생
  * valgrind, AddressSanitizer 등으로 검사 시 메모리 누수 경고가 발생
  * 반복 실행되는 테스트 중 후반부에 갑작스러운 크래시나 시스템 메모리 부족 현상
* **해결 방안**
  1. **소멸자(Destructor) 철저 구현**: RAII(Resource Acquisition Is Initialization) 원칙에 따라, 동적 할당된 리소스가 있다면 반드시 해당 리소스를 해제하는 로직을 구현한다.
  2. **스마트 포인터 사용**: $std::unique\_ptr$, $std::shared\_ptr$ 등 C++ 스마트 포인터를 적극적으로 활용해 메모리 관리 실수를 줄인다.
  3. **정적 분석 툴 및 런타임 검사**: valgrind나 clang sanitizer를 이용해 테스트 코드를 주기적으로 확인하고, 누수가 의심되는 부분은 즉각 수정한다.

#### 코드 커버리지(Code Coverage) 미달

ROS2 프로젝트는 여러 노드와 콜백이 얽혀 있어, 전체 코드 커버리지가 낮아지는 경우가 많다. 특히 노드 런칭 없이 단위 테스트만 수행하면, 메시지 전송이나 콜백 로직이 커버되지 않아 실제 코드 커버리지와 괴리가 생길 수 있다.

* **빈번한 증상**
  * $colcon$ 테스트 리포트에서 낮은 라인 커버리지(Line Coverage) 혹은 조건 커버리지(Branch Coverage) 지표
  * 실제 사용 중 문제되는 부분(예: 에러처리 구간)이 테스트 코드에서 전혀 커버되지 않음
  * 테스트가 일부 Happy Path만 검증해 예외상황 처리가 검증되지 않음
* **해결 방안**
  1. **통합 테스트 활용**: 노드 런칭 후 실제 메시지 송수신이 일어나는 시나리오까지 포함하여, 통합 테스트를 작성하고 커버리지를 측정한다.
  2. **예외 처리 구간 테스트**: 오류 상황(잘못된 파라미터, 타임아웃, 잘못된 메시지 타입 등)을 강제로 발생시키는 테스트를 작성해, 예외 처리 로직을 커버한다.
  3. **코드 분리 및 테스트 전략**: ROS2와 연관된 코드는 통합 테스트로, 순수 로직 코드는 단위 테스트로 나누어 최대한 높은 커버리지를 달성하도록 한다.

#### 지속적 통합(CI)에서의 환경 차이

개발자의 로컬 환경에서 테스트가 통과하지만, CI 서버(예: GitHub Actions, Jenkins, GitLab CI)에서 실행 시 ROS2 워크스페이스 설정, 의존성 등이 달라 테스트가 실패하는 경우가 잦다. 이러한 현상은 주로 ROS2 버전, 시스템 패키지 버전, 네트워크 설정 등에 기인한다.

* **빈번한 증상**
  * 로컬에선 정상 동작하나 CI에서만 특정 테스트가 실패
  * CI 로그에서 “Could not find package” 또는 “Failed to load shared library” 등의 에러 발생
  * ROS\_DOMAIN\_ID, RMW\_IMPLEMENTATION 설정 불일치로 인한 통신 실패
* **해결 방안**
  1. **CI 환경 명시화**: Docker 이미지를 사용해 로컬과 동일한 ROS2 Humble 환경을 구성하고, CI에서도 해당 이미지를 구동하도록 해 환경 편차를 줄인다.
  2. **의존성 자동 설치**: `$rosdep$`과 같은 도구를 통해 필요한 ROS 패키지 의존성을 자동으로 설치하고, CI 스크립트 내에 명시적으로 추가한다.
  3. **네트워크 설정 확인**: CI 서버에서 멀티캐스트 혹은 특정 포트가 막혀 있어 통신이 실패할 수 있다. 방화벽 정책이나 네트워크 설정을 사전에 체크한다.

#### 테스트 실행 순서 간 간섭

여러 개의 테스트를 병렬 혹은 순차적으로 실행할 때, 이전 테스트에서 사용하던 자원(토픽, 노드, 파라미터 등)이 해제되지 않아 다음 테스트에 영향을 끼치는 경우가 있다. 특히 동일한 토픽이나 노드 이름을 재사용하면 트래픽이 섞여서 잘못된 결과가 나올 수 있다.

* **빈번한 증상**
  * 이전 테스트에서 Publish된 메시지가 다음 테스트의 Subscribe 콜백을 트리거
  * 노드 이름 충돌로 인해 런칭 과정에서 에러 발생
  * 특정 파라미터가 이전 테스트의 값으로 유지되어 예상과 다른 결과 발생
* **해결 방안**
  1. **테스트 격리(Isolation)**: Google Test 등에서 `TearDown()` 메서드를 통해, 테스트가 끝날 때마다 노드나 실행기를 완전히 종료시키고 파라미터를 초기화한다.
  2. **토픽/노드 이름 구분**: 테스트별로 고유한 토픽/노드 이름을 사용하거나 UUID를 붙여, 이전 테스트 잔여 트래픽이 섞이지 않게 한다.
  3. **Launch Testing 시 리소스 청소**: $pytest$ 기반 Launch Testing을 사용할 경우, 테스트가 끝난 뒤에도 노드가 종료되는지 반드시 확인한다. 필요 시 `ros2 node list`를 확인하거나 추가 스크립트로 강제 종료한다.

#### 시뮬레이터를 활용한 테스트 이슈

ROS2 프로젝트에서는 실제 하드웨어 대신 시뮬레이터(예: Gazebo, Ignition, Webots)를 활용해 테스트하는 경우가 많다. 하지만 시뮬레이션 환경은 실제 하드웨어와 물리 모델의 정확성이 다르거나, 시뮬레이터 자체의 버그나 성능 이슈로 인해 테스트 결과가 왜곡될 수 있다.

* **빈번한 증상**
  * 시뮬레이터 물리 엔진이 실제 하드웨어와 다르게 동작해 실제 구동 시나리오와 불일치
  * 시뮬레이션 속도가 느리거나 불안정해 반복 테스트 시 결과 편차 발생
  * 시뮬레이터 버전 차이로 인해 특정 ROS2 플러그인이 호환되지 않음
* **해결 방안**
  1. **시뮬레이터 물리 파라미터 교정**: 무게, 관성 모멘트, 마찰 계수 등 하드웨어 특성을 실제에 가깝게 세팅하고, 공식 문서를 참고해 물리 엔진 파라미터를 조정한다.
  2. **버전 고정**: 시뮬레이터 플러그인 버전을 명시적으로 고정하여, CI나 다른 개발 환경에서 동일한 버전을 사용하도록 한다.
  3. **하드웨어-시뮬레이션 비교 테스트**: 시뮬레이션 결과가 실제 로봇 실험 결과와 일정 이상 오차 범위 내에 있음을 사전에 검증하고, 중요한 알고리즘은 실제 하드웨어 테스트를 병행한다.

#### 저성능 및 실시간성 문제

ROS2는 멀티스레딩과 DDS(Dataplicity Distribution Service) 기반 통신을 지원하지만, 특정 상황에서 높은 실시간성을 요구하는 경우(예: 로봇 팔 제어, 자율주행) 테스트 시에도 성능 이슈가 발생한다. 단순히 기능적 문제뿐 아니라, 간헐적인 지연으로 인해 타이밍이 어긋나 테스트가 실패하는 경우가 있다.

* **빈번한 증상**
  * 제어 주기(예: 1ms, 10ms) 내에 콜백이 완료되지 않아 Fail 처리
  * 메시지 전송 지연으로 장애물 회피, 경로 계획 등에서 오차가 누적
  * CPU나 메모리 사용량이 높아져 전체 시스템이 느려짐
* **해결 방안**
  1. **실시간 커널 사용**: 리눅스 기반 시스템이라면 RT-Preempt 패치가 적용된 실시간 커널을 사용해 스레드 스케줄링 우선순위를 조정한다.
  2. **DDS QoS 튜닝**: Reliable 대신 Best Effort로 통신 모드를 바꾸거나, History 정책 등을 조정해 메시지 지연을 줄인다.
  3. **로직 최적화**: 무거운 연산(예: 컴퓨터 비전, 머신러닝)은 별도 프로세스나 GPGPU에서 처리하고, 콜백 내 연산은 최소화한다.

#### 빌드/테스트 시간 초과

ROS2 패키지 수가 많아질수록, `colcon build`와 `colcon test`를 실행할 때 소요되는 시간이 기하급수적으로 늘어난다. 특히 통합 테스트나 시뮬레이션 테스트를 포함하면 CI 파이프라인에서 시간 초과가 발생해 테스트가 제대로 완료되지 않는다.

* **빈번한 증상**
  * CI에서 일정 시간(예: 30분, 1시간) 내 빌드 및 테스트가 완료되지 않아 Job이 중단
  * 로컬 환경에서도 테스트 돌리는 데 너무 오래 걸려 개발 효율이 떨어짐
  * 테스트 병렬화 시 종종 리소스 경합으로 인해 오히려 더 느려지거나 실패
* **해결 방안**
  1. **캐시 활용**: CI에서 ccache, sccache 등을 사용해 빌드 시간을 단축한다.
  2. **테스트 샤딩(Sharding)**: 테스트를 여러 그룹으로 나누어 병렬적으로 실행하거나, 고비용 시뮬레이션 테스트는 주기적으로만 수행하도록 스케줄을 분산한다.
  3. **불필요한 테스트 최소화**: 코드 변경 범위와 관련 없는 대규모 통합 테스트를 매번 돌리지 말고, 중요도에 따라 수행 빈도를 조절한다.

#### 보안(Security) 및 인증 문제

ROS2는 DDS 보안 계층(Security) 구성을 지원하지만, 이를 제대로 설정하지 않으면 테스트 환경에서 인증이 실패하거나, 암호화된 통신이 제대로 이뤄지지 않는다. 특히 네트워크로 분산된 환경에서 테스트 시 보안 구성이 안 맞아 노드 연결이 안 될 수 있다.

* **빈번한 증상**
  * 테스트 시 “Failed to initialize security” 또는 “Unauthorized participant” 같은 에러가 발생
  * 보안이 활성화된 노드와 비활성 노드가 통신에 실패
  * 테스트 환경마다 Security Artifact(권한 증명서, 정책 파일)가 달라 누락 발생
* **해결 방안**
  1. **보안 설정 파일 관리**: DDS 보안 폴더(예: keystore) 및 정책 파일(XML) 경로를 확실하게 관리하고, CI에서도 해당 경로를 미리 세팅한다.
  2. **통일된 Certificate 발급**: 모든 테스트 노드에 대해 동일한 CA(Certificate Authority)나 키 파일을 발급해, 노드 간 상호 인증이 가능하도록 한다.
  3. **보안 미활성 테스트 준비**: 빠른 단위 테스트를 위해 보안 비활성 모드를 별도로 준비해두고, 실제 환경 테스트 시에는 반드시 보안을 활성화한 상태로 진행한다.

#### 복합 이벤트 테스트(E2E)에서의 동기화 오류

ROS2 프로젝트에서는 단순히 한두 개 노드 간 통신만 확인하는 것이 아니라, 여러 노드와 여러 이벤트가 동시에 얽히는 End-to-End 시나리오 테스트가 자주 발생한다. 이때 특정 이벤트를 트리거하는 순서나 시점이 어긋나면, 각 노드의 상태가 맞지 않아 테스트가 실패하거나, 간헐적으로 결과가 달라지는 경우가 많다.

* **빈번한 증상**
  * 시나리오상 A 노드가 B 노드에게 특정 메시지를 보내고, 그 응답으로 C 노드가 동작해야 하나 시점이 엇갈려 C 노드가 요청을 못 받음
  * 테스트가 간헐적으로 성공했다가 실패하는 플레이크 현상
  * 실제 서비스 시나리오와는 다른 경로로 이벤트가 발생해, 테스트에선 확인되지 않은 버그가 필드에서 드러남
* **해결 방안**
  1. **테스트 시퀀스 명시화**: Launch 테스트 스크립트 또는 테스트 프레임워크에서 “어떤 순서로 노드를 띄우고 어떤 시점에 이벤트를 발생시킬지”를 명확히 기재한다.
  2. **이벤트 대기 로직**: 이벤트가 발생했는지 확인할 수 있는 토픽/서비스 콜백을 두고, 각 이벤트가 처리되었는지 플래그나 Condition Variable 등을 통해 확인한 후 다음 단계로 진행한다.
  3. **상태 머신 기반 시나리오 구성**: 여러 이벤트가 서로 영향을 주고받을 때 상태 머신을 설계해, 현재 상태에서 어떤 이벤트가 유효한지 검사하고 다음 상태로 전이하는 로직을 두면 시나리오 전체 흐름을 테스트하기 용이하다.

#### 결함 주입(Fault Injection) 테스트 문제

ROS2 노드 통신이나 알고리즘 동작에서 잠재적 오류를 찾기 위해서는 결함 주입(Fault Injection) 기법을 사용하기도 한다. 의도적으로 메시지를 유실시키거나, 잘못된 데이터(오류 코드, 범위를 벗어난 값)를 넣어봐야 실제 환경에서의 에러 처리 로직을 검증할 수 있다. 하지만 이 결함 주입 테스트가 제대로 설계되지 않으면, 실제 버그와는 동떨어진 실패 시나리오가 발생하거나 아예 테스트가 무의미해진다.

* **빈번한 증상**
  * 결함 주입 자체가 너무 단순(예: 메시지 한 번 유실)해서, 실제에서 발생할 수 있는 재전송 로직까지 검증 못 함
  * 너무 과도한 결함 주입으로 인해 정상 로직 수행이 불가능해, 테스트 결과가 유의미하지 않음
  * 결함 주입 시점을 제어하지 못해, 콜백이나 노드 초기화 시점과 엇갈려 실제 실패 원인을 파악하기 어려움
* **해결 방안**
  1. **현실적인 에러 시나리오 설계**: 하드웨어 고장, 네트워크 패킷 유실, 잘못된 파라미터 값 등 실제로 발생 가능한 문제 상황을 구체화하고, 해당 상황을 시뮬레이션할 수 있도록 코드를 구현한다.
  2. **재현 가능한 주입 로직**: 메시지 전송 과정에 훅(Hook)을 걸어, “n번째 메시지마다 유실” 또는 “일정 주기로 에러 코드 삽입” 등 재현 가능한 규칙을 명시한다.
  3. **결과 분석 로깅**: 결함 발생 시점, 노드 상태, 로직 흐름 등을 구체적으로 로그에 남겨, 결함 주입이 실제로 어느 시점에 일어났으며 어떻게 처리되었는지 추적 가능하도록 한다.

#### 상태 기반(Property-based) 테스트의 어려움

일반적인 단위 테스트나 통합 테스트는 입력을 특정 값으로 고정해놓고 실행하지만, 상태 기반 테스트(Property-based Testing)는 무작위 또는 범위를 달리하면서 많은 입력 케이스를 자동으로 생성해 로직 전체를 검증한다. ROS2 환경에서 이러한 테스트를 작성할 때, 비동기 통신과 상태 변화가 복합적으로 일어나 동작이 예측 불가해지는 경우가 생긴다.

* **빈번한 증상**
  * 무작위 입력으로 노드를 구동하다가 예상치 못한 순서의 콜백 호출이 발생해 디버깅이 어려움
  * 엄청난 양의 테스트 케이스가 생성되지만, 실제로 어떤 케이스에서 실패했는지 재현이 복잡함
  * 특정 상태 전이만 반복적으로 검사하다가, 다른 중요한 상태 전이는 놓침
* **해결 방안**
  1. **테스트 범위 제한**: 무작위 테스트라도 “파라미터 A는 0~~100 사이에서 균등 분포로, 파라미터 B는 0~~1 범위 내 소수점 2자리까지” 식으로 제약을 둬, 무분별한 입력 폭주를 줄인다.
  2. **결과 재현성 확보**: 무작위 시드를 고정(seed)를 둬서, 동일한 시드로 테스트를 재실행할 수 있게 한다. 실패 케이스가 발생하면 시드를 기록해 디버깅에 활용한다.
  3. **상태 전이 로깅**: 상태 기반 테스트에서 노드가 어떤 상태에서 어떤 메시지를 받고 어떻게 전이했는지 단계별로 로깅하여, 실패 시점을 파악할 수 있도록 만든다.
