diff --git a/tracetools_test/.gitignore b/tracetools_test/.gitignore
new file mode 100644
index 0000000..2f836aa
--- /dev/null
+++ b/tracetools_test/.gitignore
@@ -0,0 +1,2 @@
+*~
+*.pyc
diff --git a/tracetools_test/CMakeLists.txt b/tracetools_test/CMakeLists.txt
new file mode 100644
index 0000000..c1479bb
--- /dev/null
+++ b/tracetools_test/CMakeLists.txt
@@ -0,0 +1,49 @@
+cmake_minimum_required(VERSION 3.5)
+project(tracetools_test)
+
+# Default to C++14
+if(NOT CMAKE_CXX_STANDARD)
+ set(CMAKE_CXX_STANDARD 14)
+endif()
+
+if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ add_compile_options(-Wall -Wextra -Wpedantic -fPIC)
+endif()
+
+find_package(ament_cmake REQUIRED)
+find_package(rclcpp REQUIRED)
+find_package(std_msgs REQUIRED)
+
+# Tests
+if(BUILD_TESTING)
+ add_executable(test_publisher
+ test/test_publisher.cpp
+ )
+ ament_target_dependencies(test_publisher
+ rclcpp
+ std_msgs
+ )
+ install(TARGETS
+ test_publisher
+ DESTINATION lib/${PROJECT_NAME}
+ )
+
+ find_package(ament_cmake_pytest REQUIRED)
+
+ # Run each test in its own pytest invocation
+ set(_tracetools_test_pytest_tests
+ test/test_publisher.py
+ )
+
+ foreach(_test_path ${_tracetools_test_pytest_tests})
+ get_filename_component(_test_name ${_test_path} NAME_WE)
+ ament_add_pytest_test(${_test_name} ${_test_path}
+ PYTHON_EXECUTABLE "${PYTHON_EXECUTABLE}"
+ APPEND_ENV AMENT_PREFIX_PATH=${ament_index_build_path}
+ PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}
+ TIMEOUT 60
+ )
+ endforeach()
+endif()
+
+ament_package()
diff --git a/tracetools_test/package.xml b/tracetools_test/package.xml
new file mode 100644
index 0000000..a4d661e
--- /dev/null
+++ b/tracetools_test/package.xml
@@ -0,0 +1,28 @@
+
+
+
+ tracetools_test
+ 0.0.1
+ Separate test package for tracetools
+ Christophe Bedard
+ Christophe Bedard
+ APLv2
+
+ ament_cmake
+ pkg-config
+
+ rclcpp
+ std_msgs
+
+ rclcpp
+ std_msgs
+
+ ament_cmake_pytest
+ launch_ros
+ python3-pytest
+ tracetools_trace
+
+
+ ament_cmake
+
+
diff --git a/tracetools_test/test/test_publisher.cpp b/tracetools_test/test/test_publisher.cpp
new file mode 100644
index 0000000..05210d5
--- /dev/null
+++ b/tracetools_test/test/test_publisher.cpp
@@ -0,0 +1,32 @@
+#include "rclcpp/rclcpp.hpp"
+#include "std_msgs/msg/string.hpp"
+
+
+class PubNode : public rclcpp::Node
+{
+public:
+ PubNode() : Node("pub_node")
+ {
+ pub_ = this->create_publisher(
+ "the_topic",
+ rclcpp::QoS(10));
+ }
+
+private:
+ rclcpp::Publisher::SharedPtr pub_;
+};
+
+int main(int argc, char* argv[])
+{
+ rclcpp::init(argc, argv);
+
+ rclcpp::executors::SingleThreadedExecutor exec;
+ auto pub_node = std::make_shared();
+ exec.add_node(pub_node);
+
+ printf("spinning once\n");
+ exec.spin_once();
+
+ rclcpp::shutdown();
+ return 0;
+}
diff --git a/tracetools_test/test/test_publisher.py b/tracetools_test/test/test_publisher.py
new file mode 100644
index 0000000..c3e0b1e
--- /dev/null
+++ b/tracetools_test/test/test_publisher.py
@@ -0,0 +1,55 @@
+import time
+import shutil
+from launch import LaunchDescription
+from launch import LaunchIntrospector
+from launch import LaunchService
+
+from launch_ros import get_default_launch_description
+import launch_ros.actions
+import unittest
+from tracetools_analysis.test.utils import get_trace_event_names
+from tracetools_trace.tools.lttng import (
+ lttng_setup,
+ lttng_start,
+ lttng_stop,
+ lttng_destroy,
+)
+
+PKG = 'tracetools_test'
+
+publisher_creation_events = [
+ 'ros2:rcl_publisher_init',
+]
+
+class TestPublisher(unittest.TestCase):
+
+ def test_creation(self):
+ session_name = f'session-test-publisher-creation-{time.strftime("%Y%m%d%H%M%S")}'
+ path = '/tmp/' + session_name
+ print(f'trace directory: {path}')
+
+ lttng_setup(session_name, path, ros_events=publisher_creation_events, kernel_events=None)
+ lttng_start(session_name)
+
+ ld = LaunchDescription([
+ launch_ros.actions.Node(
+ package=PKG, node_executable='test_publisher', output='screen'),
+ ])
+ ls = LaunchService()
+ ls.include_launch_description(get_default_launch_description())
+ ls.include_launch_description(ld)
+
+ exit_code = ls.run()
+ self.assertEqual(exit_code, 0)
+
+ lttng_stop(session_name)
+ lttng_destroy(session_name)
+
+ trace_events = get_trace_event_names(path)
+ print(f'trace_events: {trace_events}')
+ self.assertListEqual(publisher_creation_events, list(trace_events))
+
+ shutil.rmtree(path)
+
+if __name__ == '__main__':
+ unittest.main()