Failure 반환 조건 테스트 (Failure Return Condition Testing)
1. 개요
Failure 반환 조건 테스트는 조건 노드가 조건 미충족 시 FAILURE 상태를 올바르게 반환하는지를 검증하는 단위 테스트이다. 이 테스트는 조건이 거짓으로 평가되어야 하는 상황뿐만 아니라, 데이터 부재, 유효하지 않은 입력, 타임아웃 등의 이상 상황에서도 안전하게 FAILURE를 반환하는지를 확인한다. 특히 안전 관련 조건 노드에서는 실패 안전(fail-safe) 원칙의 준수를 검증하는 데 핵심적이다.
2. 테스트 케이스 분류
2.1 정상 FAILURE 케이스
조건이 논리적으로 거짓인 경우의 FAILURE 반환을 검증한다.
| 케이스 | 입력 | 기대 결과 |
|---|---|---|
| 임계값 미만 | 값 < 임계값 | FAILURE |
| 범위 외 | 값이 지정 범위 외 | FAILURE |
| 불일치 | 값 \neq 기대값 | FAILURE |
2.2 이상 상황 FAILURE 케이스
데이터가 비정상적인 경우에도 안전하게 FAILURE를 반환하는지를 검증한다.
| 케이스 | 입력 | 기대 결과 |
|---|---|---|
| 메시지 미수신 | 토픽 메시지 없음 | FAILURE |
| NaN 값 | 센서 값 = NaN | FAILURE |
| Inf 값 | 센서 값 = Inf | FAILURE |
| 빈 배열 | ranges[] 비어 있음 | FAILURE |
| 배터리 미장착 | present = false | FAILURE |
| GPS 미수신 | status = STATUS_NO_FIX | FAILURE |
| 타임아웃 | 지정 시간 초과 | FAILURE |
3. 구현 예시
3.1 조건 미충족 FAILURE 테스트
TEST_F(BatteryConditionTest, ReturnsFailureBelowThreshold)
{
sensor_msgs::msg::BatteryState msg;
msg.present = true;
msg.percentage = 0.10; // 10%, 임계값 20% 미만
publishAndSpin(msg);
auto status = tree_.tickOnce();
EXPECT_EQ(status, BT::NodeStatus::FAILURE);
}
TEST_F(BatteryConditionTest, ReturnsFailureJustBelowThreshold)
{
sensor_msgs::msg::BatteryState msg;
msg.present = true;
msg.percentage = 0.199; // 19.9%, 임계값 20% 미만
publishAndSpin(msg);
auto status = tree_.tickOnce();
EXPECT_EQ(status, BT::NodeStatus::FAILURE);
}
3.2 데이터 부재 FAILURE 테스트
TEST_F(TopicConditionTest, ReturnsFailureWhenNoMessageReceived)
{
// 메시지를 발행하지 않고 tick
auto status = tree_.tickOnce();
EXPECT_EQ(status, BT::NodeStatus::FAILURE);
}
TEST_F(TopicConditionTest, ReturnsFailureWhenMessageIsNull)
{
// RosTopicSubNode의 onTick에 nullptr이 전달되는 경우
auto status = tree_.tickOnce();
EXPECT_EQ(status, BT::NodeStatus::FAILURE);
}
3.3 무효 데이터 FAILURE 테스트
TEST_F(RangeConditionTest, ReturnsFailureForNanRange)
{
sensor_msgs::msg::LaserScan msg;
msg.range_min = 0.1;
msg.range_max = 30.0;
msg.ranges = {std::numeric_limits<float>::quiet_NaN()};
publishAndSpin(msg);
auto status = tree_.tickOnce();
EXPECT_EQ(status, BT::NodeStatus::FAILURE);
}
TEST_F(RangeConditionTest, ReturnsFailureForInfRange)
{
sensor_msgs::msg::LaserScan msg;
msg.range_min = 0.1;
msg.range_max = 30.0;
msg.ranges = {std::numeric_limits<float>::infinity()};
publishAndSpin(msg);
auto status = tree_.tickOnce();
// Inf가 장애물 없음으로 해석되는지, 오류로 해석되는지는 구현에 따라 다름
// 구현 의도에 맞는 결과를 검증
}
TEST_F(RangeConditionTest, ReturnsFailureForEmptyRanges)
{
sensor_msgs::msg::LaserScan msg;
msg.ranges.clear();
publishAndSpin(msg);
auto status = tree_.tickOnce();
EXPECT_EQ(status, BT::NodeStatus::FAILURE);
}
3.4 센서 비활성 상태 테스트
TEST_F(BatteryConditionTest, ReturnsFailureWhenNotPresent)
{
sensor_msgs::msg::BatteryState msg;
msg.present = false; // 배터리 미장착
msg.percentage = 1.0; // 값은 있으나 무의미
publishAndSpin(msg);
auto status = tree_.tickOnce();
EXPECT_EQ(status, BT::NodeStatus::FAILURE);
}
TEST_F(GpsConditionTest, ReturnsFailureForNoFix)
{
sensor_msgs::msg::NavSatFix msg;
msg.status.status =
sensor_msgs::msg::NavSatStatus::STATUS_NO_FIX;
publishAndSpin(msg);
auto status = tree_.tickOnce();
EXPECT_EQ(status, BT::NodeStatus::FAILURE);
}
3.5 타임아웃 FAILURE 테스트
TEST_F(FreshnessConditionTest, ReturnsFailureForStaleMessage)
{
// 오래된 타임스탬프를 가진 메시지 발행
sensor_msgs::msg::LaserScan msg;
msg.header.stamp = node_->get_clock()->now() -
rclcpp::Duration(10, 0); // 10초 전
msg.ranges = {5.0};
publishAndSpin(msg);
auto status = tree_.tickOnce();
EXPECT_EQ(status, BT::NodeStatus::FAILURE);
}
4. RUNNING 미반환 검증
TEST_F(ConditionNodeTest, NeverReturnsRunningOnFailure)
{
// 의도적으로 FAILURE를 유발하는 입력
publishInvalidMessage();
for (int i = 0; i < 100; ++i)
{
auto status = tree_.tickOnce();
EXPECT_TRUE(status == BT::NodeStatus::SUCCESS ||
status == BT::NodeStatus::FAILURE)
<< "Tick " << i << " returned RUNNING";
}
}
5. 설계 시 고려 사항
5.1 FAILURE의 의미론적 일관성
동일한 유형의 이상 상황에 대해 모든 조건 노드가 일관된 FAILURE 반환 정책을 따라야 한다. 예를 들어, “메시지 미수신 = FAILURE” 정책은 모든 토픽 기반 조건 노드에 동일하게 적용되어야 한다.
5.2 실패 원인의 구분
테스트에서 FAILURE가 반환되었을 때, 그것이 조건의 논리적 거짓에 의한 것인지 이상 상황에 의한 것인지를 구분할 수 있어야 한다. 조건 노드의 로깅 기능을 통해 실패 원인을 추적할 수 있도록 한다.
5.3 회귀 테스트
버그 수정이나 리팩토링 후, FAILURE 반환 테스트를 회귀 테스트(regression test)로 실행하여 기존 동작이 변경되지 않았는지를 확인한다.
6. 참고 문헌
- Colledanchise, M., & Ogren, P. (2018). Behavior Trees in Robotics and AI: An Introduction. CRC Press.
- Google Test 문서. https://google.github.io/googletest/
- BehaviorTree.CPP 공식 문서. https://www.behaviortree.dev/
| 버전 | 날짜 | 변경 사항 |
|---|---|---|
| v0.1 | 2026-04-04 | 초안 작성 |