initial commit
This commit is contained in:
383
tests/test_validation.py
Normal file
383
tests/test_validation.py
Normal file
@ -0,0 +1,383 @@
|
||||
"""
|
||||
Tests for parameter validation module.
|
||||
|
||||
Testing validation of all input parameters with boundary conditions,
|
||||
invalid types, and edge cases.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import math
|
||||
from laser_control.validators import ParameterValidator
|
||||
from laser_control.exceptions import (
|
||||
ValidationError,
|
||||
TemperatureOutOfRangeError,
|
||||
CurrentOutOfRangeError,
|
||||
InvalidParameterError
|
||||
)
|
||||
from laser_control.models import VariationType
|
||||
|
||||
|
||||
class TestTemperatureValidation:
|
||||
"""Test temperature parameter validation."""
|
||||
|
||||
def test_valid_temperature_range(self):
|
||||
"""Test temperatures within valid range."""
|
||||
# Valid temperatures should pass
|
||||
assert ParameterValidator.validate_temperature(15.0, "temp1") == 15.0
|
||||
assert ParameterValidator.validate_temperature(25.5, "temp2") == 25.5
|
||||
assert ParameterValidator.validate_temperature(40.0, "temp1") == 40.0
|
||||
|
||||
def test_temperature_below_minimum(self):
|
||||
"""Test temperature below minimum threshold."""
|
||||
with pytest.raises(TemperatureOutOfRangeError) as exc_info:
|
||||
ParameterValidator.validate_temperature(10.0, "temp1")
|
||||
assert "temp1" in str(exc_info.value)
|
||||
assert "15.0" in str(exc_info.value) # min value
|
||||
|
||||
def test_temperature_above_maximum(self):
|
||||
"""Test temperature above maximum threshold."""
|
||||
with pytest.raises(TemperatureOutOfRangeError) as exc_info:
|
||||
ParameterValidator.validate_temperature(45.0, "temp2")
|
||||
assert "temp2" in str(exc_info.value)
|
||||
assert "40.0" in str(exc_info.value) # max value
|
||||
|
||||
def test_temperature_invalid_type(self):
|
||||
"""Test invalid temperature type."""
|
||||
with pytest.raises(InvalidParameterError) as exc_info:
|
||||
ParameterValidator.validate_temperature("invalid", "temp1")
|
||||
assert "temp1" in str(exc_info.value)
|
||||
assert "number" in str(exc_info.value).lower()
|
||||
|
||||
def test_temperature_nan_value(self):
|
||||
"""Test NaN temperature value."""
|
||||
with pytest.raises(InvalidParameterError) as exc_info:
|
||||
ParameterValidator.validate_temperature(float('nan'), "temp1")
|
||||
assert "NaN" in str(exc_info.value)
|
||||
|
||||
def test_temperature_inf_value(self):
|
||||
"""Test infinite temperature value."""
|
||||
with pytest.raises(InvalidParameterError) as exc_info:
|
||||
ParameterValidator.validate_temperature(float('inf'), "temp2")
|
||||
assert "infinite" in str(exc_info.value).lower()
|
||||
|
||||
def test_temperature_none_value(self):
|
||||
"""Test None temperature value."""
|
||||
with pytest.raises(InvalidParameterError) as exc_info:
|
||||
ParameterValidator.validate_temperature(None, "temp1")
|
||||
assert "temp1" in str(exc_info.value)
|
||||
|
||||
|
||||
class TestCurrentValidation:
|
||||
"""Test current parameter validation."""
|
||||
|
||||
def test_valid_current_range(self):
|
||||
"""Test currents within valid range."""
|
||||
assert ParameterValidator.validate_current(15.0, "current1") == 15.0
|
||||
assert ParameterValidator.validate_current(37.5, "current2") == 37.5
|
||||
assert ParameterValidator.validate_current(60.0, "current1") == 60.0
|
||||
|
||||
def test_current_below_minimum(self):
|
||||
"""Test current below minimum threshold."""
|
||||
with pytest.raises(CurrentOutOfRangeError) as exc_info:
|
||||
ParameterValidator.validate_current(10.0, "current1")
|
||||
assert "current1" in str(exc_info.value)
|
||||
assert "15.0" in str(exc_info.value) # min value
|
||||
|
||||
def test_current_above_maximum(self):
|
||||
"""Test current above maximum threshold."""
|
||||
with pytest.raises(CurrentOutOfRangeError) as exc_info:
|
||||
ParameterValidator.validate_current(65.0, "current2")
|
||||
assert "current2" in str(exc_info.value)
|
||||
assert "60.0" in str(exc_info.value) # max value
|
||||
|
||||
def test_current_invalid_type(self):
|
||||
"""Test invalid current type."""
|
||||
with pytest.raises(InvalidParameterError) as exc_info:
|
||||
ParameterValidator.validate_current([15, 20], "current1")
|
||||
assert "current1" in str(exc_info.value)
|
||||
|
||||
def test_current_negative_value(self):
|
||||
"""Test negative current value."""
|
||||
with pytest.raises(CurrentOutOfRangeError) as exc_info:
|
||||
ParameterValidator.validate_current(-5.0, "current1")
|
||||
assert "current1" in str(exc_info.value)
|
||||
|
||||
|
||||
class TestVariationParameterValidation:
|
||||
"""Test variation mode parameter validation."""
|
||||
|
||||
def test_valid_current_variation_params(self):
|
||||
"""Test valid parameters for current variation."""
|
||||
params = {
|
||||
'min_value': 20.0,
|
||||
'max_value': 50.0,
|
||||
'step': 0.5,
|
||||
'time_step': 50, # microseconds
|
||||
'delay_time': 5 # milliseconds
|
||||
}
|
||||
validated = ParameterValidator.validate_variation_params(
|
||||
params,
|
||||
VariationType.CHANGE_CURRENT_LD1
|
||||
)
|
||||
assert validated['min_value'] == 20.0
|
||||
assert validated['max_value'] == 50.0
|
||||
assert validated['step'] == 0.5
|
||||
|
||||
def test_variation_min_greater_than_max(self):
|
||||
"""Test min value greater than max value."""
|
||||
params = {
|
||||
'min_value': 50.0,
|
||||
'max_value': 20.0,
|
||||
'step': 0.5,
|
||||
'time_step': 50,
|
||||
'delay_time': 5
|
||||
}
|
||||
with pytest.raises(ValidationError) as exc_info:
|
||||
ParameterValidator.validate_variation_params(
|
||||
params,
|
||||
VariationType.CHANGE_CURRENT_LD1
|
||||
)
|
||||
assert "min" in str(exc_info.value).lower()
|
||||
assert "max" in str(exc_info.value).lower()
|
||||
|
||||
def test_variation_invalid_step(self):
|
||||
"""Test invalid step values."""
|
||||
# Zero step
|
||||
params = {
|
||||
'min_value': 20.0,
|
||||
'max_value': 50.0,
|
||||
'step': 0,
|
||||
'time_step': 50,
|
||||
'delay_time': 5
|
||||
}
|
||||
with pytest.raises(ValidationError) as exc_info:
|
||||
ParameterValidator.validate_variation_params(
|
||||
params,
|
||||
VariationType.CHANGE_CURRENT_LD1
|
||||
)
|
||||
assert "step" in str(exc_info.value).lower()
|
||||
|
||||
# Negative step
|
||||
params['step'] = -0.5
|
||||
with pytest.raises(ValidationError) as exc_info:
|
||||
ParameterValidator.validate_variation_params(
|
||||
params,
|
||||
VariationType.CHANGE_CURRENT_LD1
|
||||
)
|
||||
assert "step" in str(exc_info.value).lower()
|
||||
|
||||
def test_variation_step_too_small(self):
|
||||
"""Test step value too small for current."""
|
||||
params = {
|
||||
'min_value': 20.0,
|
||||
'max_value': 50.0,
|
||||
'step': 0.001, # Too small for current (min 0.002)
|
||||
'time_step': 50,
|
||||
'delay_time': 5
|
||||
}
|
||||
with pytest.raises(ValidationError) as exc_info:
|
||||
ParameterValidator.validate_variation_params(
|
||||
params,
|
||||
VariationType.CHANGE_CURRENT_LD2
|
||||
)
|
||||
assert "step" in str(exc_info.value).lower()
|
||||
assert "0.002" in str(exc_info.value)
|
||||
|
||||
def test_variation_step_too_large(self):
|
||||
"""Test step value too large."""
|
||||
params = {
|
||||
'min_value': 20.0,
|
||||
'max_value': 50.0,
|
||||
'step': 10.0, # Too large for current (max 0.5)
|
||||
'time_step': 50,
|
||||
'delay_time': 5
|
||||
}
|
||||
with pytest.raises(ValidationError) as exc_info:
|
||||
ParameterValidator.validate_variation_params(
|
||||
params,
|
||||
VariationType.CHANGE_CURRENT_LD1
|
||||
)
|
||||
assert "step" in str(exc_info.value).lower()
|
||||
assert "0.5" in str(exc_info.value)
|
||||
|
||||
def test_valid_temperature_variation_params(self):
|
||||
"""Test valid parameters for temperature variation."""
|
||||
params = {
|
||||
'min_value': 20.0,
|
||||
'max_value': 35.0,
|
||||
'step': 0.1,
|
||||
'time_step': 50,
|
||||
'delay_time': 5
|
||||
}
|
||||
validated = ParameterValidator.validate_variation_params(
|
||||
params,
|
||||
VariationType.CHANGE_TEMPERATURE_LD1
|
||||
)
|
||||
assert validated['min_value'] == 20.0
|
||||
assert validated['max_value'] == 35.0
|
||||
assert validated['step'] == 0.1
|
||||
|
||||
def test_temperature_variation_step_bounds(self):
|
||||
"""Test temperature variation step boundaries."""
|
||||
params = {
|
||||
'min_value': 20.0,
|
||||
'max_value': 35.0,
|
||||
'step': 0.02, # Too small (min 0.05)
|
||||
'time_step': 50,
|
||||
'delay_time': 5
|
||||
}
|
||||
with pytest.raises(ValidationError) as exc_info:
|
||||
ParameterValidator.validate_variation_params(
|
||||
params,
|
||||
VariationType.CHANGE_TEMPERATURE_LD2
|
||||
)
|
||||
assert "0.05" in str(exc_info.value)
|
||||
|
||||
params['step'] = 2.0 # Too large (max 1.0)
|
||||
with pytest.raises(ValidationError) as exc_info:
|
||||
ParameterValidator.validate_variation_params(
|
||||
params,
|
||||
VariationType.CHANGE_TEMPERATURE_LD1
|
||||
)
|
||||
assert "1.0" in str(exc_info.value)
|
||||
|
||||
def test_missing_required_params(self):
|
||||
"""Test missing required parameters."""
|
||||
params = {
|
||||
'min_value': 20.0,
|
||||
'max_value': 50.0
|
||||
# Missing step, time_step, delay_time
|
||||
}
|
||||
with pytest.raises(ValidationError) as exc_info:
|
||||
ParameterValidator.validate_variation_params(
|
||||
params,
|
||||
VariationType.CHANGE_CURRENT_LD1
|
||||
)
|
||||
assert "required" in str(exc_info.value).lower()
|
||||
|
||||
def test_invalid_variation_type(self):
|
||||
"""Test invalid variation type."""
|
||||
params = {
|
||||
'min_value': 20.0,
|
||||
'max_value': 50.0,
|
||||
'step': 0.5,
|
||||
'time_step': 50,
|
||||
'delay_time': 5
|
||||
}
|
||||
with pytest.raises(ValidationError) as exc_info:
|
||||
ParameterValidator.validate_variation_params(
|
||||
params,
|
||||
"INVALID_TYPE"
|
||||
)
|
||||
assert "variation type" in str(exc_info.value).lower()
|
||||
|
||||
|
||||
class TestTimeParameterValidation:
|
||||
"""Test time parameter validation."""
|
||||
|
||||
def test_valid_time_params(self):
|
||||
"""Test valid time parameters."""
|
||||
step_time, delay_time = ParameterValidator.validate_time_params(50, 5)
|
||||
assert step_time == 50
|
||||
assert delay_time == 5
|
||||
|
||||
step_time, delay_time = ParameterValidator.validate_time_params(20, 3)
|
||||
assert step_time == 20
|
||||
assert delay_time == 3
|
||||
|
||||
step_time, delay_time = ParameterValidator.validate_time_params(100, 10)
|
||||
assert step_time == 100
|
||||
assert delay_time == 10
|
||||
|
||||
def test_time_step_below_minimum(self):
|
||||
"""Test time step below minimum."""
|
||||
with pytest.raises(ValidationError) as exc_info:
|
||||
ParameterValidator.validate_time_params(10, 5) # Min is 20
|
||||
assert "time step" in str(exc_info.value).lower()
|
||||
assert "20" in str(exc_info.value)
|
||||
|
||||
def test_time_step_above_maximum(self):
|
||||
"""Test time step above maximum."""
|
||||
with pytest.raises(ValidationError) as exc_info:
|
||||
ParameterValidator.validate_time_params(150, 5) # Max is 100
|
||||
assert "time step" in str(exc_info.value).lower()
|
||||
assert "100" in str(exc_info.value)
|
||||
|
||||
def test_delay_time_below_minimum(self):
|
||||
"""Test delay time below minimum."""
|
||||
with pytest.raises(ValidationError) as exc_info:
|
||||
ParameterValidator.validate_time_params(50, 1) # Min is 3
|
||||
assert "delay" in str(exc_info.value).lower()
|
||||
assert "3" in str(exc_info.value)
|
||||
|
||||
def test_delay_time_above_maximum(self):
|
||||
"""Test delay time above maximum."""
|
||||
with pytest.raises(ValidationError) as exc_info:
|
||||
ParameterValidator.validate_time_params(50, 15) # Max is 10
|
||||
assert "delay" in str(exc_info.value).lower()
|
||||
assert "10" in str(exc_info.value)
|
||||
|
||||
def test_time_params_invalid_type(self):
|
||||
"""Test invalid type for time parameters."""
|
||||
with pytest.raises(InvalidParameterError):
|
||||
ParameterValidator.validate_time_params("50", 5)
|
||||
|
||||
with pytest.raises(InvalidParameterError):
|
||||
ParameterValidator.validate_time_params(50, [5])
|
||||
|
||||
def test_time_params_float_conversion(self):
|
||||
"""Test float to int conversion for time parameters."""
|
||||
step_time, delay_time = ParameterValidator.validate_time_params(50.7, 5.2)
|
||||
assert step_time == 50 # Should be truncated to int
|
||||
assert delay_time == 5
|
||||
|
||||
|
||||
class TestManualModeValidation:
|
||||
"""Test manual mode parameter validation."""
|
||||
|
||||
def test_validate_all_manual_params(self):
|
||||
"""Test validation of all manual mode parameters at once."""
|
||||
result = ParameterValidator.validate_manual_mode_params(
|
||||
temp1=25.0,
|
||||
temp2=30.0,
|
||||
current1=40.0,
|
||||
current2=35.0
|
||||
)
|
||||
assert result['temp1'] == 25.0
|
||||
assert result['temp2'] == 30.0
|
||||
assert result['current1'] == 40.0
|
||||
assert result['current2'] == 35.0
|
||||
|
||||
def test_manual_mode_invalid_combination(self):
|
||||
"""Test invalid parameter combinations in manual mode."""
|
||||
# One invalid parameter should fail all validation
|
||||
with pytest.raises(ValidationError):
|
||||
ParameterValidator.validate_manual_mode_params(
|
||||
temp1=25.0,
|
||||
temp2=30.0,
|
||||
current1=70.0, # Too high
|
||||
current2=35.0
|
||||
)
|
||||
|
||||
def test_manual_mode_boundary_values(self):
|
||||
"""Test boundary values for manual mode."""
|
||||
# All minimum values
|
||||
result = ParameterValidator.validate_manual_mode_params(
|
||||
temp1=15.0,
|
||||
temp2=15.0,
|
||||
current1=15.0,
|
||||
current2=15.0
|
||||
)
|
||||
assert all(v in [15.0] for v in result.values())
|
||||
|
||||
# All maximum values
|
||||
result = ParameterValidator.validate_manual_mode_params(
|
||||
temp1=40.0,
|
||||
temp2=40.0,
|
||||
current1=60.0,
|
||||
current2=60.0
|
||||
)
|
||||
assert result['temp1'] == 40.0
|
||||
assert result['temp2'] == 40.0
|
||||
assert result['current1'] == 60.0
|
||||
assert result['current2'] == 60.0
|
||||
Reference in New Issue
Block a user