BehaviorTree/BehaviorTree.ROS2

Unit Testing

Closed this issue · 0 comments

Below I have attached my cpp file for which I wish to write a unit test, specifically for the onTick method. This node is supposed to run at the top of the tree inside a reactive fallback to control the current state of the tree eg, localized, e stop, hw failure, sw failure etc. Since it is an essential node in the tree, I wanted to write a unit test for it. The code is from the sample subscriber wrapper provided in the package

`

#include "my_behavior_tree/ok_status.hpp"

using namespace BT;

OKStatus::OKStatus(const std::string& name,
                            const NodeConfig& conf,
                            const RosNodeParams& params)
: RosTopicSubNode<std_msgs::msg::String>(name, conf, params)
{

}

BT::PortsList OKStatus::providedPorts()
{
    return{InputPort<std::string>("topic_name")};
}

// Check if status is okay or not, if not return failure. Used to control state of the tree
NodeStatus OKStatus::onTick(const std::shared_ptr<std_msgs::msg::String>& last_msg)
  {    // TODO - Add multiple state checks

    if (last_msg)
    {
      status = last_msg->data;

      if(status =="OK") 
    {
      // RCLCPP_INFO(logger(), "Not in error"); 
      c = 0;
      return NodeStatus::SUCCESS; 
    }
    else
    {
      c =1;
      // RCLCPP_INFO(logger(), "In error");
      return NodeStatus::FAILURE; 
    }

    }

    else
    {
      
      if(c ==0) 
    {
      return NodeStatus::SUCCESS; 
    }
    else
    {
        return NodeStatus::FAILURE; 
    }
       

    } 
    
    
  }

`

This is the corresponding header file

`

#include "behaviortree_ros2/bt_topic_sub_node.hpp"
#include <std_msgs/msg/string.hpp>

using namespace BT;

class OKStatus: public RosTopicSubNode<std_msgs::msg::String>
{
public:
  OKStatus(const std::string& name,
                const NodeConfig& conf,
                const RosNodeParams& params);

  static BT::PortsList providedPorts();

  NodeStatus onTick(const std::shared_ptr<std_msgs::msg::String>& last_msg) override;

  std::string status;
  int c;
};

`

This is the Test method I have written

`

#include <gtest/gtest.h>
#include <ament_index_cpp/get_package_share_directory.hpp>
#include <ament_index_cpp/get_package_prefix.hpp>
#include <rclcpp/rclcpp.hpp>
#include <vector>
#include <string>
#include <fstream>
#include <memory>
#include <utility>
#include <boost/filesystem.hpp>
#include <my_behavior_tree/ok_status.hpp>

using namespace BT;


std_msgs::msg::String createString(const std::string& name)
{
    std_msgs::msg::String sample;
    sample.data = name;
    return sample;
}

class BehaviorTreeTestFixture : public ::testing::Test
{

protected:
    std::shared_ptr<BehaviorTreeHandler> bt_handler;
    std_msgs::msg::String a;

public:
    void SetUp() override
    {
        bt_handler = std::make_shared<BehaviorTreeHandler>();
        a = createString("OK");
        
    }

    void TearDown() override
    {
        bt_handler.reset();
    }

};

TEST_F(BehaviorTreeTestFixture, TestSuccess)
{

rclcpp::init(0, nullptr);


auto nh = std::make_shared<rclcpp::Node>("tree_test_node");

RosNodeParams params;
params.nh = nh;
params.default_port_value = "test";

factory.registerNodeType<OKStatus>("OKStatus", params);

OKStatus ok_status("ok_status",NodeConfig(),RosNodeParams());

auto message_ptr = std::make_shared<std_msgs::msg::String>(a);

auto status = ok_status.onTick(message_ptr);
EXPECT_EQ(status, BT::NodeStatus::SUCCESS);

rclcpp::shutdown();

}
`

I am getting the following error when I am running this code

unknown file: Failure C++ exception with description "Both [topic_name] in the InputPort and the RosNodeParams are empty." thrown in the test body.

My idea is to write a unit test specifically for the onTick method only without involving any of the ROS components, but since the OKStatus class is inheriting from the RosTopicSubNode class, I believe that will not be possible without completely re writing the class and separating out the ROS dependency and onTick method.

So I wanted to check if someone has faced a similar problem or has some better suggestions to write a unit test for this method?

I have also tried to load the xml file and also add a tickOnce/tickWhileRunning method but even then I get the same error, however with those cases, the subscriber is actually created but the code eventually crashes at line 181 https://github.com/BehaviorTree/BehaviorTree.ROS2/blob/humble/behaviortree_ros2/include/behaviortree_ros2/bt_topic_sub_node.hpp

Thank you