Spaces:
Sleeping
Sleeping
| # test_error_handling.py | |
| """ | |
| Unit tests for error handling and validation in verification mode. | |
| Tests error message display, validation, and user-friendly error handling. | |
| Requirements: 10.1, 10.2, 10.3, 10.4, 10.5 | |
| """ | |
| import pytest | |
| from src.core.verification_error_handler import ( | |
| VerificationErrorHandler, | |
| VerificationError, | |
| ErrorType, | |
| ) | |
| class TestErrorMessageDisplay: | |
| """Tests for error message display (Subtask 9.1).""" | |
| def test_error_message_for_missing_feedback(self): | |
| """Test error message for missing feedback.""" | |
| error_msg = VerificationErrorHandler.get_user_friendly_message( | |
| ErrorType.MISSING_FEEDBACK | |
| ) | |
| assert "Feedback Required" in error_msg | |
| assert "select if this message was correct or incorrect" in error_msg | |
| assert "✓ Correct" in error_msg or "Correct" in error_msg | |
| assert "✗ Incorrect" in error_msg or "Incorrect" in error_msg | |
| def test_error_message_for_missing_correction(self): | |
| """Test error message for missing correction.""" | |
| error_msg = VerificationErrorHandler.get_user_friendly_message( | |
| ErrorType.MISSING_CORRECTION | |
| ) | |
| assert "Correction Required" in error_msg | |
| assert "didn't select" in error_msg or "select" in error_msg | |
| assert "GREEN" in error_msg | |
| assert "YELLOW" in error_msg | |
| assert "RED" in error_msg | |
| def test_error_message_for_csv_export_failure(self): | |
| """Test error message for CSV export failure.""" | |
| error_msg = VerificationErrorHandler.get_user_friendly_message( | |
| ErrorType.CSV_EXPORT_FAILURE | |
| ) | |
| assert "Download Failed" in error_msg | |
| assert "couldn't download" in error_msg or "couldn't" in error_msg | |
| assert "try again" in error_msg.lower() | |
| def test_error_message_for_no_verified_messages(self): | |
| """Test error message for no verified messages.""" | |
| error_msg = VerificationErrorHandler.get_user_friendly_message( | |
| ErrorType.NO_VERIFIED_MESSAGES | |
| ) | |
| assert "No Results to Export" in error_msg | |
| assert "haven't verified" in error_msg or "verified" in error_msg | |
| assert "at least one" in error_msg | |
| def test_error_message_for_invalid_notes(self): | |
| """Test error message for invalid notes.""" | |
| error_msg = VerificationErrorHandler.get_user_friendly_message( | |
| ErrorType.INVALID_NOTES | |
| ) | |
| assert "Notes Too Long" in error_msg | |
| assert "500 characters" in error_msg | |
| def test_error_message_for_session_load_failure(self): | |
| """Test error message for session load failure.""" | |
| error_msg = VerificationErrorHandler.get_user_friendly_message( | |
| ErrorType.SESSION_LOAD_FAILURE | |
| ) | |
| assert "Session Load Failed" in error_msg | |
| assert "couldn't load" in error_msg or "load" in error_msg | |
| def test_error_message_for_dataset_load_failure(self): | |
| """Test error message for dataset load failure.""" | |
| error_msg = VerificationErrorHandler.get_user_friendly_message( | |
| ErrorType.DATASET_LOAD_FAILURE | |
| ) | |
| assert "Dataset Load Failed" in error_msg | |
| assert "couldn't load" in error_msg or "load" in error_msg | |
| def test_error_message_for_storage_failure(self): | |
| """Test error message for storage failure.""" | |
| error_msg = VerificationErrorHandler.get_user_friendly_message( | |
| ErrorType.STORAGE_FAILURE | |
| ) | |
| assert "Save Failed" in error_msg | |
| assert "couldn't save" in error_msg or "save" in error_msg | |
| def test_error_messages_are_user_friendly(self): | |
| """Test that all error messages are user-friendly (non-technical).""" | |
| for error_type in ErrorType: | |
| error_msg = VerificationErrorHandler.get_user_friendly_message(error_type) | |
| # Should not contain technical jargon | |
| assert "exception" not in error_msg.lower() | |
| assert "traceback" not in error_msg.lower() | |
| assert "stacktrace" not in error_msg.lower() | |
| # Should contain helpful suggestion | |
| assert "💡" in error_msg or "try" in error_msg.lower() or "select" in error_msg.lower() | |
| def test_error_message_format_includes_title(self): | |
| """Test that error messages include a title.""" | |
| error_msg = VerificationErrorHandler.get_user_friendly_message( | |
| ErrorType.MISSING_CORRECTION | |
| ) | |
| # Should have markdown bold title | |
| assert "**" in error_msg | |
| def test_error_message_format_includes_suggestion(self): | |
| """Test that error messages include a suggestion.""" | |
| error_msg = VerificationErrorHandler.get_user_friendly_message( | |
| ErrorType.MISSING_FEEDBACK | |
| ) | |
| # Should have suggestion with 💡 emoji | |
| assert "💡" in error_msg | |
| class TestFeedbackValidation: | |
| """Tests for feedback validation.""" | |
| def test_validate_feedback_correct_is_valid(self): | |
| """Test that correct feedback is valid.""" | |
| is_valid, error_msg = VerificationErrorHandler.validate_feedback_selection( | |
| is_correct=True | |
| ) | |
| assert is_valid is True | |
| assert error_msg is None | |
| def test_validate_feedback_incorrect_without_correction_is_invalid(self): | |
| """Test that incorrect feedback without correction is invalid.""" | |
| is_valid, error_msg = VerificationErrorHandler.validate_feedback_selection( | |
| is_correct=False, | |
| ground_truth_label="" | |
| ) | |
| assert is_valid is False | |
| assert error_msg is not None | |
| assert "Correction Required" in error_msg | |
| def test_validate_feedback_incorrect_with_valid_correction_is_valid(self): | |
| """Test that incorrect feedback with valid correction is valid.""" | |
| for correction in ["green", "yellow", "red"]: | |
| is_valid, error_msg = VerificationErrorHandler.validate_feedback_selection( | |
| is_correct=False, | |
| ground_truth_label=correction | |
| ) | |
| assert is_valid is True | |
| assert error_msg is None | |
| def test_validate_feedback_incorrect_with_invalid_correction_is_invalid(self): | |
| """Test that incorrect feedback with invalid correction is invalid.""" | |
| is_valid, error_msg = VerificationErrorHandler.validate_feedback_selection( | |
| is_correct=False, | |
| ground_truth_label="invalid" | |
| ) | |
| assert is_valid is False | |
| assert error_msg is not None | |
| assert "Invalid Selection" in error_msg or "invalid" in error_msg.lower() | |
| def test_validate_feedback_correction_case_insensitive(self): | |
| """Test that correction validation is case-insensitive.""" | |
| for correction in ["GREEN", "Yellow", "RED"]: | |
| is_valid, error_msg = VerificationErrorHandler.validate_feedback_selection( | |
| is_correct=False, | |
| ground_truth_label=correction | |
| ) | |
| assert is_valid is True | |
| assert error_msg is None | |
| class TestNotesValidation: | |
| """Tests for notes field validation.""" | |
| def test_validate_notes_empty_is_valid(self): | |
| """Test that empty notes are valid.""" | |
| is_valid, error_msg = VerificationErrorHandler.validate_notes_field("") | |
| assert is_valid is True | |
| assert error_msg is None | |
| def test_validate_notes_valid_text_is_valid(self): | |
| """Test that valid notes text is valid.""" | |
| notes = "This is a valid note explaining the correction" | |
| is_valid, error_msg = VerificationErrorHandler.validate_notes_field(notes) | |
| assert is_valid is True | |
| assert error_msg is None | |
| def test_validate_notes_at_limit_is_valid(self): | |
| """Test that notes at 500 character limit are valid.""" | |
| notes = "x" * 500 | |
| is_valid, error_msg = VerificationErrorHandler.validate_notes_field(notes) | |
| assert is_valid is True | |
| assert error_msg is None | |
| def test_validate_notes_exceeding_limit_is_invalid(self): | |
| """Test that notes exceeding 500 characters are invalid.""" | |
| notes = "x" * 501 | |
| is_valid, error_msg = VerificationErrorHandler.validate_notes_field(notes) | |
| assert is_valid is False | |
| assert error_msg is not None | |
| assert "500 characters" in error_msg | |
| def test_validate_notes_significantly_exceeding_limit_is_invalid(self): | |
| """Test that notes significantly exceeding limit are invalid.""" | |
| notes = "x" * 1000 | |
| is_valid, error_msg = VerificationErrorHandler.validate_notes_field(notes) | |
| assert is_valid is False | |
| assert error_msg is not None | |
| class TestCSVExportValidation: | |
| """Tests for CSV export validation.""" | |
| def test_validate_csv_export_with_no_messages_is_invalid(self): | |
| """Test that CSV export with no verified messages is invalid.""" | |
| is_valid, error_msg = VerificationErrorHandler.validate_csv_export_preconditions( | |
| verified_count=0 | |
| ) | |
| assert is_valid is False | |
| assert error_msg is not None | |
| assert "No Results to Export" in error_msg | |
| def test_validate_csv_export_with_one_message_is_valid(self): | |
| """Test that CSV export with one verified message is valid.""" | |
| is_valid, error_msg = VerificationErrorHandler.validate_csv_export_preconditions( | |
| verified_count=1 | |
| ) | |
| assert is_valid is True | |
| assert error_msg is None | |
| def test_validate_csv_export_with_multiple_messages_is_valid(self): | |
| """Test that CSV export with multiple verified messages is valid.""" | |
| is_valid, error_msg = VerificationErrorHandler.validate_csv_export_preconditions( | |
| verified_count=10 | |
| ) | |
| assert is_valid is True | |
| assert error_msg is None | |
| class TestErrorCreation: | |
| """Tests for error creation and formatting.""" | |
| def test_create_error_includes_user_message(self): | |
| """Test that created error includes user-friendly message.""" | |
| error = VerificationErrorHandler.create_error( | |
| ErrorType.MISSING_CORRECTION, | |
| "Technical error details" | |
| ) | |
| assert isinstance(error, VerificationError) | |
| assert error.error_type == ErrorType.MISSING_CORRECTION | |
| assert error.message == "Technical error details" | |
| assert "Correction Required" in error.user_message | |
| def test_format_error_for_display(self): | |
| """Test that error is formatted correctly for display.""" | |
| error = VerificationErrorHandler.create_error( | |
| ErrorType.CSV_EXPORT_FAILURE, | |
| "CSV generation failed" | |
| ) | |
| formatted = VerificationErrorHandler.format_error_for_display(error) | |
| assert "Download Failed" in formatted | |
| assert "try again" in formatted.lower() | |
| def test_get_retry_suggestion(self): | |
| """Test that retry suggestion is provided.""" | |
| suggestion = VerificationErrorHandler.get_retry_suggestion( | |
| ErrorType.CSV_EXPORT_FAILURE | |
| ) | |
| assert suggestion is not None | |
| assert len(suggestion) > 0 | |
| assert "try" in suggestion.lower() or "again" in suggestion.lower() | |
| class TestErrorHandlerIntegration: | |
| """Integration tests for error handler.""" | |
| def test_error_handler_provides_consistent_messages(self): | |
| """Test that error handler provides consistent messages.""" | |
| msg1 = VerificationErrorHandler.get_user_friendly_message( | |
| ErrorType.MISSING_CORRECTION | |
| ) | |
| msg2 = VerificationErrorHandler.get_user_friendly_message( | |
| ErrorType.MISSING_CORRECTION | |
| ) | |
| assert msg1 == msg2 | |
| def test_all_error_types_have_messages(self): | |
| """Test that all error types have user-friendly messages.""" | |
| for error_type in ErrorType: | |
| msg = VerificationErrorHandler.get_user_friendly_message(error_type) | |
| assert msg is not None | |
| assert len(msg) > 0 | |
| assert "**" in msg # Should have title | |
| assert "💡" in msg # Should have suggestion | |
| def test_validation_functions_return_consistent_format(self): | |
| """Test that validation functions return consistent format.""" | |
| # All validation functions should return (bool, Optional[str]) | |
| result1 = VerificationErrorHandler.validate_feedback_selection(True) | |
| result2 = VerificationErrorHandler.validate_notes_field("") | |
| result3 = VerificationErrorHandler.validate_csv_export_preconditions(1) | |
| assert isinstance(result1, tuple) and len(result1) == 2 | |
| assert isinstance(result2, tuple) and len(result2) == 2 | |
| assert isinstance(result3, tuple) and len(result3) == 2 | |
| assert isinstance(result1[0], bool) | |
| assert isinstance(result2[0], bool) | |
| assert isinstance(result3[0], bool) | |