Update docs

This commit is contained in:
Xuwznln
2025-11-18 17:17:43 +08:00
parent 653e6e1ac3
commit 6a681e1d73
121 changed files with 7700 additions and 985 deletions

View File

@@ -0,0 +1 @@
# 消息转换器测试包

View File

@@ -0,0 +1,71 @@
"""
基本测试
测试消息转换器的基本功能,包括导入、类型映射等。
"""
import unittest
from unilabos.ros.msgs.message_converter import (
msg_converter_manager,
get_msg_type,
get_action_type,
get_ros_type_by_msgname,
Point3D,
Point,
Float64,
String,
Bool,
Int32,
)
class TestBasicFunctionality(unittest.TestCase):
"""测试消息转换器的基本功能"""
def test_manager_initialization(self):
"""测试导入管理器初始化"""
self.assertIsNotNone(msg_converter_manager)
self.assertTrue(len(msg_converter_manager.list_modules()) > 0)
self.assertTrue(len(msg_converter_manager.list_classes()) > 0)
def test_get_msg_type(self):
"""测试获取消息类型"""
self.assertEqual(get_msg_type(float), Float64)
self.assertEqual(get_msg_type(str), String)
self.assertEqual(get_msg_type(bool), Bool)
self.assertEqual(get_msg_type(int), Int32)
self.assertEqual(get_msg_type(Point3D), Point)
# 测试错误情况
with self.assertRaises(ValueError):
get_msg_type(set) # 不支持的类型
def test_get_action_type(self):
"""测试获取动作类型"""
float_action = get_action_type(float)
self.assertIsNotNone(float_action)
self.assertTrue("type" in float_action)
self.assertTrue("goal" in float_action)
self.assertTrue("feedback" in float_action)
# 测试错误情况
with self.assertRaises(ValueError):
get_action_type(set) # 不支持的类型
def test_get_ros_type_by_msgname(self):
"""测试通过消息名称获取ROS类型"""
# 测试有效的消息名称
point_type = get_ros_type_by_msgname("geometry_msgs/msg/Point")
self.assertEqual(point_type, Point)
# 测试无效的消息名称
with self.assertRaises(ValueError):
get_ros_type_by_msgname("invalid_format")
# 不存在的消息类型可能会引发ImportError但这依赖于运行环境
# 因此不进行显式测试
if __name__ == "__main__":
unittest.main()

View File

@@ -0,0 +1,131 @@
"""
转换测试
测试Python对象和ROS消息之间的转换功能。
"""
import unittest
from dataclasses import dataclass
from unilabos.ros.msgs.message_converter import (
convert_to_ros_msg,
convert_from_ros_msg,
convert_to_ros_msg_with_mapping,
convert_from_ros_msg_with_mapping,
Point,
Float64,
String,
Point3D,
Resource,
)
# 定义一些测试数据类
@dataclass
class TestPoint:
x: float = 0.0
y: float = 0.0
z: float = 0.0
class TestBasicConversion(unittest.TestCase):
"""测试基本类型转换"""
def test_primitive_conversion(self):
"""测试原始类型转换"""
# Float转换
float_value = 3.14
ros_float = convert_to_ros_msg(Float64, float_value)
self.assertEqual(ros_float.data, float_value)
# 反向转换
py_float = convert_from_ros_msg(ros_float)
self.assertEqual(py_float, float_value)
# 字符串转换
str_value = "hello"
ros_str = convert_to_ros_msg(String, str_value)
self.assertEqual(ros_str.data, str_value)
# 反向转换
py_str = convert_from_ros_msg(ros_str)
self.assertEqual(py_str, str_value)
def test_point_conversion(self):
"""测试点类型转换"""
# 创建Point3D对象
py_point = Point3D(x=1.0, y=2.0, z=3.0)
# 转换为ROS Point
ros_point = convert_to_ros_msg(Point, py_point)
self.assertEqual(ros_point.x, py_point.x)
self.assertEqual(ros_point.y, py_point.y)
self.assertEqual(ros_point.z, py_point.z)
# 反向转换
py_point_back = convert_from_ros_msg(ros_point)
self.assertEqual(py_point_back.x, py_point.x)
self.assertEqual(py_point_back.y, py_point.y)
self.assertEqual(py_point_back.z, py_point.z)
def test_dataclass_conversion(self):
"""测试dataclass转换"""
# 创建dataclass
test_point = TestPoint(x=1.0, y=2.0, z=3.0)
# 转换
ros_point = convert_to_ros_msg(Point, test_point)
self.assertEqual(ros_point.x, test_point.x)
self.assertEqual(ros_point.y, test_point.y)
self.assertEqual(ros_point.z, test_point.z)
class TestMappingConversion(unittest.TestCase):
"""测试映射转换功能"""
def test_mapping_conversion(self):
"""测试带映射的转换"""
# 创建测试数据
test_data = {
"position": {"x": 1.0, "y": 2.0, "z": 3.0},
"name": "test_resource",
"id": "123",
"type": "test_type",
}
# 定义映射
mapping = {
"id": "id",
"name": "name",
"type": "type",
"pose.position": "position",
}
# 转换为ROS资源
ros_resource = convert_to_ros_msg_with_mapping(Resource, test_data, mapping)
self.assertEqual(ros_resource.id, "123")
self.assertEqual(ros_resource.name, "test_resource")
self.assertEqual(ros_resource.type, "test_type")
self.assertEqual(ros_resource.pose.position.x, 1.0)
self.assertEqual(ros_resource.pose.position.y, 2.0)
self.assertEqual(ros_resource.pose.position.z, 3.0)
# 反向转换
reverse_mapping = {
"id": "id",
"name": "name",
"type": "type",
"pose.position": "position",
}
py_data = convert_from_ros_msg_with_mapping(ros_resource, reverse_mapping)
self.assertEqual(py_data["id"], "123")
self.assertEqual(py_data["name"], "test_resource")
self.assertEqual(py_data["type"], "test_type")
self.assertEqual(py_data["position"].x, 1.0)
self.assertEqual(py_data["position"].y, 2.0)
self.assertEqual(py_data["position"].z, 3.0)
if __name__ == "__main__":
unittest.main()

View File

@@ -0,0 +1,120 @@
"""
映射测试
测试消息类型映射和字段映射功能。
"""
import unittest
from dataclasses import dataclass
from unilabos.ros.msgs.message_converter import (
_msg_mapping,
_action_mapping,
_msg_converter,
_msg_converter_back,
compare_model_fields,
Point,
Point3D,
Float64,
String,
set_msg_data,
)
@dataclass
class TestMappingModel:
"""用于测试映射的数据类"""
id: str
name: str
value: float
@dataclass
class TestPointModel:
"""用于测试字段比较的点模型"""
x: float
y: float
z: float
class TestTypeMapping(unittest.TestCase):
"""测试类型映射"""
def test_msg_mapping(self):
"""测试消息类型映射"""
self.assertIn(float, _msg_mapping)
self.assertEqual(_msg_mapping[float], Float64)
self.assertIn(str, _msg_mapping)
self.assertEqual(_msg_mapping[str], String)
self.assertIn(Point3D, _msg_mapping)
self.assertEqual(_msg_mapping[Point3D], Point)
def test_action_mapping(self):
"""测试动作类型映射"""
self.assertIn(float, _action_mapping)
self.assertIn("type", _action_mapping[float])
self.assertIn("goal", _action_mapping[float])
self.assertIn("feedback", _action_mapping[float])
self.assertIn("result", _action_mapping[float])
def test_converter_mapping(self):
"""测试转换器映射"""
# 测试Python到ROS映射
self.assertIn(float, _msg_converter)
self.assertIn(Float64, _msg_converter)
self.assertIn(String, _msg_converter)
self.assertIn(Point, _msg_converter)
# 测试ROS到Python映射
self.assertIn(float, _msg_converter_back)
self.assertIn(Float64, _msg_converter_back)
self.assertIn(String, _msg_converter_back)
self.assertIn(Point, _msg_converter_back)
class TestFieldMapping(unittest.TestCase):
"""测试字段映射"""
def test_compare_model_fields(self):
"""测试模型字段比较"""
# Point3D和TestPointModel有相同的字段
self.assertTrue(compare_model_fields(Point3D, TestPointModel))
# 与其他类型比较
self.assertFalse(compare_model_fields(Point3D, TestMappingModel))
self.assertFalse(compare_model_fields(Point3D, float))
# 类型对象和实例对象比较
point = Point3D(x=1.0, y=2.0, z=3.0)
self.assertTrue(compare_model_fields(Point3D, type(point)))
def test_set_msg_data(self):
"""测试设置消息数据类型"""
# 测试float转换
float_value = "3.14"
self.assertEqual(set_msg_data("float", float_value), 3.14)
self.assertEqual(set_msg_data("double", float_value), 3.14)
# 测试int转换
int_value = "42"
self.assertEqual(set_msg_data("int", int_value), 42)
# 测试bool转换
bool_value = "True"
self.assertEqual(set_msg_data("bool", bool_value), True)
# 测试str转换
str_value = "hello"
self.assertEqual(set_msg_data("str", str_value), "hello")
# 测试默认转换
default_value = 123
self.assertEqual(set_msg_data("unknown_type", default_value), "123")
if __name__ == "__main__":
unittest.main()

View File

@@ -0,0 +1,47 @@
"""
测试运行器
运行所有消息转换器的测试用例。
"""
import unittest
import sys
import os
# 添加项目根目录到路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))))
# 导入测试模块
from test.ros.msgs.test_basic import TestBasicFunctionality
from test.ros.msgs.test_conversion import TestBasicConversion, TestMappingConversion
from test.ros.msgs.test_mapping import TestTypeMapping, TestFieldMapping
def run_tests():
"""运行所有测试"""
# 创建测试加载器
loader = unittest.TestLoader()
# 创建测试套件
suite = unittest.TestSuite()
# 添加测试类
suite.addTests(loader.loadTestsFromTestCase(TestBasicFunctionality))
suite.addTests(loader.loadTestsFromTestCase(TestBasicConversion))
suite.addTests(loader.loadTestsFromTestCase(TestMappingConversion))
suite.addTests(loader.loadTestsFromTestCase(TestTypeMapping))
suite.addTests(loader.loadTestsFromTestCase(TestFieldMapping))
# 创建测试运行器
runner = unittest.TextTestRunner(verbosity=2)
# 运行测试
result = runner.run(suite)
# 返回结果
return result.wasSuccessful()
if __name__ == "__main__":
success = run_tests()
sys.exit(not success)