File size: 13,056 Bytes
b216c95 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 |
"""
Unit tests for common.validators module
Tests all validation functions with various inputs and edge cases.
"""
import pytest
from pathlib import Path
from datetime import datetime
from tempfile import NamedTemporaryFile, TemporaryDirectory
from common import (
Validator,
ValidationException,
AudioFileException
)
class TestValidateAudioFile:
"""Test cases for validate_audio_file function"""
def test_validate_audio_file_with_empty_path(self):
"""Should raise ValidationException for empty path"""
with pytest.raises(ValidationException) as exc_info:
Validator.validate_audio_file("")
assert "audio_file" in str(exc_info.value)
def test_validate_audio_file_nonexistent(self):
"""Should raise AudioFileException for non-existent file"""
with pytest.raises(AudioFileException) as exc_info:
Validator.validate_audio_file("/nonexistent/path/to/audio.wav")
assert "does not exist" in str(exc_info.value)
def test_validate_audio_file_unsupported_format(self, tmp_path):
"""Should raise AudioFileException for unsupported file format"""
# Create a file with unsupported extension
unsupported_file = tmp_path / "audio.xyz"
unsupported_file.write_text("fake audio data")
with pytest.raises(AudioFileException) as exc_info:
Validator.validate_audio_file(str(unsupported_file))
assert "Unsupported format" in str(exc_info.value)
def test_validate_audio_file_empty_file(self, tmp_path):
"""Should raise AudioFileException for empty file"""
empty_file = tmp_path / "empty.wav"
empty_file.write_bytes(b"")
with pytest.raises(AudioFileException) as exc_info:
Validator.validate_audio_file(str(empty_file))
assert "empty" in str(exc_info.value).lower()
def test_validate_audio_file_valid_wav(self, tmp_path):
"""Should return Path object for valid WAV file"""
valid_file = tmp_path / "audio.wav"
valid_file.write_bytes(b"fake audio data")
result = Validator.validate_audio_file(str(valid_file))
assert isinstance(result, Path)
assert result.exists()
assert result.suffix.lower() == ".wav"
def test_validate_audio_file_valid_mp3(self, tmp_path):
"""Should return Path object for valid MP3 file"""
valid_file = tmp_path / "audio.mp3"
valid_file.write_bytes(b"fake audio data")
result = Validator.validate_audio_file(str(valid_file))
assert isinstance(result, Path)
assert result.suffix.lower() == ".mp3"
def test_validate_audio_file_valid_m4a(self, tmp_path):
"""Should return Path object for valid M4A file"""
valid_file = tmp_path / "audio.m4a"
valid_file.write_bytes(b"fake audio data")
result = Validator.validate_audio_file(str(valid_file))
assert isinstance(result, Path)
assert result.suffix.lower() == ".m4a"
def test_validate_audio_file_is_directory(self, tmp_path):
"""Should raise AudioFileException if path is directory, not file"""
with pytest.raises(AudioFileException) as exc_info:
Validator.validate_audio_file(str(tmp_path))
assert "not a file" in str(exc_info.value)
class TestValidateText:
"""Test cases for validate_text function"""
def test_validate_text_empty(self):
"""Should raise ValidationException for empty text"""
with pytest.raises(ValidationException):
Validator.validate_text("")
def test_validate_text_none(self):
"""Should raise ValidationException for None text"""
with pytest.raises(ValidationException):
Validator.validate_text(None)
def test_validate_text_too_short(self):
"""Should raise ValidationException if text is too short"""
with pytest.raises(ValidationException) as exc_info:
Validator.validate_text("ab") # MIN is 10
assert "at least" in str(exc_info.value)
def test_validate_text_valid_minimum(self):
"""Should accept text at minimum length"""
result = Validator.validate_text("1234567890") # 10 chars
assert result == "1234567890"
def test_validate_text_valid_normal(self):
"""Should accept normal text"""
text = "This is a valid text"
result = Validator.validate_text(text)
assert result == text
def test_validate_text_with_whitespace(self):
"""Should strip whitespace from text"""
text = " valid text "
result = Validator.validate_text(text)
assert result == "valid text"
def test_validate_text_custom_field_name(self):
"""Should use custom field name in error message"""
with pytest.raises(ValidationException) as exc_info:
Validator.validate_text("short", field_name="custom_field")
assert "custom_field" in str(exc_info.value)
class TestValidatePatientName:
"""Test cases for validate_patient_name function"""
def test_validate_patient_name_none(self):
"""Should return None for None input"""
result = Validator.validate_patient_name(None)
assert result is None
def test_validate_patient_name_empty(self):
"""Should return None for empty string"""
result = Validator.validate_patient_name("")
assert result is None
def test_validate_patient_name_too_short(self):
"""Should raise ValidationException for too short name"""
with pytest.raises(ValidationException) as exc_info:
Validator.validate_patient_name("Ab")
assert "at least 3" in str(exc_info.value)
def test_validate_patient_name_valid_cyrillic(self):
"""Should accept valid Cyrillic name"""
name = "Иван Петров"
result = Validator.validate_patient_name(name)
assert result == name
def test_validate_patient_name_valid_latin(self):
"""Should accept valid Latin name"""
name = "John Smith"
result = Validator.validate_patient_name(name)
assert result == name
def test_validate_patient_name_with_hyphen(self):
"""Should accept name with hyphen"""
name = "Mary-Jane Watson"
result = Validator.validate_patient_name(name)
assert result == name
def test_validate_patient_name_with_numbers(self):
"""Should reject name with numbers"""
with pytest.raises(ValidationException):
Validator.validate_patient_name("Ivan123 Petrov")
def test_validate_patient_name_with_special_chars(self):
"""Should reject name with special characters"""
with pytest.raises(ValidationException):
Validator.validate_patient_name("Ivan@Petrov")
def test_validate_patient_name_with_whitespace(self):
"""Should strip whitespace from name"""
name = " Ivan Petrov "
result = Validator.validate_patient_name(name)
assert result == "Ivan Petrov"
class TestValidateDate:
"""Test cases for validate_date function"""
def test_validate_date_none(self):
"""Should return None for None input"""
result = Validator.validate_date(None)
assert result is None
def test_validate_date_empty(self):
"""Should return None for empty string"""
result = Validator.validate_date("")
assert result is None
def test_validate_date_valid_format(self):
"""Should accept valid date in DD.MM.YYYY format"""
date_str = "15.01.2026"
result = Validator.validate_date(date_str)
assert result == date_str
def test_validate_date_invalid_format(self):
"""Should reject invalid date format"""
with pytest.raises(ValidationException) as exc_info:
Validator.validate_date("2026-01-15") # Wrong format
assert "Invalid date format" in str(exc_info.value)
def test_validate_date_invalid_day(self):
"""Should reject invalid day"""
with pytest.raises(ValidationException):
Validator.validate_date("32.01.2026")
def test_validate_date_invalid_month(self):
"""Should reject invalid month"""
with pytest.raises(ValidationException):
Validator.validate_date("15.13.2026")
def test_validate_date_custom_format(self):
"""Should accept custom date format"""
date_str = "2026-01-15"
result = Validator.validate_date(date_str, date_format="%Y-%m-%d")
assert result == date_str
def test_validate_date_with_whitespace(self):
"""Should strip whitespace from date"""
date_str = " 15.01.2026 "
result = Validator.validate_date(date_str)
assert result == "15.01.2026"
class TestValidateApiKey:
"""Test cases for validate_api_key function"""
def test_validate_api_key_none(self):
"""Should return None for None input"""
result = Validator.validate_api_key(None)
assert result is None
def test_validate_api_key_empty(self):
"""Should return None for empty string"""
result = Validator.validate_api_key("")
assert result is None
def test_validate_api_key_too_short(self):
"""Should raise ValidationException for too short key"""
with pytest.raises(ValidationException) as exc_info:
Validator.validate_api_key("short")
assert "too short" in str(exc_info.value)
def test_validate_api_key_valid(self):
"""Should accept valid API key"""
api_key = "sk_test_1234567890"
result = Validator.validate_api_key(api_key)
assert result == api_key
def test_validate_api_key_with_whitespace(self):
"""Should strip whitespace from API key"""
api_key = " sk_test_1234567890 "
result = Validator.validate_api_key(api_key)
assert result == "sk_test_1234567890"
class TestValidateFilePath:
"""Test cases for validate_file_path function"""
def test_validate_file_path_empty(self):
"""Should raise ValidationException for empty path"""
with pytest.raises(ValidationException):
Validator.validate_file_path("")
def test_validate_file_path_nonexistent_not_required(self):
"""Should accept non-existent path if must_exist=False"""
result = Validator.validate_file_path("/nonexistent/path.txt", must_exist=False)
assert isinstance(result, Path)
def test_validate_file_path_nonexistent_required(self):
"""Should reject non-existent path if must_exist=True"""
with pytest.raises(ValidationException) as exc_info:
Validator.validate_file_path("/nonexistent/path.txt", must_exist=True)
assert "does not exist" in str(exc_info.value)
def test_validate_file_path_existing_file(self, tmp_path):
"""Should accept existing file path"""
file_path = tmp_path / "test.txt"
file_path.write_text("test content")
result = Validator.validate_file_path(str(file_path), must_exist=True)
assert isinstance(result, Path)
assert result.exists()
def test_validate_file_path_existing_directory(self, tmp_path):
"""Should accept existing directory path"""
result = Validator.validate_file_path(str(tmp_path), must_exist=True)
assert isinstance(result, Path)
assert result.exists()
def test_validate_file_path_resolves_relative(self):
"""Should resolve relative paths"""
result = Validator.validate_file_path(".", must_exist=False)
assert isinstance(result, Path)
assert result.is_absolute()
class TestValidatorIntegration:
"""Integration tests for validators"""
def test_full_patient_validation_flow(self):
"""Test complete patient data validation"""
# Valid data
name = Validator.validate_patient_name("Ivan Petrov")
date = Validator.validate_date("15.01.1990")
assert name == "Ivan Petrov"
assert date == "15.01.1990"
def test_full_audio_file_validation(self, tmp_path):
"""Test complete audio file validation flow"""
# Create a valid audio file
audio_file = tmp_path / "recording.wav"
audio_file.write_bytes(b"fake audio data")
# Validate
result = Validator.validate_audio_file(str(audio_file))
assert result.exists()
assert result.suffix.lower() == ".wav"
def test_validation_error_handling(self):
"""Test that validation errors have proper context"""
with pytest.raises(ValidationException) as exc_info:
Validator.validate_patient_name("X")
exc = exc_info.value
assert exc.field == "patient_name"
assert "3" in str(exc)
|