[ROS2] Testing launch of Node
I've been trying to write some tests for my package, but with not much success until now...
I have a "PelicanUnit" node and in its constructor I require a path to a .sdf model: if that's not given, everything shuts down with a std::runtime_error. Now, using colcon test and Google Test, I've been trying to write sort of like smoketests for successful and unsuccessful launches. The failing case has been a little tricky, but in the end I've managed with this:
TEST(SmokeTests, ParseModelFailing) {
// Initialize RCLCPP
rclcpp::init(0, nullptr);
EXPECT_THROW(
{
try {
PelicanUnit pelican;
} catch (const std::exception& e) {
EXPECT_STREQ("Agent model could not be parsed!", e.what());
throw; // Re-throw the exception for Google Test to catch
}
},
std::runtime_error);
// Shutdown RCLCPP
rclcpp::shutdown();
}
Unfortunately, I cannot find a way for the other test.
Up until now I've tried:
launching the node from the test itself but I could not pass the config file I normally use with the standard launch file
TEST(SmokeTests, Main) { // Useless, since the node itself does not parse arguments (?) char arg0[] = "--params-file"; char arg1[] = "src/pelican/config/copter1.yaml"; // TODO: use package share directory char* argv[] = { &arg0[0], &arg1[0], NULL }; int argc = (int)(sizeof(argv) / sizeof(argv[0])) - 1; // Initialization rclcpp::init(argc, argv); // Instantiation rclcpp::Node::SharedPtr node = std::make_shared<PelicanUnit>(); rclcpp::executors::MultiThreadedExecutor executor; executor.add_node(node); executor.spin(); rclcpp::shutdown(); }
using a test launch_file, which has been somewhat almost good, but the config file used has not been found and, most importantly, I'm not sure I can use this as a proper test. I can only test that the command is launched, not that the node itself fires up smoothly...
TEST(SmokeTests, NodeStartingCorrectly) { // Set the launch file path and arguments const std::string pwd = "source "; const std::string launch_command = "ros2 launch pelican test_launch.launch.py"; // Run the launch command and check its exit status std::system(pwd.c_str()); int exit_status = std::system(launch_command.c_str()); ASSERT_EQ(exit_status, 0); }
(launch file)
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch_ros.actions import Node
from launch_ros.substitutions import FindPackageShare
from launch.substitutions import PathJoinSubstitution, ThisLaunchFileDir
def generate_launch_description():
config_pkg_share = FindPackageShare('pelican')
config_middleware = 'config/'
ld = LaunchDescription()
config_file = 'copter1.yaml'
node = Node(
package='pelican',
executable='pelican_unit',
ros_arguments=['--params-file',
PathJoinSubstitution([config_pkg_share, config_middleware, config_file])]
)
ld.add_action(node)
return ld
Is there anyone that can provide some assistance or suggestions for this? Thank you!