Skip to content

Commit ce1c715

Browse files
author
Tom Softreck
committed
update
1 parent badde11 commit ce1c715

File tree

3 files changed

+108
-65
lines changed

3 files changed

+108
-65
lines changed

tests/unit/test_config_module.py

Lines changed: 47 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -74,38 +74,40 @@ def test_resolve_env_vars(self):
7474
"DB_PORT": "5432"
7575
}
7676

77-
# Test with direct variable
77+
# Test with direct variable using Jinja2 syntax
7878
result = resolver.resolve_env_vars(
79-
"postgresql://${DB_HOST}:${DB_PORT}/mydb",
79+
"postgresql://{{DB_HOST}}:{{DB_PORT}}/mydb",
8080
env_vars
8181
)
8282
assert result == "postgresql://localhost:5432/mydb"
8383

84-
# Test with default value
84+
# Test with direct variable using ${} syntax
8585
result = resolver.resolve_env_vars(
86-
"postgresql://${DB_HOST:127.0.0.1}:${DB_PORT:5432}/mydb",
87-
{}
86+
"postgresql://${DB_HOST}:${DB_PORT}/mydb",
87+
env_vars
8888
)
89-
assert result == "postgresql://127.0.0.1:5432/mydb"
89+
assert result == "postgresql://localhost:5432/mydb"
9090

9191
def test_check_required_env_vars(self):
9292
"""Test required environment variable validation."""
9393
resolver = ConfigResolver()
9494

95-
# Test with all required vars present
96-
env_vars = {
97-
"REQUIRED_VAR_1": "value1",
98-
"REQUIRED_VAR_2": "value2"
99-
}
100-
resolver.check_required_env_vars(["REQUIRED_VAR_1", "REQUIRED_VAR_2"], env_vars)
95+
# Set up environment variables
96+
os.environ["REQUIRED_VAR_1"] = "value1"
97+
os.environ["REQUIRED_VAR_2"] = "value2"
10198

102-
# Test with missing required var
103-
with pytest.raises(ValueError) as exc_info:
104-
resolver.check_required_env_vars(
105-
["REQUIRED_VAR_1", "MISSING_VAR"],
106-
env_vars
107-
)
108-
assert "Missing required environment variable: MISSING_VAR" in str(exc_info.value)
99+
try:
100+
# Test with all required vars present
101+
missing = resolver.check_required_env_vars(["REQUIRED_VAR_1", "REQUIRED_VAR_2"])
102+
assert missing == [], "Expected no missing variables"
103+
104+
# Test with missing required var
105+
missing = resolver.check_required_env_vars(["REQUIRED_VAR_1", "MISSING_VAR"])
106+
assert missing == ["MISSING_VAR"], "Expected MISSING_VAR to be missing"
107+
finally:
108+
# Clean up
109+
os.environ.pop("REQUIRED_VAR_1", None)
110+
os.environ.pop("REQUIRED_VAR_2", None)
109111

110112

111113
class TestConfigValidator:
@@ -114,41 +116,48 @@ class TestConfigValidator:
114116
def test_validate_uri(self):
115117
"""Test URI validation."""
116118
# Test valid RTSP URI
117-
assert ConfigValidator.validate_uri("rtsp://camera1:554/stream", "sources") is None
119+
errors = ConfigValidator.validate_uri("rtsp://camera1:554/stream", "sources")
120+
assert not errors, f"Expected no errors, got: {errors}"
118121

119122
# Test invalid scheme
120-
with pytest.raises(ValueError) as exc_info:
121-
ConfigValidator.validate_uri("invalid://test", "sources")
122-
assert "Unsupported scheme 'invalid' for source" in str(exc_info.value)
123+
errors = ConfigValidator.validate_uri("invalid://test", "sources")
124+
assert any("Unsupported scheme 'invalid' for sources" in e for e in errors), \
125+
f"Expected unsupported scheme error, got: {errors}"
123126

124127
# Test invalid destination
125-
with pytest.raises(ValueError) as exc_info:
126-
ConfigValidator.validate_uri("rtsp://test", "destinations")
127-
assert "Unsupported scheme 'rtsp' for destination" in str(exc_info.value)
128+
errors = ConfigValidator.validate_uri("rtsp://test", "destinations")
129+
assert any("Unsupported scheme 'rtsp' for destinations" in e for e in errors), \
130+
f"Expected unsupported scheme error for destination, got: {errors}"
128131

129132
def test_validate_processor(self):
130133
"""Test processor configuration validation."""
131134
# Test valid processor
132135
valid_processor = {
133136
"type": "filter",
134-
"config": {"min_confidence": 0.5}
137+
"condition": "some_condition"
135138
}
136-
assert ConfigValidator.validate_processor(valid_processor) is None
139+
errors = ConfigValidator.validate_processor(valid_processor)
140+
assert not errors, f"Expected no errors, got: {errors}"
137141

138142
# Test missing type
139-
with pytest.raises(ValueError) as exc_info:
140-
ConfigValidator.validate_processor({"config": {}})
141-
assert "Processor config missing 'type' field" in str(exc_info.value)
143+
errors = ConfigValidator.validate_processor({"config": {}})
144+
assert any("Unsupported processor type 'None'" in e for e in errors), \
145+
f"Expected missing type error, got: {errors}"
142146

143147
# Test invalid type
144-
with pytest.raises(ValueError) as exc_info:
145-
ConfigValidator.validate_processor({"type": "invalid"})
146-
assert "Unsupported processor type: invalid" in str(exc_info.value)
148+
errors = ConfigValidator.validate_processor({"type": "invalid"})
149+
assert any("Unsupported processor type 'invalid'" in e for e in errors), \
150+
f"Expected unsupported type error, got: {errors}"
147151

148-
# Test missing config
149-
with pytest.raises(ValueError) as exc_info:
150-
ConfigValidator.validate_processor({"type": "filter"})
151-
assert "Processor config missing 'config' field" in str(exc_info.value)
152+
# Test missing required fields for filter type
153+
errors = ConfigValidator.validate_processor({"type": "filter"})
154+
assert any("Filter processor requires 'condition' field" in e for e in errors), \
155+
f"Expected missing condition error, got: {errors}"
156+
157+
# Test external processor validation
158+
errors = ConfigValidator.validate_processor({"type": "external"})
159+
assert any("External processor requires 'command' field" in e for e in errors), \
160+
f"Expected missing command error, got: {errors}"
152161

153162

154163
def test_config_loading_from_file(tmp_path):

tests/unit/test_connectors.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,23 @@ async def test_rtsp_source_receive(self):
4040
"""Test RTSP source receive method."""
4141
with patch('cv2.VideoCapture') as mock_capture:
4242
# Setup mock
43-
mock_capture.return_value.isOpened.return_value = True
44-
mock_capture.return_value.grab.return_value = True
45-
mock_capture.return_value.retrieve.return_value = (True, "frame_data")
43+
mock_cap = mock_capture.return_value
44+
mock_cap.isOpened.return_value = True
45+
mock_cap.read.return_value = (True, "frame_data")
4646

4747
source = connectors.RTSPSource("rtsp://test")
4848
source.reconnect_attempts = 1 # Limit reconnect attempts for test
4949

5050
# Test receive generator
51+
count = 0
5152
async for frame in source.receive():
52-
assert frame == {"frame": "frame_data", "metadata": {}}
53-
break # Just test one iteration
53+
assert frame["type"] == "camera_frame"
54+
assert "timestamp" in frame
55+
assert frame["frame"] == "frame_data"
56+
assert frame["source"] == "rtsp://test"
57+
count += 1
58+
if count >= 1: # Just test one iteration
59+
break
5460

5561

5662
class TestHTTPDestination:

tests/unit/test_connectors_destinations.py

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ def email_dest(self):
3535
@pytest.mark.asyncio
3636
async def test_send_email(self, email_dest):
3737
"""Test sending an email."""
38-
mock_smtp = MagicMock()
39-
mock_server = MagicMock()
40-
mock_smtp.return_value = mock_server
41-
42-
with patch('smtplib.SMTP', mock_smtp):
38+
with patch('smtplib.SMTP') as mock_smtp:
39+
mock_server = MagicMock()
40+
mock_smtp.return_value = mock_server
41+
42+
# Test with string message
4343
await email_dest.send("Test email content")
4444

4545
# Verify SMTP connection and login
@@ -52,6 +52,16 @@ async def test_send_email(self, email_dest):
5252
assert msg['From'] == 'test@example.com'
5353
assert msg['To'] == 'recipient@example.com'
5454
assert 'Test email content' in msg.as_string()
55+
56+
# Test with dict message
57+
mock_smtp.reset_mock()
58+
mock_server.reset_mock()
59+
mock_smtp.return_value = mock_server
60+
61+
await email_dest.send({"subject": "Test Subject", "body": "Test Body"})
62+
msg = mock_server.send_message.call_args[0][0]
63+
assert 'Test Subject' in msg['Subject']
64+
assert 'Test Body' in msg.as_string()
5565

5666

5767
class TestHTTPDestination:
@@ -65,20 +75,30 @@ def http_dest(self):
6575
@pytest.mark.asyncio
6676
async def test_send_http_request(self, http_dest):
6777
"""Test sending an HTTP request."""
68-
mock_session = AsyncMock()
6978
mock_response = AsyncMock()
7079
mock_response.status = 200
71-
mock_session.post.return_value.__aenter__.return_value = mock_response
7280

73-
with patch('aiohttp.ClientSession', return_value=mock_session):
81+
with patch('aiohttp.ClientSession') as mock_session:
82+
mock_session.return_value.__aenter__.return_value.post.return_value.__aenter__.return_value = mock_response
83+
84+
# Test with dict message
7485
await http_dest.send({"key": "value"})
7586

7687
# Verify HTTP POST request was made
77-
mock_session.post.assert_awaited_once_with(
88+
mock_session.return_value.__aenter__.return_value.post.assert_awaited_once_with(
7889
'http://example.com/webhook',
7990
json={"key": "value"},
8091
headers={'Content-Type': 'application/json'}
8192
)
93+
94+
# Test with string message
95+
mock_session.return_value.__aenter__.return_value.post.reset_mock()
96+
await http_dest.send("test message")
97+
mock_session.return_value.__aenter__.return_value.post.assert_awaited_once_with(
98+
'http://example.com/webhook',
99+
json="test message",
100+
headers={'Content-Type': 'application/json'}
101+
)
82102

83103

84104
class TestMQTTDestination:
@@ -92,19 +112,27 @@ def mqtt_dest(self):
92112
@pytest.mark.asyncio
93113
async def test_send_mqtt_message(self, mqtt_dest):
94114
"""Test sending an MQTT message."""
95-
mock_client = AsyncMock()
96-
97-
with patch('paho.mqtt.client.Client', return_value=mock_client):
98-
# Mock the connect method to avoid actual connection
99-
with patch.object(mqtt_dest, 'connect', new_callable=AsyncMock) as mock_connect:
100-
await mqtt_dest.send("test message")
101-
102-
# Verify connection and message publishing
103-
mock_connect.assert_awaited_once()
104-
mock_client.publish.assert_called_once_with(
105-
'test/topic',
106-
'test message'
107-
)
115+
with patch('paho.mqtt.client.Client') as mock_client:
116+
mock_client.return_value.connect_sync = MagicMock()
117+
mock_client.return_value.publish = MagicMock()
118+
119+
# Test with string message
120+
await mqtt_dest.send("test message")
121+
122+
# Verify connection and message publishing
123+
mock_client.return_value.connect_sync.assert_called_once_with('broker.example.com', 1883, 60)
124+
mock_client.return_value.publish.assert_called_once_with(
125+
'test/topic',
126+
'test message'
127+
)
128+
129+
# Test with dict message
130+
mock_client.return_value.publish.reset_mock()
131+
await mqtt_dest.send({"key": "value"})
132+
mock_client.return_value.publish.assert_called_once_with(
133+
'test/topic',
134+
'{"key": "value"}'
135+
)
108136

109137

110138
class TestFileDestination:

0 commit comments

Comments
 (0)