Skip to content

test: add 348 tests to improve non-UI coverage#3

Open
cortexuvula wants to merge 98 commits into
mainfrom
test/coverage-gaps-non-ui
Open

test: add 348 tests to improve non-UI coverage#3
cortexuvula wants to merge 98 commits into
mainfrom
test/coverage-gaps-non-ui

Conversation

@cortexuvula
Copy link
Copy Markdown
Owner

Summary

  • Adds 348 new tests across 12 files (11 extended, 1 new) targeting coverage gaps in non-UI code
  • Focuses on pure-logic validation functions, RAG search quality modules, and manager/health checker mocked paths
  • Key coverage gains: validation.py 58→89%, health_checker.py 66→99%, query_expander.py→100%, adaptive_threshold/mmr_reranker/entity_deduplicator→97-98%

Test plan

  • All 13,867 tests pass (348 new + 13,519 existing)
  • Same 42 Tkinter failures as before (headless environment, unchanged)
  • Zero regressions introduced
  • Coverage verified on all 12 target modules

🤖 Generated with Claude Code

cortexuvula and others added 30 commits March 28, 2026 17:45
…y_storage

- test_vocabulary_manager.py (60 tests): CRUD, import/export JSON/CSV,
  statistics, singleton, settings load/save, specialty/category filtering
- test_recipient_manager.py (58 tests): CRUD, search FTS+fallback, CSV
  import, row mapping, address formatting, singleton isolation
- test_key_storage.py (59 tests): Fernet encrypt/decrypt, salt lifecycle,
  legacy salt migration, machine ID, thread safety, provider listing

All 177 tests pass; suite: 4277 passing, same 38 pre-existing Tkinter failures.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…ding autosave

Covers three critical untested paths identified in GOM-3 audit:

- test_soap_generation_extended.py (35 tests): _prepare_soap_generation(),
  _postprocess_soap_result(), _validate_soap_output() ICD warning branches,
  create_soap_note_streaming(), create_soap_note_with_openai()
- test_migration_manager_extended.py (36 tests): MigrationManager.migrate(),
  rollback(), get_applied_migrations(), get_pending_migrations(),
  _apply_migration(), _apply_migration_12(), run_migrations()
- test_recording_autosave_manager.py (44 tests): full lifecycle (start/stop),
  recovery detection, get_recovery_info(), cleanup, _extract_audio_for_save(),
  thread safety

All tests use mocked dependencies (no real AI calls, DB, or audio hardware).

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- test_exceptions.py (58 tests): full exception hierarchy and AIResult
  wrapper — success/failure factories, unwrap, bool, str, context, usage
- test_timeout_config.py (38 tests): TimeoutConfig singleton, get_timeout,
  get_timeout_tuple, update_timeout, update_connect_timeout, reset_to_defaults,
  get_all_timeouts, settings integration, module-level convenience functions
- test_audit_logger.py (49 tests): AuditEventType enum, singleton behaviour,
  _generate_session_hash, _redact_phi (PHI fields, nested dicts, length),
  log method (JSON output, timestamps, resource hashing, error truncation),
  log_api_key_operation, log_data_export, log_recording_access,
  log_security_event, audit_log convenience function, thread-safety

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…r_manager

- test_sentry_config.py (43 tests): _scrub_data (PHI fields, nested dicts,
  long string truncation, list handling), _before_send (exception frame vars,
  breadcrumbs, extra/tags/user scrubbing), _before_send_transaction, init_sentry
  (no DSN, whitespace DSN, import error, init exception, env flags, PHI
  protection), _get_release_version (git SHA, fallback scenarios)
- test_single_instance.py (28 tests): _get_lock_file_path (per-platform paths),
  _read_lock_file (valid, missing, invalid, whitespace), _write_lock_file
  (success, permission error), _remove_lock_file (exists, missing, OSError),
  _is_process_running (current PID, OSError), ensure_single_instance (first run,
  duplicate detection, stale lock cleanup, own PID, write failure)
- test_data_folder_manager.py (21 tests): path properties (env_file, settings,
  vocabulary, database, config, logs, data), _ensure_folders_exist, migrate_existing_files
  (env file, no-overwrite, config folder), _migrate_from_bundle (macOS bundle
  migration, no-overwrite), singleton checks

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…rity_decorators, log_manager, analysis_storage, and text_processor

- test_autosave_manager.py (87): register/unregister providers, start/stop lifecycle,
  perform_save hash detection + callbacks + disk I/O, _rotate_backups,
  load_latest fallback, clear_saves, get_save_info, settings provider filtering
- test_base_provider_manager.py (55): concrete ProviderManager subclass tests,
  lazy provider init + caching, cache invalidation on settings change,
  get_provider_safe/test_connection_safe OperationResult wrapping,
  create_thread_safe_singleton thread-safety
- test_security_decorators.py (42): rate_limited (allowed/blocked/identifier_arg),
  sanitize_inputs (string filtering, type passthrough, warning on change),
  require_api_key (missing/empty/invalid key), log_api_call (success/error logging),
  secure_api_call combined decorator
- test_log_manager.py (26): _get_logging_settings defaults + merge + parse errors,
  LogManager init log level resolution + env override, setup_logging handler creation
  + module overrides, get_log_file_path/get_log_directory accessors
- test_analysis_storage.py (63): save_medication/differential/compliance_analysis
  db delegation + error handling, get_analyses_for_recording, get/has per type,
  get_recent_* with limit, singleton reset
- test_text_processor.py (25): initial state, clean_command_text (lowercase/strip/
  punctuation), handle_text_command (all 12 known commands + unknown),
  capitalize_next flag, append_text_to_widget, delete_last_word

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Paperclip <noreply@paperclip.ing>
… mocking)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
… RecordingSchema, QueueSchema, BatchSchema)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…rocessingMixin pure logic

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…ts, QueueDatabaseSchema helpers)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…s, completion)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…singleton)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…e, cancellation, status)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…xception isolation

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…grity

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…URL getters, choice generators)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…e index lookup)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…tion, value validation)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…singleton)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…timed, RequestLogger)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…aseTool validation)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…on, query length, singleton)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…s, enrich) and search_config

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…tribution, singletons)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…en, StreamingSearchState)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Covers SearchSyntaxParser (type/date/entity/score/exclude/phrase
extraction, clean_query, full parse integration, singleton, convenience
function) and all Pydantic models in rag/models.py (DocumentType,
UploadStatus enums, DocumentMetadata, DocumentChunk, RAGDocument,
EmbeddingRequest, VectorSearchQuery, HybridSearchResult,
QueryExpansion.get_all_search_terms, RAGQueryRequest, TemporalInfo,
RAGSettings, DocumentUploadRequest, DocumentUploadProgress).

Co-Authored-By: Paperclip <noreply@paperclip.ing>
guidelines_models.py: covers all 8 enums (GuidelineSpecialty,
GuidelineSource, GuidelineType, RecommendationClass, EvidenceLevel,
ComplianceStatus, SectionType, GuidelineUploadStatus), 5 dataclasses
(GuidelineReference, ComplianceItem, ComplianceResult, ConditionFinding,
ConditionCompliance, ComplianceAnalysisResult), and Pydantic models
(GuidelineMetadata, GuidelineChunk, GuidelineDocument, GuidelineSearchQuery,
GuidelinesSettings, ComplianceCheckRequest, ComplianceCheckResponse).

followup_detector.py: covers QueryIntent enum, FollowupResult.to_dict(),
SemanticFollowupDetector class constants and all private methods
(_compute_similarity, _detect_coreference, _check_topic_overlap,
_check_followup_patterns, _calculate_confidence, _determine_intent),
detect() integration, singleton, and convenience function.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Covers RAGError (attributes, __str__ format with/without details,
recoverable flag), all subclasses (EmbeddingError, VectorSearchError,
GraphQueryError including long-query truncation, DocumentProcessingError,
RAGConnectionError with credential-stripping, RAGConfigurationError with
recoverable=False default, RateLimitError, CircuitBreakerOpenError),
RAGErrorCodes constants, and helper functions (wrap_exception with __cause__
chaining, is_retriable_error for RAGError/OS/Timeout/message patterns,
get_retry_delay with exponential backoff + cap at 60s + retry_after).

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Covers ExtractionResult defaults, _extract_recommendation_class (Class
I/IIa/IIb/III, COR, standalone descriptors, case-insensitive),
_extract_evidence_level (all LOE variants, parenthetical, colon format),
_extract_section_type (warning/contraindication/monitoring/evidence/
rationale/default), extract() confidence calculation, and extract_batch().

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Covers _cosine_similarity (identical, orthogonal, opposite, 45°, zero
vector, mismatched lengths), _jaccard_similarity (identical, disjoint,
half-overlap, subsets), _tokenize, rerank with MMR disabled/enabled,
text-based fallback (Jaccard diversity), embedding-based MMR selection,
calculate_diversity_score (single/empty/identical/disjoint/partial),
and singleton helpers (get_mmr_reranker, reset, rerank_with_mmr).

Co-Authored-By: Paperclip <noreply@paperclip.ing>
cortexuvula and others added 30 commits March 29, 2026 00:04
…try, and text processing

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…exporter, and STT failover

Co-Authored-By: Paperclip <noreply@paperclip.ing>
… builder

2 tests marked xfail exposing Composition.subject List[Reference] bug in source.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…nAgent pure-logic methods

Co-Authored-By: Paperclip <noreply@paperclip.ing>
… factory

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Paperclip <noreply@paperclip.ing>
…istry

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Paperclip <noreply@paperclip.ing>
…Manager

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…thods

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…ic methods

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Paperclip <noreply@paperclip.ing>
…ic methods

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…thods

- test_error_handling.py (164 tests): sanitize_error_for_user, get_sanitized_error,
  OperationResult (success/failure/to_dict/unwrap/map), format_error_for_user,
  ErrorContext (capture/user_message/to_log_string/to_dict), handle_errors decorator
  (all 4 return types + CRITICAL re-raise), safe_execute
- test_audit_logger.py (63 tests): AuditEventType enum values, _generate_session_hash
  (SHA-256 truncated to 12 chars, determinism, None path), _redact_phi (all 16 PHI
  field names, case-insensitive keys, nested dict recursion, non-string values)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…ic methods

- test_graph_data_provider.py (178 tests): EntityType.from_string (direct+fuzzy
  matching), GraphNode display_name/matches_search, GraphEdge display_type/
  reliability_score/to_dict, RelationshipConfidenceCalculator.calculate_confidence/
  merge_confidence/should_merge_relationships/merge_edges, GraphData node_count/
  edge_count/get_node/get_edges_for_node/get_connected_nodes/filter_by_type/search
- test_mcp_tool_wrapper_pure.py (81 tests): MCPToolWrapper.validate_args (required
  fields, type checking for string/number/boolean/array/object), _get_cache_key
  (MD5 determinism, sort_keys, non-serializable values)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…_build_context

- test_fallback_cache_provider.py (83 tests): FallbackCacheProvider init (healthy/
  unhealthy primary), _get_provider with retry logic, get/set/get_batch/set_batch/
  delete/clear/cleanup failover behavior, health_check, get_stats, close, concurrency
- test_streaming_retriever_pure.py (44 tests): StreamingHybridRetriever._build_context
  with empty results, source numbering, chunk text, related entities truncation at 5,
  blank-line separators, exact output structure, multiple results ordering

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…ts mixin

- tests/unit/test_analysis_panel_formatter.py: 180 tests for pure detection
  methods (_is_section_header, _detect_severity, _detect_confidence_level,
  _is_warning_line, _detect_warning_type, _is_red_flag, _is_recommendation)
  plus SeverityConfig dataclass and SEVERITY_COLORS/WARNING_COLORS constants
- tests/unit/test_medication_prompts.py: 134 tests for all 7 prompt-building
  methods in MedicationPromptMixin, covering context injection, patient factor
  formatting, renal/hepatic sections, and de-prescribing triggers

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- tests/unit/test_security_validators.py: 59 tests for APIKeyValidator._validate_key_format
  (prefix, length, character-set rules for all 7 providers) and update_format,
  plus InputSanitizer._sanitize_generic (control-char removal, length limit, strip)
- tests/unit/test_lru_cache.py: 88 tests for LRUCache in model_provider — get/set/remove/
  clear, TTL expiry with mocked time.time, LRU eviction order verification, cleanup_expired
  count, stats dict, and concurrent thread-safety

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- tests/unit/test_tool_registry.py: 81 tests for ToolRegistry — default tool
  initialization (10 tools), get/register/remove/list operations, get_tools_for_agent
  filtering, agent-type case-insensitivity, default parameter structures
- tests/unit/test_diagnostic_formatter.py: 76 tests for FormatterMixin._is_in_section —
  section boundary detection, whitespace stripping semantics, all 5 known section headers,
  real-world multi-section document scenarios, and edge cases

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…ator provider

- tests/unit/test_medication_agent_pure.py: 76 tests for MedicationAgent._determine_task_type
  (all routing keywords, case-insensitive, first-match-wins), _parse_medication_list
  (dash/numbered prefixes, colon property parsing, key normalization, edge cases),
  TDM_DRUGS dict (16 drugs, required fields, spot-checks), BEERS_HIGH_RISK list
- tests/unit/test_deep_translator_provider.py: 44 tests for DeepTranslatorProvider
  COMMON_LANGUAGES constant (100 entries, format), get_supported_languages (google/
  microsoft returns COMMON_LANGUAGES, deepl returns shorter list without zh-CN),
  _map_to_deepl_code (all 7 mapped codes + passthrough for unmapped codes)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…xamples

- tests/unit/test_synopsis_agent_pure.py: 77 tests for SynopsisAgent._build_prompt
  (3-vs-4-part join structure, context guard), _clean_synopsis (markdown removal,
  prefix stripping, sequential double-strip), _truncate_to_word_limit (sentence
  boundary via max(period,question,exclamation), ellipsis fallback, limit=0 edge case)
- tests/unit/test_entity_type_examples.py: 96 tests for ENTITY_TYPE_EXAMPLES data
  in generate_prototypes.py — 6 categories, 20 entries each, structure validation,
  specific term membership across all 6 categories, cross-category uniqueness

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Stubbing utils.security_decorators and utils.resilience in sys.modules
was polluting test state and causing test_security_decorators.py to fail
when run in the same session. Only external packages (deep_translator,
deep_translator.exceptions) need stubbing.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…, and managers

Extends 11 existing test files and creates 1 new file (test_api_key_manager.py)
to close coverage gaps in pure-logic and mockable service layers:

- validation.py: 58% → 89% (audio, model, temperature, path, filename, whitelist)
- health_checker.py: 66% → 99% (all 5 health check functions + startup diagnostics)
- adaptive_threshold.py → 98%, entity_deduplicator.py → 97%, mmr_reranker.py → 98%
- query_expander.py → 100%, temporal_reasoner.py → 91%
- agent_manager.py → 86% (retry math, sub-agent concurrency, condition eval security)
- feedback_manager.py → 78%, api_key_manager.py: 0% → 34% (non-GUI)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ctured_logging

- test_sentry_config: Use autouse fixture to properly manage sentry_sdk
  in sys.modules, preventing cross-test pollution when sentry_sdk is/isn't
  installed on CI runners
- test_structured_logging_extended: Save/restore root logger handlers in
  setUp/tearDown so logging.basicConfig takes effect (it's a no-op when
  handlers already exist), and use format() call instead of private _fmt
  attribute for formatter validation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ithout package

The previous sys.modules approach failed on CI ubuntu where sentry_sdk
is installed — Python's import cached the real module reference. Now
intercepts at builtins.__import__ level which works regardless of
whether sentry_sdk is installed. Also uses clear_env=True for
environment tests to prevent MEDICAL_ASSISTANT_ENV leaking from CI env.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The builtins.__import__ approach still failed on CI because pytest's
import machinery doesn't reliably intercept local function imports.
New approach: patch("sentry_sdk.init") directly on the real module —
the import resolves normally, we just mock the .init() call. Tests
skip gracefully if sentry_sdk is not installed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
patch("sentry_sdk.init") failed on CI because Python's import resolution
under coverage.py doesn't reliably intercept the mock. Now pre-imports
sentry_sdk at module level and uses patch.object(_sentry_sdk, "init")
which directly replaces the attribute on the already-loaded module —
no import resolution involved.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause found: sentry_config.py used logging.getLogger() (standard)
but called logger.info("...", environment=env) with a keyword arg that
only StructuredLogger supports. On CI, sentry_sdk.init() succeeded but
the logger.info() call threw "Logger._log() got an unexpected keyword
argument 'environment'", caught by the except Exception block, returning
False. Switched to get_logger() from structured_logging.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant