Spaces:
Build error
Build error
| """ | |
| Unit tests for input validation functions | |
| """ | |
| import pytest | |
| from app import validate_inputs, validate_component_id | |
| class TestComponentIDValidation: | |
| """Test component ID validation""" | |
| def test_valid_component_ids(self): | |
| """Test that valid component IDs pass validation""" | |
| valid_ids = [ | |
| "api-service", | |
| "auth-service", | |
| "payment-service-v2", | |
| "db-01", | |
| "cache", | |
| "a", # Single character | |
| "api-gateway-prod-001", | |
| ] | |
| for component_id in valid_ids: | |
| is_valid, msg = validate_component_id(component_id) | |
| assert is_valid is True, f"'{component_id}' should be valid but got: {msg}" | |
| assert msg == "" | |
| def test_invalid_uppercase(self): | |
| """Test that uppercase letters are rejected""" | |
| invalid_ids = ["API-SERVICE", "Auth-Service", "PaymentService"] | |
| for component_id in invalid_ids: | |
| is_valid, msg = validate_component_id(component_id) | |
| assert is_valid is False | |
| assert "lowercase" in msg.lower() | |
| def test_invalid_underscore(self): | |
| """Test that underscores are rejected""" | |
| is_valid, msg = validate_component_id("api_service") | |
| assert is_valid is False | |
| assert "lowercase" in msg.lower() or "hyphen" in msg.lower() | |
| def test_invalid_special_characters(self): | |
| """Test that special characters are rejected""" | |
| invalid_ids = [ | |
| "api@service", | |
| "api.service", | |
| "api service", # Space | |
| "api/service", | |
| "api&service", | |
| ] | |
| for component_id in invalid_ids: | |
| is_valid, msg = validate_component_id(component_id) | |
| assert is_valid is False, f"'{component_id}' should be invalid" | |
| def test_empty_string(self): | |
| """Test that empty string is rejected""" | |
| is_valid, msg = validate_component_id("") | |
| assert is_valid is False | |
| assert "1-255" in msg or "character" in msg.lower() | |
| def test_too_long(self): | |
| """Test that component IDs longer than 255 chars are rejected""" | |
| long_id = "a" * 256 | |
| is_valid, msg = validate_component_id(long_id) | |
| assert is_valid is False | |
| assert "255" in msg | |
| def test_non_string_type(self): | |
| """Test that non-string types are rejected""" | |
| is_valid, msg = validate_component_id(123) | |
| assert is_valid is False | |
| assert "string" in msg.lower() | |
| class TestNumericInputValidation: | |
| """Test numeric input validation""" | |
| def test_valid_inputs(self): | |
| """Test that valid inputs pass validation""" | |
| is_valid, msg = validate_inputs( | |
| latency=150.0, | |
| error_rate=0.05, | |
| throughput=1000.0, | |
| cpu_util=0.7, | |
| memory_util=0.6 | |
| ) | |
| assert is_valid is True | |
| assert msg == "" | |
| def test_valid_inputs_with_none_optionals(self): | |
| """Test that None is valid for optional fields""" | |
| is_valid, msg = validate_inputs( | |
| latency=150.0, | |
| error_rate=0.05, | |
| throughput=1000.0, | |
| cpu_util=None, | |
| memory_util=None | |
| ) | |
| assert is_valid is True | |
| assert msg == "" | |
| class TestLatencyValidation: | |
| """Test latency validation""" | |
| def test_valid_latency(self): | |
| """Test valid latency values""" | |
| valid_values = [0, 1, 100, 500, 1000, 9999] | |
| for latency in valid_values: | |
| is_valid, msg = validate_inputs(latency, 0.05, 1000, None, None) | |
| assert is_valid is True, f"Latency {latency} should be valid" | |
| def test_negative_latency(self): | |
| """Test that negative latency is rejected""" | |
| is_valid, msg = validate_inputs(-10, 0.05, 1000, None, None) | |
| assert is_valid is False | |
| assert "latency" in msg.lower() | |
| def test_excessive_latency(self): | |
| """Test that excessive latency is rejected""" | |
| is_valid, msg = validate_inputs(20000, 0.05, 1000, None, None) | |
| assert is_valid is False | |
| assert "latency" in msg.lower() | |
| def test_non_numeric_latency(self): | |
| """Test that non-numeric latency is rejected""" | |
| is_valid, msg = validate_inputs("invalid", 0.05, 1000, None, None) | |
| assert is_valid is False | |
| assert "latency" in msg.lower() | |
| class TestErrorRateValidation: | |
| """Test error rate validation""" | |
| def test_valid_error_rates(self): | |
| """Test valid error rate values""" | |
| valid_values = [0, 0.01, 0.05, 0.5, 0.99, 1.0] | |
| for error_rate in valid_values: | |
| is_valid, msg = validate_inputs(100, error_rate, 1000, None, None) | |
| assert is_valid is True, f"Error rate {error_rate} should be valid" | |
| def test_negative_error_rate(self): | |
| """Test that negative error rate is rejected""" | |
| is_valid, msg = validate_inputs(100, -0.1, 1000, None, None) | |
| assert is_valid is False | |
| assert "error rate" in msg.lower() | |
| def test_error_rate_exceeds_one(self): | |
| """Test that error rate > 1 is rejected""" | |
| is_valid, msg = validate_inputs(100, 1.5, 1000, None, None) | |
| assert is_valid is False | |
| assert "error rate" in msg.lower() | |
| def test_non_numeric_error_rate(self): | |
| """Test that non-numeric error rate is rejected""" | |
| is_valid, msg = validate_inputs(100, "high", 1000, None, None) | |
| assert is_valid is False | |
| assert "error rate" in msg.lower() | |
| class TestThroughputValidation: | |
| """Test throughput validation""" | |
| def test_valid_throughput(self): | |
| """Test valid throughput values""" | |
| valid_values = [0, 1, 100, 1000, 10000] | |
| for throughput in valid_values: | |
| is_valid, msg = validate_inputs(100, 0.05, throughput, None, None) | |
| assert is_valid is True, f"Throughput {throughput} should be valid" | |
| def test_negative_throughput(self): | |
| """Test that negative throughput is rejected""" | |
| is_valid, msg = validate_inputs(100, 0.05, -500, None, None) | |
| assert is_valid is False | |
| assert "throughput" in msg.lower() | |
| def test_non_numeric_throughput(self): | |
| """Test that non-numeric throughput is rejected""" | |
| is_valid, msg = validate_inputs(100, 0.05, "many", None, None) | |
| assert is_valid is False | |
| assert "throughput" in msg.lower() | |
| class TestCPUUtilizationValidation: | |
| """Test CPU utilization validation""" | |
| def test_valid_cpu_util(self): | |
| """Test valid CPU utilization values""" | |
| valid_values = [0, 0.1, 0.5, 0.85, 1.0] | |
| for cpu_util in valid_values: | |
| is_valid, msg = validate_inputs(100, 0.05, 1000, cpu_util, None) | |
| assert is_valid is True, f"CPU util {cpu_util} should be valid" | |
| def test_negative_cpu_util(self): | |
| """Test that negative CPU utilization is rejected""" | |
| is_valid, msg = validate_inputs(100, 0.05, 1000, -0.1, None) | |
| assert is_valid is False | |
| assert "cpu" in msg.lower() | |
| def test_cpu_util_exceeds_one(self): | |
| """Test that CPU utilization > 1 is rejected""" | |
| is_valid, msg = validate_inputs(100, 0.05, 1000, 1.5, None) | |
| assert is_valid is False | |
| assert "cpu" in msg.lower() | |
| def test_non_numeric_cpu_util(self): | |
| """Test that non-numeric CPU utilization is rejected""" | |
| is_valid, msg = validate_inputs(100, 0.05, 1000, "high", None) | |
| assert is_valid is False | |
| assert "cpu" in msg.lower() | |
| class TestMemoryUtilizationValidation: | |
| """Test memory utilization validation""" | |
| def test_valid_memory_util(self): | |
| """Test valid memory utilization values""" | |
| valid_values = [0, 0.1, 0.5, 0.85, 1.0] | |
| for memory_util in valid_values: | |
| is_valid, msg = validate_inputs(100, 0.05, 1000, None, memory_util) | |
| assert is_valid is True, f"Memory util {memory_util} should be valid" | |
| def test_negative_memory_util(self): | |
| """Test that negative memory utilization is rejected""" | |
| is_valid, msg = validate_inputs(100, 0.05, 1000, None, -0.1) | |
| assert is_valid is False | |
| assert "memory" in msg.lower() | |
| def test_memory_util_exceeds_one(self): | |
| """Test that memory utilization > 1 is rejected""" | |
| is_valid, msg = validate_inputs(100, 0.05, 1000, None, 1.5) | |
| assert is_valid is False | |
| assert "memory" in msg.lower() | |
| def test_non_numeric_memory_util(self): | |
| """Test that non-numeric memory utilization is rejected""" | |
| is_valid, msg = validate_inputs(100, 0.05, 1000, None, "full") | |
| assert is_valid is False | |
| assert "memory" in msg.lower() | |
| class TestEdgeCases: | |
| """Test edge cases and boundary conditions""" | |
| def test_zero_values(self): | |
| """Test that zero is valid for all metrics""" | |
| is_valid, msg = validate_inputs(0, 0, 0, 0, 0) | |
| assert is_valid is True | |
| def test_maximum_values(self): | |
| """Test maximum boundary values""" | |
| is_valid, msg = validate_inputs(10000, 1.0, 999999, 1.0, 1.0) | |
| assert is_valid is True | |
| def test_float_precision(self): | |
| """Test that high-precision floats are handled""" | |
| is_valid, msg = validate_inputs( | |
| latency=123.456789, | |
| error_rate=0.123456, | |
| throughput=1234.56, | |
| cpu_util=0.87654321, | |
| memory_util=0.76543210 | |
| ) | |
| assert is_valid is True | |
| def test_integer_inputs(self): | |
| """Test that integer inputs are accepted""" | |
| is_valid, msg = validate_inputs(100, 0, 1000, 1, 1) | |
| assert is_valid is True | |
| def test_string_numbers(self): | |
| """Test that string numbers are converted""" | |
| is_valid, msg = validate_inputs("100", "0.05", "1000", "0.7", "0.6") | |
| assert is_valid is True | |
| class TestErrorMessages: | |
| """Test that error messages are helpful""" | |
| def test_error_message_contains_field_name(self): | |
| """Test that error messages identify the problematic field""" | |
| # Latency error | |
| is_valid, msg = validate_inputs(-10, 0.05, 1000, None, None) | |
| assert "latency" in msg.lower() | |
| # Error rate error | |
| is_valid, msg = validate_inputs(100, 2.0, 1000, None, None) | |
| assert "error rate" in msg.lower() | |
| # Throughput error | |
| is_valid, msg = validate_inputs(100, 0.05, -100, None, None) | |
| assert "throughput" in msg.lower() | |
| def test_error_message_has_emoji(self): | |
| """Test that error messages include emoji for visibility""" | |
| is_valid, msg = validate_inputs(-10, 0.05, 1000, None, None) | |
| assert "❌" in msg | |
| def test_error_message_provides_guidance(self): | |
| """Test that error messages provide guidance""" | |
| is_valid, msg = validate_inputs(-10, 0.05, 1000, None, None) | |
| assert "between" in msg.lower() or "range" in msg.lower() or "0-10000" in msg | |
| if __name__ == "__main__": | |
| pytest.main([__file__, "-v", "--tb=short"]) |