Success 반환 조건 테스트 (Success Return Condition Testing)
1. 개요
Success 반환 조건 테스트는 조건 노드가 조건 충족 시 SUCCESS 상태를 올바르게 반환하는지를 검증하는 단위 테스트이다. 이 테스트는 조건 노드의 정상 경로(happy path)를 검증하며, 유효한 입력 데이터가 주어졌을 때 조건이 올바르게 참으로 평가되는지를 확인한다.
2. 테스트 전략
2.1 테스트 케이스 설계
SUCCESS 반환 테스트에서 검증하여야 할 주요 케이스는 다음과 같다.
| 케이스 | 설명 | 예시 |
|---|---|---|
| 명확한 참 조건 | 임계값보다 크게 상회하는 값 | 배터리 80%, 임계값 20% |
| 경계 근처 참 조건 | 임계값을 미세하게 초과하는 값 | 배터리 20.1%, 임계값 20% |
| 정확한 경계값 | 임계값과 정확히 동일한 값 (이상 비교 시) | 배터리 20.0%, 임계값 20% |
| 다중 조건 충족 | 복수의 평가 기준이 모두 충족 | 속도 < 2.0 m/s AND 각속도 < 1.0 rad/s |
2.2 테스트 데이터 준비
각 테스트 케이스에 대해 ROS2 토픽 메시지를 모의 발행(mock publish)하여 조건 노드에 입력을 제공한다.
3. 구현 예시
3.1 배터리 잔량 조건의 SUCCESS 테스트
TEST_F(BatteryConditionTest, ReturnsSuccessAboveThreshold)
{
// 배터리 잔량이 임계값보다 충분히 높은 경우
sensor_msgs::msg::BatteryState msg;
msg.present = true;
msg.percentage = 0.85; // 85%
publishAndSpin(msg);
auto status = tree_.tickOnce();
EXPECT_EQ(status, BT::NodeStatus::SUCCESS);
}
TEST_F(BatteryConditionTest, ReturnsSuccessAtExactThreshold)
{
// 잔량이 정확히 임계값인 경우 (>= 비교)
sensor_msgs::msg::BatteryState msg;
msg.present = true;
msg.percentage = 0.20; // 임계값과 동일
publishAndSpin(msg);
auto status = tree_.tickOnce();
EXPECT_EQ(status, BT::NodeStatus::SUCCESS);
}
TEST_F(BatteryConditionTest, ReturnsSuccessJustAboveThreshold)
{
// 임계값을 미세하게 초과하는 경우
sensor_msgs::msg::BatteryState msg;
msg.present = true;
msg.percentage = 0.201;
publishAndSpin(msg);
auto status = tree_.tickOnce();
EXPECT_EQ(status, BT::NodeStatus::SUCCESS);
}
3.2 거리 센서 조건의 SUCCESS 테스트
TEST_F(RangeConditionTest, ReturnsSuccessWhenAllRangesAboveMin)
{
sensor_msgs::msg::LaserScan msg;
msg.range_min = 0.1;
msg.range_max = 30.0;
msg.angle_min = -M_PI;
msg.angle_max = M_PI;
msg.angle_increment = M_PI / 180.0;
// 모든 측정값이 최소 거리 이상
msg.ranges.resize(360, 5.0);
publishAndSpin(msg);
auto status = tree_.tickOnce();
EXPECT_EQ(status, BT::NodeStatus::SUCCESS);
}
3.3 블랙보드 기반 조건의 SUCCESS 테스트
TEST_F(BlackboardConditionTest, ReturnsSuccessWhenValueMatches)
{
auto blackboard = tree_.rootBlackboard();
blackboard->set("sensor_value", 42.0);
auto status = tree_.tickOnce();
EXPECT_EQ(status, BT::NodeStatus::SUCCESS);
}
4. 반복 tick에서의 SUCCESS 안정성
조건 노드가 동일한 입력에 대해 반복적으로 SUCCESS를 반환하는지를 검증한다. 내부 상태의 부적절한 변경이 있으면 반복 tick에서 결과가 달라질 수 있다.
TEST_F(ConditionStabilityTest, ConsistentSuccessOnRepeatedTicks)
{
publishValidMessage();
for (int i = 0; i < 50; ++i)
{
auto status = tree_.tickOnce();
EXPECT_EQ(status, BT::NodeStatus::SUCCESS)
<< "Tick " << i << " returned unexpected status";
}
}
5. 매개변수화된 테스트
Google Test의 매개변수화된 테스트(parameterized test)를 활용하여, 다양한 SUCCESS 조건을 체계적으로 검증한다.
struct SuccessCase
{
double value;
double threshold;
};
class ParameterizedSuccessTest
: public ConditionNodeTest,
public ::testing::WithParamInterface<SuccessCase>
{};
TEST_P(ParameterizedSuccessTest, ReturnsSuccess)
{
auto params = GetParam();
setThreshold(params.threshold);
publishValue(params.value);
auto status = tree_.tickOnce();
EXPECT_EQ(status, BT::NodeStatus::SUCCESS);
}
INSTANTIATE_TEST_SUITE_P(
SuccessCases,
ParameterizedSuccessTest,
::testing::Values(
SuccessCase{10.0, 5.0},
SuccessCase{5.001, 5.0},
SuccessCase{5.0, 5.0}, // 경계값 (>= 비교)
SuccessCase{100.0, 0.0},
SuccessCase{0.001, 0.0}
));
6. 설계 시 고려 사항
6.1 비교 연산의 정확한 의미
임계값과의 비교가 초과(>)인지 이상(>=)인지에 따라 경계값에서의 결과가 달라진다. 테스트에서 이 차이를 명확히 검증하여야 하며, 조건 노드의 문서화된 의미론과 실제 구현이 일치하는지를 확인한다.
6.2 부동소수점 정밀도
부동소수점 비교에서 정밀도 한계에 의한 예기치 않은 결과가 발생할 수 있다. 경계값 테스트에서는 머신 엡실론 수준의 차이를 포함한 테스트 케이스를 추가하여야 한다.
6.3 시간 의존적 SUCCESS
타임스탬프 기반 조건 노드의 경우, 테스트 실행 시점에 따라 결과가 달라질 수 있다. 테스트에서 시간을 제어 가능하도록, 시뮬레이션 시간을 사용하거나 시간 관련 매개변수를 적절히 설정하여야 한다.
7. 참고 문헌
- 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 | 초안 작성 |