mirror of
https://github.com/ZGCA-Forge/MsgCenterPy.git
synced 2025-12-15 13:34:36 +00:00
init version
This commit is contained in:
463
tests/test_json_schema_instance.py
Normal file
463
tests/test_json_schema_instance.py
Normal file
@@ -0,0 +1,463 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
# 添加项目路径
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
||||
|
||||
# JSON Schema 依赖检查
|
||||
|
||||
from msgcenterpy.core.type_info import ConstraintType
|
||||
from msgcenterpy.core.types import MessageType
|
||||
from msgcenterpy.instances.json_schema_instance import JSONSchemaMessageInstance
|
||||
|
||||
|
||||
class TestJSONSchemaMessageInstance:
|
||||
"""JSONSchemaMessageInstance 基本功能测试"""
|
||||
|
||||
@pytest.fixture
|
||||
def simple_schema(self):
|
||||
"""简单的 JSON Schema 示例"""
|
||||
return {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"age": {"type": "integer", "minimum": 0, "maximum": 150},
|
||||
"active": {"type": "boolean"},
|
||||
},
|
||||
"required": ["name"],
|
||||
}
|
||||
|
||||
@pytest.fixture
|
||||
def complex_schema(self):
|
||||
"""复杂的 JSON Schema 示例"""
|
||||
return {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"user": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {"type": "string"},
|
||||
"profile": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"email": {"type": "string", "format": "email"},
|
||||
"phone": {
|
||||
"type": "string",
|
||||
"pattern": "^\\+?[1-9]\\d{1,14}$",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"required": ["id"],
|
||||
},
|
||||
"tags": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"minItems": 1,
|
||||
"maxItems": 10,
|
||||
},
|
||||
"scores": {
|
||||
"type": "array",
|
||||
"items": {"type": "number", "minimum": 0, "maximum": 100},
|
||||
},
|
||||
"metadata": {"type": "object", "additionalProperties": True},
|
||||
},
|
||||
"required": ["user", "tags"],
|
||||
}
|
||||
|
||||
@pytest.fixture
|
||||
def simple_data(self):
|
||||
"""匹配简单 schema 的数据"""
|
||||
return {"name": "John Doe", "age": 30, "active": True}
|
||||
|
||||
@pytest.fixture
|
||||
def complex_data(self):
|
||||
"""匹配复杂 schema 的数据"""
|
||||
return {
|
||||
"user": {
|
||||
"id": "user_123",
|
||||
"profile": {"email": "john@example.com", "phone": "+1234567890"},
|
||||
},
|
||||
"tags": ["developer", "python", "testing"],
|
||||
"scores": [85.5, 92.0, 78.3],
|
||||
"metadata": {"created_at": "2024-01-01", "version": 1},
|
||||
}
|
||||
|
||||
def test_basic_creation(self, simple_schema, simple_data):
|
||||
"""测试基本创建功能"""
|
||||
instance = JSONSchemaMessageInstance(simple_data, simple_schema)
|
||||
|
||||
assert instance.message_type == MessageType.JSON_SCHEMA
|
||||
assert instance.inner_data == simple_data
|
||||
assert instance.json_schema == simple_schema
|
||||
assert len(instance._validation_errors) == 0
|
||||
|
||||
def test_data_validation_success(self, simple_schema, simple_data):
|
||||
"""测试数据验证成功"""
|
||||
instance = JSONSchemaMessageInstance(simple_data, simple_schema)
|
||||
|
||||
# 验证成功,没有错误
|
||||
assert len(instance._validation_errors) == 0
|
||||
|
||||
def test_data_validation_failure(self, simple_schema):
|
||||
"""测试数据验证失败"""
|
||||
invalid_data = {
|
||||
"age": -5, # 违反 minimum 约束
|
||||
"active": "not_boolean", # 类型错误
|
||||
# 缺少必需的 "name" 字段
|
||||
}
|
||||
|
||||
instance = JSONSchemaMessageInstance(invalid_data, simple_schema)
|
||||
|
||||
# 应该有验证错误
|
||||
assert len(instance._validation_errors) > 0
|
||||
|
||||
def test_get_python_dict(self, simple_schema, simple_data):
|
||||
"""测试获取 Python 字典"""
|
||||
instance = JSONSchemaMessageInstance(simple_data, simple_schema)
|
||||
|
||||
result = instance.get_python_dict()
|
||||
|
||||
assert isinstance(result, dict)
|
||||
assert result == simple_data
|
||||
assert result is not simple_data # 应该是副本
|
||||
|
||||
def test_set_python_dict(self, simple_schema, simple_data):
|
||||
"""测试设置 Python 字典"""
|
||||
instance = JSONSchemaMessageInstance(simple_data, simple_schema)
|
||||
|
||||
new_data = {"name": "Jane Smith", "age": 25}
|
||||
|
||||
result = instance.set_python_dict(new_data)
|
||||
|
||||
assert result is True
|
||||
assert instance.get_python_dict()["name"] == "Jane Smith"
|
||||
assert instance.get_python_dict()["age"] == 25
|
||||
|
||||
def test_export_to_envelope(self, simple_schema, simple_data):
|
||||
"""测试导出信封"""
|
||||
instance = JSONSchemaMessageInstance(simple_data, simple_schema)
|
||||
|
||||
envelope = instance.export_to_envelope()
|
||||
|
||||
assert "content" in envelope
|
||||
assert "metadata" in envelope
|
||||
assert envelope["content"] == simple_data
|
||||
|
||||
metadata = envelope["metadata"]
|
||||
assert metadata["current_format"] == "json_schema"
|
||||
assert "properties" in metadata
|
||||
|
||||
def test_import_from_envelope(self, simple_schema, simple_data):
|
||||
"""测试从信封导入"""
|
||||
# 创建原始实例
|
||||
original = JSONSchemaMessageInstance(simple_data, simple_schema)
|
||||
envelope = original.export_to_envelope()
|
||||
|
||||
# 从信封导入新实例
|
||||
new_instance = JSONSchemaMessageInstance.import_from_envelope(envelope)
|
||||
|
||||
assert isinstance(new_instance, JSONSchemaMessageInstance)
|
||||
assert new_instance.get_python_dict() == simple_data
|
||||
assert new_instance.json_schema == simple_schema
|
||||
|
||||
|
||||
class TestJSONSchemaFieldTypeInfo:
|
||||
"""JSON Schema 字段类型信息测试"""
|
||||
|
||||
@pytest.fixture
|
||||
def typed_schema(self):
|
||||
"""包含各种类型的 schema"""
|
||||
return {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"string_field": {"type": "string", "minLength": 3, "maxLength": 50},
|
||||
"integer_field": {"type": "integer", "minimum": 0, "maximum": 100},
|
||||
"number_field": {"type": "number", "multipleOf": 0.5},
|
||||
"boolean_field": {"type": "boolean"},
|
||||
"array_field": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"minItems": 1,
|
||||
"maxItems": 5,
|
||||
},
|
||||
"object_field": {
|
||||
"type": "object",
|
||||
"properties": {"nested_string": {"type": "string"}},
|
||||
},
|
||||
"enum_field": {
|
||||
"type": "string",
|
||||
"enum": ["option1", "option2", "option3"],
|
||||
},
|
||||
"format_field": {"type": "string", "format": "email"},
|
||||
},
|
||||
"required": ["string_field", "integer_field"],
|
||||
}
|
||||
|
||||
@pytest.fixture
|
||||
def typed_data(self):
|
||||
"""匹配类型化 schema 的数据"""
|
||||
return {
|
||||
"string_field": "hello",
|
||||
"integer_field": 42,
|
||||
"number_field": 3.5,
|
||||
"boolean_field": True,
|
||||
"array_field": ["item1", "item2"],
|
||||
"object_field": {"nested_string": "nested_value"},
|
||||
"enum_field": "option1",
|
||||
"format_field": "test@example.com",
|
||||
}
|
||||
|
||||
def test_string_field_type_info(self, typed_schema, typed_data):
|
||||
"""测试字符串字段类型信息"""
|
||||
instance = JSONSchemaMessageInstance(typed_data, typed_schema)
|
||||
type_info = instance.fields.get_sub_type_info("string_field")
|
||||
|
||||
assert type_info is not None
|
||||
assert type_info.field_name == "string_field"
|
||||
assert type_info.standard_type.value == "string"
|
||||
assert type_info.current_value == "hello"
|
||||
|
||||
# 检查约束
|
||||
assert type_info.has_constraint(ConstraintType.MIN_LENGTH)
|
||||
assert type_info.get_constraint_value(ConstraintType.MIN_LENGTH) == 3
|
||||
assert type_info.has_constraint(ConstraintType.MAX_LENGTH)
|
||||
assert type_info.get_constraint_value(ConstraintType.MAX_LENGTH) == 50
|
||||
assert type_info.has_constraint(ConstraintType.REQUIRED)
|
||||
|
||||
def test_integer_field_type_info(self, typed_schema, typed_data):
|
||||
"""测试整数字段类型信息"""
|
||||
instance = JSONSchemaMessageInstance(typed_data, typed_schema)
|
||||
type_info = instance.fields.get_sub_type_info("integer_field")
|
||||
|
||||
assert type_info is not None
|
||||
assert type_info.standard_type.value == "integer"
|
||||
assert type_info.current_value == 42
|
||||
|
||||
# 检查数值约束
|
||||
assert type_info.has_constraint(ConstraintType.MIN_VALUE)
|
||||
assert type_info.get_constraint_value(ConstraintType.MIN_VALUE) == 0
|
||||
assert type_info.has_constraint(ConstraintType.MAX_VALUE)
|
||||
assert type_info.get_constraint_value(ConstraintType.MAX_VALUE) == 100
|
||||
assert type_info.has_constraint(ConstraintType.REQUIRED)
|
||||
|
||||
def test_array_field_type_info(self, typed_schema, typed_data):
|
||||
"""测试数组字段类型信息"""
|
||||
instance = JSONSchemaMessageInstance(typed_data, typed_schema)
|
||||
type_info = instance.fields.get_sub_type_info("array_field")
|
||||
|
||||
assert type_info is not None
|
||||
assert type_info.is_array is True
|
||||
assert type_info.current_value == ["item1", "item2"]
|
||||
|
||||
# 检查数组约束
|
||||
assert type_info.has_constraint(ConstraintType.MIN_ITEMS)
|
||||
assert type_info.get_constraint_value(ConstraintType.MIN_ITEMS) == 1
|
||||
assert type_info.has_constraint(ConstraintType.MAX_ITEMS)
|
||||
assert type_info.get_constraint_value(ConstraintType.MAX_ITEMS) == 5
|
||||
|
||||
# 检查元素类型信息
|
||||
assert type_info.element_type_info is not None
|
||||
assert type_info.element_type_info.standard_type.value == "string"
|
||||
|
||||
def test_object_field_type_info(self, typed_schema, typed_data):
|
||||
"""测试对象字段类型信息"""
|
||||
instance = JSONSchemaMessageInstance(typed_data, typed_schema)
|
||||
type_info = instance.fields.get_sub_type_info("object_field")
|
||||
|
||||
assert type_info is not None
|
||||
assert type_info.is_object is True
|
||||
assert type_info.current_value == {"nested_string": "nested_value"}
|
||||
|
||||
# 检查对象字段定义
|
||||
assert len(type_info.object_fields) > 0
|
||||
assert "nested_string" in type_info.object_fields
|
||||
|
||||
nested_field_info = type_info.object_fields["nested_string"]
|
||||
assert nested_field_info.standard_type.value == "string"
|
||||
|
||||
def test_enum_field_type_info(self, typed_schema, typed_data):
|
||||
"""测试枚举字段类型信息"""
|
||||
instance = JSONSchemaMessageInstance(typed_data, typed_schema)
|
||||
type_info = instance.fields.get_sub_type_info("enum_field")
|
||||
|
||||
assert type_info is not None
|
||||
assert type_info.has_constraint(ConstraintType.ENUM_VALUES)
|
||||
enum_values = type_info.get_constraint_value(ConstraintType.ENUM_VALUES)
|
||||
assert enum_values == ["option1", "option2", "option3"]
|
||||
|
||||
def test_format_field_type_info(self, typed_schema, typed_data):
|
||||
"""测试格式字段类型信息"""
|
||||
instance = JSONSchemaMessageInstance(typed_data, typed_schema)
|
||||
type_info = instance.fields.get_sub_type_info("format_field")
|
||||
|
||||
assert type_info is not None
|
||||
assert type_info.has_constraint(ConstraintType.FORMAT)
|
||||
format_value = type_info.get_constraint_value(ConstraintType.FORMAT)
|
||||
assert format_value == "email"
|
||||
|
||||
|
||||
class TestJSONSchemaInstanceJSONSchema:
|
||||
"""JSONSchemaMessageInstance 自身的 JSON Schema 生成测试"""
|
||||
|
||||
def test_get_json_schema_simple(self):
|
||||
"""测试简单数据的 JSON Schema 生成"""
|
||||
schema = {
|
||||
"type": "object",
|
||||
"properties": {"name": {"type": "string"}, "count": {"type": "integer"}},
|
||||
}
|
||||
data = {"name": "test", "count": 5}
|
||||
|
||||
instance = JSONSchemaMessageInstance(data, schema)
|
||||
generated_schema = instance.get_json_schema()
|
||||
|
||||
assert generated_schema["type"] == "object"
|
||||
assert "properties" in generated_schema
|
||||
assert "name" in generated_schema["properties"]
|
||||
assert "count" in generated_schema["properties"]
|
||||
assert generated_schema["title"] == "JSONSchemaMessageInstance Schema"
|
||||
|
||||
def test_get_json_schema_with_constraints(self):
|
||||
"""测试包含约束的 JSON Schema 生成"""
|
||||
schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"email": {"type": "string", "format": "email", "minLength": 5},
|
||||
"age": {"type": "integer", "minimum": 0, "maximum": 120},
|
||||
"tags": {"type": "array", "items": {"type": "string"}, "minItems": 1},
|
||||
},
|
||||
"required": ["email"],
|
||||
}
|
||||
data = {"email": "test@example.com", "age": 25, "tags": ["tag1", "tag2"]}
|
||||
|
||||
instance = JSONSchemaMessageInstance(data, schema)
|
||||
generated_schema = instance.get_json_schema()
|
||||
|
||||
# 检查约束是否保留在生成的 schema 中
|
||||
properties = generated_schema["properties"]
|
||||
|
||||
# email 字段约束
|
||||
email_prop = properties["email"]
|
||||
assert email_prop["type"] == "string"
|
||||
|
||||
# age 字段约束
|
||||
age_prop = properties["age"]
|
||||
assert age_prop["type"] == "integer"
|
||||
|
||||
# tags 数组约束
|
||||
tags_prop = properties["tags"]
|
||||
assert tags_prop["type"] == "array"
|
||||
|
||||
def test_get_json_schema_nested_objects(self):
|
||||
"""测试嵌套对象的 JSON Schema 生成"""
|
||||
schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"user": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {"type": "string"},
|
||||
"settings": {
|
||||
"type": "object",
|
||||
"properties": {"theme": {"type": "string"}},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
data = {"user": {"id": "user123", "settings": {"theme": "dark"}}}
|
||||
|
||||
instance = JSONSchemaMessageInstance(data, schema)
|
||||
generated_schema = instance.get_json_schema()
|
||||
|
||||
assert "user" in generated_schema["properties"]
|
||||
user_prop = generated_schema["properties"]["user"]
|
||||
assert user_prop["type"] == "object"
|
||||
|
||||
|
||||
class TestJSONSchemaValidation:
|
||||
"""JSON Schema 验证功能测试"""
|
||||
|
||||
def test_constraint_validation(self):
|
||||
"""测试约束验证"""
|
||||
schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"age": {"type": "integer", "minimum": 0, "maximum": 150},
|
||||
"name": {"type": "string", "minLength": 2, "maxLength": 50},
|
||||
},
|
||||
"required": ["name"],
|
||||
}
|
||||
|
||||
# 有效数据
|
||||
valid_data = {"name": "John", "age": 30}
|
||||
valid_instance = JSONSchemaMessageInstance(valid_data, schema)
|
||||
assert len(valid_instance._validation_errors) == 0
|
||||
|
||||
# 无效数据 - 年龄超出范围
|
||||
invalid_data1 = {"name": "John", "age": 200}
|
||||
invalid_instance1 = JSONSchemaMessageInstance(invalid_data1, schema)
|
||||
assert len(invalid_instance1._validation_errors) > 0
|
||||
|
||||
# 无效数据 - 缺少必需字段
|
||||
invalid_data2 = {"age": 30}
|
||||
invalid_instance2 = JSONSchemaMessageInstance(invalid_data2, schema)
|
||||
assert len(invalid_instance2._validation_errors) > 0
|
||||
|
||||
def test_type_validation(self):
|
||||
"""测试类型验证"""
|
||||
schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"count": {"type": "integer"},
|
||||
"active": {"type": "boolean"},
|
||||
"items": {"type": "array", "items": {"type": "string"}},
|
||||
},
|
||||
}
|
||||
|
||||
# 类型正确的数据
|
||||
valid_data = {"count": 42, "active": True, "items": ["a", "b", "c"]}
|
||||
valid_instance = JSONSchemaMessageInstance(valid_data, schema)
|
||||
assert len(valid_instance._validation_errors) == 0
|
||||
|
||||
# 类型错误的数据
|
||||
invalid_data = {
|
||||
"count": "not_integer",
|
||||
"active": "not_boolean",
|
||||
"items": "not_array",
|
||||
}
|
||||
invalid_instance = JSONSchemaMessageInstance(invalid_data, schema)
|
||||
assert len(invalid_instance._validation_errors) > 0
|
||||
|
||||
|
||||
# 运行测试的便捷函数
|
||||
def run_json_schema_tests():
|
||||
"""运行 JSON Schema 相关测试"""
|
||||
|
||||
import subprocess
|
||||
|
||||
result = subprocess.run(
|
||||
[
|
||||
"python",
|
||||
"-m",
|
||||
"pytest",
|
||||
"tests/test_json_schema_instance.py",
|
||||
"-v",
|
||||
"--tb=short",
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
|
||||
print(result.stdout)
|
||||
if result.stderr:
|
||||
print("STDERR:", result.stderr)
|
||||
|
||||
return result.returncode == 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 直接运行测试
|
||||
run_json_schema_tests()
|
||||
325
tests/test_ros2_instance.py
Normal file
325
tests/test_ros2_instance.py
Normal file
@@ -0,0 +1,325 @@
|
||||
import array
|
||||
import os
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
from msgcenterpy import TypeConverter
|
||||
|
||||
# Add project path
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
||||
|
||||
# ROS2 dependency check
|
||||
try:
|
||||
from geometry_msgs.msg import Point, Pose
|
||||
from std_msgs.msg import Float64MultiArray, String
|
||||
|
||||
# Only import ROS2MessageInstance when ROS2 message packages are available
|
||||
from msgcenterpy.instances.ros2_instance import ROS2MessageInstance
|
||||
|
||||
HAS_ROS2 = True
|
||||
except ImportError:
|
||||
HAS_ROS2 = False
|
||||
|
||||
|
||||
from msgcenterpy.core.types import MessageType
|
||||
|
||||
|
||||
class TestROS2MessageInstance:
|
||||
"""ROS2MessageInstance test class"""
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="ROS2 dependencies not available")
|
||||
def test_basic_creation_string_message(self):
|
||||
"""Test basic String message creation"""
|
||||
# Create String message
|
||||
string_msg = String()
|
||||
string_msg.data = "Hello ROS2"
|
||||
|
||||
# Create ROS2MessageInstance
|
||||
ros2_inst = ROS2MessageInstance(string_msg)
|
||||
|
||||
assert ros2_inst.message_type == MessageType.ROS2
|
||||
assert ros2_inst.inner_data is string_msg
|
||||
assert ros2_inst.ros_msg_cls == String
|
||||
assert ros2_inst.ros_msg_cls_namespace == "std_msgs/msg/String"
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="ROS2 dependencies not available")
|
||||
def test_basic_creation_float_array(self):
|
||||
"""Test Float64MultiArray message creation"""
|
||||
# Create Float64MultiArray message
|
||||
array_msg = Float64MultiArray()
|
||||
array_msg.data = [1.1, 2.2, 3.3, 4.4, 5.5]
|
||||
|
||||
# Create ROS2MessageInstance
|
||||
ros2_inst = ROS2MessageInstance(array_msg)
|
||||
|
||||
assert ros2_inst.message_type == MessageType.ROS2
|
||||
assert ros2_inst.inner_data is array_msg
|
||||
assert ros2_inst.ros_msg_cls == Float64MultiArray
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="ROS2 dependencies not available")
|
||||
def test_simple_field_assignment(self):
|
||||
"""Test simple field assignment - based on __main__ test1"""
|
||||
# Create String message
|
||||
string_msg = String()
|
||||
ros2_inst = ROS2MessageInstance(string_msg)
|
||||
|
||||
# Initial state check
|
||||
assert string_msg.data == ""
|
||||
|
||||
# Test field assignment
|
||||
ros2_inst.data = "test_value" # Assignment through field accessor
|
||||
assert string_msg.data == "test_value"
|
||||
assert ros2_inst.inner_data.data == "test_value"
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="ROS2 dependencies not available")
|
||||
def test_nested_field_assignment(self):
|
||||
"""测试嵌套字段赋值 - 基于 __main__ 测试2,3"""
|
||||
# Create Pose message
|
||||
pose_msg = Pose()
|
||||
ros2_inst = ROS2MessageInstance(pose_msg)
|
||||
|
||||
# 测试嵌套字段赋值
|
||||
ros2_inst.position.x = 1.5
|
||||
ros2_inst.position.y = 2.5
|
||||
ros2_inst.position.z = 3.5
|
||||
|
||||
assert pose_msg.position.x == 1.5
|
||||
assert pose_msg.position.y == 2.5
|
||||
assert pose_msg.position.z == 3.5
|
||||
|
||||
# 测试整个对象赋值
|
||||
new_position = Point(x=10.0, y=20.0, z=30.0)
|
||||
ros2_inst.position = new_position
|
||||
|
||||
assert pose_msg.position.x == 10.0
|
||||
assert pose_msg.position.y == 20.0
|
||||
assert pose_msg.position.z == 30.0
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="ROS2 dependencies not available")
|
||||
def test_export_to_envelope(self):
|
||||
"""测试导出信封功能 - 基于 __main__ 测试6"""
|
||||
# Create and setup String message
|
||||
string_msg = String()
|
||||
string_msg.data = "test_envelope_data"
|
||||
ros2_inst = ROS2MessageInstance(string_msg)
|
||||
|
||||
# 导出信封
|
||||
envelope = ros2_inst.export_to_envelope()
|
||||
|
||||
# 验证信封结构
|
||||
assert "content" in envelope
|
||||
assert "metadata" in envelope
|
||||
assert envelope["content"]["data"] == "test_envelope_data"
|
||||
|
||||
# 验证元数据
|
||||
metadata = envelope["metadata"]
|
||||
assert metadata["current_format"] == "ros2"
|
||||
assert "properties" in metadata
|
||||
|
||||
properties = metadata["properties"]
|
||||
assert "ros_msg_cls_namespace" in properties
|
||||
assert "ros_msg_cls_path" in properties
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="ROS2 dependencies not available")
|
||||
def test_get_python_dict(self):
|
||||
"""测试获取 Python 字典"""
|
||||
# Create Float64MultiArray message
|
||||
array_msg = Float64MultiArray()
|
||||
array_msg.data = [1.0, 2.0, 3.0]
|
||||
ros2_inst = ROS2MessageInstance(array_msg)
|
||||
|
||||
# 获取 Python 字典
|
||||
python_dict = ros2_inst.get_python_dict()
|
||||
|
||||
assert isinstance(python_dict, dict)
|
||||
assert "data" in python_dict
|
||||
assert python_dict["data"] == [1.0, 2.0, 3.0]
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="ROS2 dependencies not available")
|
||||
def test_set_python_dict(self):
|
||||
"""测试设置 Python 字典"""
|
||||
# Create String message
|
||||
string_msg = String()
|
||||
ros2_inst = ROS2MessageInstance(string_msg)
|
||||
|
||||
# 设置字典数据
|
||||
new_data = {"data": "updated_value"}
|
||||
result = ros2_inst.set_python_dict(new_data)
|
||||
|
||||
assert result is True
|
||||
assert string_msg.data == "updated_value"
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="ROS2 dependencies not available")
|
||||
def test_field_type_info_extraction(self):
|
||||
"""测试字段类型信息提取"""
|
||||
# Create Float64MultiArray message
|
||||
array_msg = Float64MultiArray()
|
||||
array_msg.data = [1.0, 2.0, 3.0]
|
||||
ros2_inst = ROS2MessageInstance(array_msg)
|
||||
|
||||
# 获取字段类型信息
|
||||
type_info = ros2_inst.fields.get_sub_type_info("data")
|
||||
|
||||
assert type_info is not None
|
||||
assert type_info.field_name == "data"
|
||||
assert type_info.is_array is True
|
||||
assert type_info.python_type == array.array
|
||||
assert type_info.python_value_from_standard_type == [1.0, 2.0, 3.0]
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="ROS2 dependencies not available")
|
||||
def test_obtain_ros_cls_from_string(self):
|
||||
"""测试从字符串获取 ROS 类"""
|
||||
# 测试 namespace 格式
|
||||
ros_cls_ns = ROS2MessageInstance.obtain_ros_cls_from_str("std_msgs/msg/String")
|
||||
assert ros_cls_ns == String
|
||||
|
||||
# 测试模块路径格式
|
||||
ros_cls_path = ROS2MessageInstance.obtain_ros_cls_from_str("std_msgs.msg._string.String")
|
||||
assert ros_cls_path == String
|
||||
|
||||
# 测试直接传入类
|
||||
ros_cls_direct = ROS2MessageInstance.obtain_ros_cls_from_str(String)
|
||||
assert ros_cls_direct == String
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="ROS2 dependencies not available")
|
||||
def test_ros_msg_cls_properties(self):
|
||||
"""测试 ROS 消息类属性"""
|
||||
string_msg = String()
|
||||
ros2_inst = ROS2MessageInstance(string_msg)
|
||||
|
||||
# 测试类路径属性
|
||||
cls_path = ros2_inst.ros_msg_cls_path
|
||||
assert "std_msgs.msg" in cls_path
|
||||
assert "String" in cls_path
|
||||
|
||||
# 测试命名空间属性
|
||||
namespace = ros2_inst.ros_msg_cls_namespace
|
||||
assert namespace == "std_msgs/msg/String"
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="ROS2 dependencies not available")
|
||||
def test_import_from_envelope(self):
|
||||
"""测试从信封导入"""
|
||||
# Create original message
|
||||
original_msg = String()
|
||||
original_msg.data = "envelope_test"
|
||||
original_inst = ROS2MessageInstance(original_msg)
|
||||
|
||||
# 导出信封
|
||||
envelope = original_inst.export_to_envelope()
|
||||
|
||||
# 从信封导入新实例
|
||||
new_inst = ROS2MessageInstance.import_from_envelope(envelope)
|
||||
|
||||
assert isinstance(new_inst, ROS2MessageInstance)
|
||||
assert new_inst.inner_data.data == "envelope_test"
|
||||
assert new_inst.ros_msg_cls == String
|
||||
|
||||
|
||||
class TestROS2MessageInstanceJSONSchema:
|
||||
"""ROS2MessageInstance JSON Schema 生成测试"""
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="ROS2 dependencies not available")
|
||||
def test_get_json_schema_string_message(self):
|
||||
"""测试 String 消息的 JSON Schema 生成"""
|
||||
string_msg = String()
|
||||
string_msg.data = "test_schema"
|
||||
ros2_inst = ROS2MessageInstance(string_msg)
|
||||
|
||||
# 生成 JSON Schema
|
||||
schema = ros2_inst.get_json_schema()
|
||||
|
||||
assert schema["type"] == "object"
|
||||
assert "properties" in schema
|
||||
assert "data" in schema["properties"]
|
||||
assert schema["properties"]["data"]["type"] == "string"
|
||||
assert schema["title"] == "ROS2MessageInstance Schema"
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="ROS2 dependencies not available")
|
||||
def test_get_json_schema_float_array(self):
|
||||
"""测试 Float64MultiArray 的 JSON Schema 生成"""
|
||||
array_msg = Float64MultiArray()
|
||||
array_msg.data = [1.1, 2.2, 3.3]
|
||||
ros2_inst = ROS2MessageInstance(array_msg)
|
||||
|
||||
# 生成 JSON Schema
|
||||
schema = ros2_inst.get_json_schema()
|
||||
|
||||
assert schema["type"] == "object"
|
||||
assert "properties" in schema
|
||||
assert "data" in schema["properties"]
|
||||
|
||||
# 检查数组类型
|
||||
data_prop = schema["properties"]["data"]
|
||||
assert data_prop["type"] == "array"
|
||||
assert "items" in data_prop
|
||||
assert data_prop["items"]["type"] == "number"
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="ROS2 dependencies not available")
|
||||
def test_get_json_schema_pose_message(self):
|
||||
"""测试复杂 Pose 消息的 JSON Schema 生成"""
|
||||
pose_msg = Pose()
|
||||
pose_msg.position.x = 1.0
|
||||
pose_msg.position.y = 2.0
|
||||
pose_msg.position.z = 3.0
|
||||
ros2_inst = ROS2MessageInstance(pose_msg)
|
||||
|
||||
# 生成 JSON Schema
|
||||
schema = ros2_inst.get_json_schema()
|
||||
|
||||
assert schema["type"] == "object"
|
||||
assert "properties" in schema
|
||||
|
||||
# 检查嵌套对象
|
||||
properties = schema["properties"]
|
||||
assert "position" in properties
|
||||
assert "orientation" in properties
|
||||
|
||||
# 验证对象类型
|
||||
position_prop = properties["position"]
|
||||
assert position_prop["type"] == "object"
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="ROS2 dependencies not available")
|
||||
def test_json_schema_constraint_extraction(self):
|
||||
"""测试约束条件提取"""
|
||||
array_msg = Float64MultiArray()
|
||||
array_msg.data = [1.0, 2.0, 3.0, 4.0, 5.0]
|
||||
ros2_inst = ROS2MessageInstance(array_msg)
|
||||
|
||||
# 获取字段类型信息检查约束
|
||||
type_info = ros2_inst.fields.get_sub_type_info("data")
|
||||
|
||||
assert type_info is not None
|
||||
assert type_info.is_array is True
|
||||
|
||||
# 生成 Schema 并检查约束是否转换
|
||||
schema = ros2_inst.get_json_schema()
|
||||
data_prop = schema["properties"]["data"]
|
||||
assert data_prop["type"] == "array"
|
||||
|
||||
|
||||
# 运行测试的便捷函数
|
||||
def run_ros2_tests():
|
||||
"""运行 ROS2 相关测试"""
|
||||
if not HAS_ROS2:
|
||||
print("❌ ROS2 dependencies not available, skipping tests")
|
||||
return False
|
||||
|
||||
import subprocess
|
||||
|
||||
result = subprocess.run(
|
||||
["python", "-m", "pytest", "tests/test_ros2_instance.py", "-v", "--tb=short"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
|
||||
print(result.stdout)
|
||||
if result.stderr:
|
||||
print("STDERR:", result.stderr)
|
||||
|
||||
return result.returncode == 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 直接运行测试
|
||||
run_ros2_tests()
|
||||
384
tests/test_ros_to_json_schema_conversion.py
Normal file
384
tests/test_ros_to_json_schema_conversion.py
Normal file
@@ -0,0 +1,384 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
# 添加项目路径
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
||||
|
||||
# 依赖检查
|
||||
try:
|
||||
from geometry_msgs.msg import Point, Pose, Vector3
|
||||
from std_msgs.msg import Bool, Float64MultiArray, Int32, String
|
||||
|
||||
# 只有在 ROS2 消息包可用时才导入 ROS2MessageInstance
|
||||
from msgcenterpy.instances.ros2_instance import ROS2MessageInstance
|
||||
|
||||
HAS_ROS2 = True
|
||||
except ImportError:
|
||||
HAS_ROS2 = False
|
||||
|
||||
|
||||
import jsonschema
|
||||
|
||||
from msgcenterpy.core.types import MessageType
|
||||
from msgcenterpy.instances.json_schema_instance import JSONSchemaMessageInstance
|
||||
|
||||
|
||||
class TestROS2ToJSONSchemaConversion:
|
||||
"""ROS2 转 JSON Schema 转换测试"""
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="Missing dependencies")
|
||||
def test_string_message_to_json_schema(self):
|
||||
"""测试 String 消息转 JSON Schema"""
|
||||
# 创建 ROS2 String 消息
|
||||
string_msg = String()
|
||||
string_msg.data = "Hello JSON Schema"
|
||||
ros2_inst = ROS2MessageInstance(string_msg)
|
||||
|
||||
# 生成 JSON Schema
|
||||
schema = ros2_inst.get_json_schema()
|
||||
|
||||
# 验证 Schema 结构
|
||||
assert schema["type"] == "object"
|
||||
assert "properties" in schema
|
||||
assert "data" in schema["properties"]
|
||||
assert schema["properties"]["data"]["type"] == "string"
|
||||
assert schema["title"] == "ROS2MessageInstance Schema"
|
||||
assert "ros2" in schema["description"]
|
||||
|
||||
# 验证与原始数据的一致性
|
||||
ros2_dict = ros2_inst.get_python_dict()
|
||||
assert "data" in ros2_dict
|
||||
assert ros2_dict["data"] == "Hello JSON Schema"
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="Missing dependencies")
|
||||
def test_float_array_to_json_schema(self):
|
||||
"""测试 Float64MultiArray 转 JSON Schema"""
|
||||
# 创建 Float64MultiArray 消息
|
||||
array_msg = Float64MultiArray()
|
||||
array_msg.data = [1.1, 2.2, 3.3, 4.4, 5.5]
|
||||
ros2_inst = ROS2MessageInstance(array_msg)
|
||||
|
||||
# 生成 JSON Schema
|
||||
schema = ros2_inst.get_json_schema()
|
||||
|
||||
# 验证数组字段的 Schema
|
||||
assert "data" in schema["properties"]
|
||||
data_prop = schema["properties"]["data"]
|
||||
assert data_prop["type"] == "array"
|
||||
assert "items" in data_prop
|
||||
assert data_prop["items"]["type"] == "number"
|
||||
|
||||
# 验证约束条件
|
||||
assert "minItems" in data_prop or "maxItems" in data_prop or data_prop["type"] == "array"
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="Missing dependencies")
|
||||
def test_pose_message_to_json_schema(self):
|
||||
"""测试复杂 Pose 消息转 JSON Schema"""
|
||||
# 创建 Pose 消息
|
||||
pose_msg = Pose()
|
||||
pose_msg.position.x = 1.0
|
||||
pose_msg.position.y = 2.0
|
||||
pose_msg.position.z = 3.0
|
||||
pose_msg.orientation.w = 1.0
|
||||
ros2_inst = ROS2MessageInstance(pose_msg)
|
||||
|
||||
# 生成 JSON Schema
|
||||
schema = ros2_inst.get_json_schema()
|
||||
|
||||
# 验证嵌套对象结构
|
||||
properties = schema["properties"]
|
||||
assert "position" in properties
|
||||
assert "orientation" in properties
|
||||
|
||||
# 验证对象类型
|
||||
position_prop = properties["position"]
|
||||
assert position_prop["type"] == "object"
|
||||
|
||||
orientation_prop = properties["orientation"]
|
||||
assert orientation_prop["type"] == "object"
|
||||
|
||||
|
||||
class TestROS2ToJSONSchemaInstanceConversion:
|
||||
"""ROS2 转 JSONSchemaMessageInstance 转换测试"""
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="Missing dependencies")
|
||||
def test_ros2_to_json_schema_instance_string(self):
|
||||
"""测试 ROS2 String 转 JSONSchemaMessageInstance"""
|
||||
# 创建 ROS2 实例
|
||||
string_msg = String()
|
||||
string_msg.data = "Test conversion"
|
||||
ros2_inst = ROS2MessageInstance(string_msg)
|
||||
|
||||
# 转换为 JSONSchemaMessageInstance
|
||||
json_schema_inst = ros2_inst.to_json_schema()
|
||||
|
||||
# 验证转换结果
|
||||
assert isinstance(json_schema_inst, JSONSchemaMessageInstance)
|
||||
assert json_schema_inst.message_type == MessageType.JSON_SCHEMA
|
||||
|
||||
# 验证数据一致性
|
||||
original_data = ros2_inst.get_python_dict()
|
||||
converted_data = json_schema_inst.get_python_dict()
|
||||
assert original_data == converted_data
|
||||
|
||||
# 验证 Schema 存在
|
||||
schema = json_schema_inst.json_schema
|
||||
assert schema is not None
|
||||
assert schema["type"] == "object"
|
||||
assert "properties" in schema
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="Missing dependencies")
|
||||
def test_ros2_to_json_schema_instance_array(self):
|
||||
"""测试 ROS2 数组转 JSONSchemaMessageInstance"""
|
||||
# 创建 ROS2 数组实例
|
||||
array_msg = Float64MultiArray()
|
||||
array_msg.data = [10.5, 20.3, 30.7]
|
||||
ros2_inst = ROS2MessageInstance(array_msg)
|
||||
|
||||
# 转换为 JSONSchemaMessageInstance
|
||||
json_schema_inst = ros2_inst.to_json_schema()
|
||||
|
||||
# 验证转换结果
|
||||
assert isinstance(json_schema_inst, JSONSchemaMessageInstance)
|
||||
|
||||
# 验证数据一致性
|
||||
original_data = ros2_inst.get_python_dict()
|
||||
converted_data = json_schema_inst.get_python_dict()
|
||||
assert original_data == converted_data
|
||||
assert converted_data["data"] == [10.5, 20.3, 30.7]
|
||||
|
||||
# 验证 Schema 的数组类型
|
||||
schema = json_schema_inst.json_schema
|
||||
if "data" in schema["properties"]:
|
||||
data_prop = schema["properties"]["data"]
|
||||
assert data_prop["type"] == "array"
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="Missing dependencies")
|
||||
def test_ros2_to_json_schema_instance_pose(self):
|
||||
"""测试 ROS2 Pose 转 JSONSchemaMessageInstance"""
|
||||
# 创建复杂的 Pose 消息
|
||||
pose_msg = Pose()
|
||||
pose_msg.position.x = 5.0
|
||||
pose_msg.position.y = 10.0
|
||||
pose_msg.position.z = 15.0
|
||||
pose_msg.orientation.x = 0.0
|
||||
pose_msg.orientation.y = 0.0
|
||||
pose_msg.orientation.z = 0.0
|
||||
pose_msg.orientation.w = 1.0
|
||||
ros2_inst = ROS2MessageInstance(pose_msg)
|
||||
|
||||
# 转换为 JSONSchemaMessageInstance
|
||||
json_schema_inst = ros2_inst.to_json_schema()
|
||||
|
||||
# 验证转换结果
|
||||
assert isinstance(json_schema_inst, JSONSchemaMessageInstance)
|
||||
|
||||
# 验证嵌套数据一致性
|
||||
original_data = ros2_inst.get_python_dict()
|
||||
converted_data = json_schema_inst.get_python_dict()
|
||||
assert original_data == converted_data
|
||||
|
||||
# 验证嵌套结构
|
||||
assert "position" in converted_data
|
||||
assert "orientation" in converted_data
|
||||
assert converted_data["position"]["x"] == 5.0
|
||||
assert converted_data["position"]["y"] == 10.0
|
||||
assert converted_data["position"]["z"] == 15.0
|
||||
|
||||
|
||||
class TestConversionConsistency:
|
||||
"""转换一致性测试"""
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="Missing dependencies")
|
||||
def test_schema_data_consistency(self):
|
||||
"""测试 Schema 与数据的一致性"""
|
||||
# 创建多种类型的数据
|
||||
test_cases = []
|
||||
|
||||
# String 消息
|
||||
string_msg = String()
|
||||
string_msg.data = "consistency_test"
|
||||
test_cases.append(("String", ROS2MessageInstance(string_msg)))
|
||||
|
||||
# Float64MultiArray 消息
|
||||
array_msg = Float64MultiArray()
|
||||
array_msg.data = [1.0, 2.0, 3.0]
|
||||
test_cases.append(("Float64MultiArray", ROS2MessageInstance(array_msg)))
|
||||
|
||||
for test_name, ros2_inst in test_cases:
|
||||
# 生成 Schema
|
||||
schema = ros2_inst.get_json_schema()
|
||||
original_data = ros2_inst.get_python_dict()
|
||||
|
||||
# 验证 Schema 属性与数据字段一致
|
||||
schema_props = set(schema["properties"].keys())
|
||||
data_keys = set(original_data.keys())
|
||||
|
||||
assert schema_props == data_keys, f"{test_name}: Schema properties and data keys don't match"
|
||||
|
||||
# 验证每个字段的类型一致性
|
||||
for field_name, field_value in original_data.items():
|
||||
if field_name in schema["properties"]:
|
||||
prop_schema = schema["properties"][field_name]
|
||||
|
||||
# 基本类型检查
|
||||
if isinstance(field_value, str):
|
||||
assert prop_schema["type"] == "string", f"{test_name}.{field_name}: Type mismatch"
|
||||
elif isinstance(field_value, bool):
|
||||
assert prop_schema["type"] == "boolean", f"{test_name}.{field_name}: Type mismatch"
|
||||
elif isinstance(field_value, int):
|
||||
assert prop_schema["type"] == "integer", f"{test_name}.{field_name}: Type mismatch"
|
||||
elif isinstance(field_value, float):
|
||||
assert prop_schema["type"] == "number", f"{test_name}.{field_name}: Type mismatch"
|
||||
elif isinstance(field_value, list):
|
||||
assert prop_schema["type"] == "array", f"{test_name}.{field_name}: Type mismatch"
|
||||
elif isinstance(field_value, dict):
|
||||
assert prop_schema["type"] == "object", f"{test_name}.{field_name}: Type mismatch"
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="Missing dependencies")
|
||||
def test_conversion_roundtrip_data(self):
|
||||
"""测试转换往返的数据一致性"""
|
||||
# 创建原始 ROS2 消息
|
||||
string_msg = String()
|
||||
string_msg.data = "roundtrip_test"
|
||||
original_ros2_inst = ROS2MessageInstance(string_msg)
|
||||
original_data = original_ros2_inst.get_python_dict()
|
||||
|
||||
# ROS2 -> JSONSchema
|
||||
json_schema_inst = original_ros2_inst.to_json_schema()
|
||||
converted_data = json_schema_inst.get_python_dict()
|
||||
|
||||
# 验证数据在转换过程中保持一致
|
||||
assert original_data == converted_data
|
||||
|
||||
# 验证 Schema 的有效性
|
||||
schema = json_schema_inst.json_schema
|
||||
assert schema is not None
|
||||
|
||||
# 使用 jsonschema 库验证数据符合生成的 Schema
|
||||
try:
|
||||
jsonschema.validate(converted_data, schema)
|
||||
except jsonschema.ValidationError as e:
|
||||
pytest.fail(f"Generated data doesn't match generated schema: {e}")
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="Missing dependencies")
|
||||
def test_multiple_message_types_conversion(self):
|
||||
"""测试多种消息类型的转换"""
|
||||
test_messages = []
|
||||
|
||||
# String
|
||||
string_msg = String()
|
||||
string_msg.data = "multi_test_string"
|
||||
test_messages.append(("String", string_msg))
|
||||
|
||||
# Float64MultiArray
|
||||
array_msg = Float64MultiArray()
|
||||
array_msg.data = [1.5, 2.5, 3.5]
|
||||
test_messages.append(("Float64MultiArray", array_msg))
|
||||
|
||||
# Point
|
||||
point_msg = Point()
|
||||
point_msg.x = 1.0
|
||||
point_msg.y = 2.0
|
||||
point_msg.z = 3.0
|
||||
test_messages.append(("Point", point_msg))
|
||||
|
||||
for msg_type_name, msg in test_messages:
|
||||
# 创建 ROS2 实例
|
||||
ros2_inst = ROS2MessageInstance(msg)
|
||||
|
||||
# 转换为 JSONSchema 实例
|
||||
json_schema_inst = ros2_inst.to_json_schema()
|
||||
|
||||
# 验证转换成功
|
||||
assert isinstance(json_schema_inst, JSONSchemaMessageInstance)
|
||||
assert json_schema_inst.message_type == MessageType.JSON_SCHEMA
|
||||
|
||||
# 验证数据一致性
|
||||
original_data = ros2_inst.get_python_dict()
|
||||
converted_data = json_schema_inst.get_python_dict()
|
||||
assert original_data == converted_data, f"{msg_type_name}: Data inconsistency after conversion"
|
||||
|
||||
# 验证 Schema 生成
|
||||
schema = json_schema_inst.json_schema
|
||||
assert schema is not None
|
||||
assert schema["type"] == "object"
|
||||
assert len(schema["properties"]) > 0, f"{msg_type_name}: No properties in generated schema"
|
||||
|
||||
|
||||
class TestConversionErrorHandling:
|
||||
"""转换错误处理测试"""
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="Missing dependencies")
|
||||
def test_empty_message_conversion(self):
|
||||
"""测试空消息的转换"""
|
||||
# 创建空的 String 消息
|
||||
empty_string = String()
|
||||
ros2_inst = ROS2MessageInstance(empty_string)
|
||||
|
||||
# 转换应该成功,即使数据为空
|
||||
json_schema_inst = ros2_inst.to_json_schema()
|
||||
|
||||
assert isinstance(json_schema_inst, JSONSchemaMessageInstance)
|
||||
|
||||
# 验证 Schema 仍然有效
|
||||
schema = json_schema_inst.json_schema
|
||||
assert schema["type"] == "object"
|
||||
assert "properties" in schema
|
||||
|
||||
@pytest.mark.skipif(not HAS_ROS2, reason="Missing dependencies")
|
||||
def test_large_data_conversion(self):
|
||||
"""测试大数据量的转换"""
|
||||
# 创建包含大量数据的数组消息
|
||||
large_array = Float64MultiArray()
|
||||
large_array.data = [float(i) for i in range(1000)] # 1000 个浮点数
|
||||
ros2_inst = ROS2MessageInstance(large_array)
|
||||
|
||||
# 转换应该能处理大数据量
|
||||
json_schema_inst = ros2_inst.to_json_schema()
|
||||
|
||||
assert isinstance(json_schema_inst, JSONSchemaMessageInstance)
|
||||
|
||||
# 验证数据完整性
|
||||
original_data = ros2_inst.get_python_dict()
|
||||
converted_data = json_schema_inst.get_python_dict()
|
||||
assert len(original_data["data"]) == 1000
|
||||
assert len(converted_data["data"]) == 1000
|
||||
assert original_data == converted_data
|
||||
|
||||
|
||||
# 运行测试的便捷函数
|
||||
def run_conversion_tests():
|
||||
"""运行转换测试"""
|
||||
if not HAS_ROS2:
|
||||
print("❌ Required dependencies not available, skipping tests")
|
||||
print(f" ROS2: {HAS_ROS2}")
|
||||
return False
|
||||
|
||||
import subprocess
|
||||
|
||||
result = subprocess.run(
|
||||
[
|
||||
"python",
|
||||
"-m",
|
||||
"pytest",
|
||||
"tests/test_ros_to_json_schema_conversion.py",
|
||||
"-v",
|
||||
"--tb=short",
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
|
||||
print(result.stdout)
|
||||
if result.stderr:
|
||||
print("STDERR:", result.stderr)
|
||||
|
||||
return result.returncode == 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 直接运行测试
|
||||
run_conversion_tests()
|
||||
Reference in New Issue
Block a user