Unit Testing Strategy
Relevant source files
The following files were used as context for generating this wiki page:
The unit testing strategy for the flext-ldap repository is built upon the FLEXT framework's standards, emphasizing strict type safety, zero-ceremony API facades, and comprehensive validation of LDAP-specific logic. The strategy employs a namespaced approach to testing support utilities (using u), constants (c), and models (m), ensuring that tests are decoupled from hardcoded values and remain resilient to configuration changes.
Unit tests are primarily located in the tests/unit/ directory and utilize pytest as the execution engine. The strategy covers a broad spectrum of components, including the public API facade, LDAP operations, synchronization logic, server detection utilities, and adapter helpers. This multi-layered approach ensures that each level of the system—from low-level ldap3 interaction to high-level domain services—is verified in isolation.
Sources: tests/unit/test_api.py:11-15, tests/unit/test_utilities.py:10-14, AGENTS.md:P0
Test Architecture and Components
The testing infrastructure relies on a centralized set of constants and utilities to maintain consistency across the suite. This follows the "Truth with evidence" and "One owner" principles where tests validate canonical facts rather than hardcoding expectations.
Core Testing Namespaces
| Namespace | Description | Source |
|---|---|---|
c.Ldap.Tests | Centralized test constants (DNs, filters, hostnames, ports). | tests/constants.py |
u.Ldap.Tests | Specialized test assertion and validation utilities. | tests/utilities.py |
m.Ldap | Pydantic models used for requests, configurations, and results. | tests/models.py |
p.Ldap | Protocols defining structural interfaces for mocking and adapters. | tests/protocols.py |
Testing MRO and Inheritance
The project heavily utilizes Method Resolution Order (MRO) for its public facade (ldap). Testing focuses on ensuring that methods are correctly inherited and dispatched through the facade layers.
This diagram illustrates how test support components interact with the system's inheritance-based facade architecture.
Sources: tests/unit/test_api.py:22-24, tests/unit/test_utilities.py:32-45, tests/constants.py:24-30
Operation and API Validation
Testing the ldap API facade and FlextLdapOperations involves verifying both success paths and the robust handling of "not connected" states. Since many operations require a live connection, unit tests verify that the library gracefully fails and returns descriptive error results when a connection is absent.
Operation Guarding
Tests ensure that API calls like search(), add(), modify(), and delete() return a failure result when the client is not connected to a server.
Sequence showing the standard failure flow when performing operations without an active connection.
Parameter Variation Testing
The strategy employs extensive parametrization to test edge cases in DN formats, search filters, and scope types.
- DN Variations: Valid DNs, empty DNs, and special character handling (e.g.,
cn=test\,user). - Search Filters: Equality, substrings, compound AND/OR filters, and nested logic.
- Search Scopes: BASE, ONE_LEVEL, SUBTREE, and SUBORDINATE.
Sources: tests/unit/test_operations.py:73-100, tests/unit/test_operations.py:215-265, tests/unit/test_api.py:59-65
Synchronization and Batch Logic
The synchronization testing strategy focuses on the FlextLdapSync mixin and its ability to process multiple phases of LDIF data. This includes validating progress callbacks and error-handling configurations (e.g., stop_on_error).
Callback Signature Validation
Tests verify that the system can distinguish between and properly wrap single-phase and multi-phase progress callbacks.
- Single-phase:
(current, total, dn, stats) - Multi-phase:
(phase, current, total, dn, stats)
The system uses _make_phase_progress_callback to wrap signatures, ensuring the correct number of arguments are passed to the user-provided function.
Sources: tests/unit/test_sync.py:36-70, tests/unit/test_api.py:35-57
Batch Upsert Resilience
Batch operations are tested using BatchPathOperations (a deterministic mock) to simulate partial failures in a multi-entry batch. This validates that:
- Failed entries are correctly counted in
LdapBatchStats. - The batch continues or stops based on the
stop_on_errorsetting. - Final failure messages contain correct counts of synced, skipped, and failed entries.
Sources: tests/unit/test_operations.py:108-140, tests/unit/test_operations.py:155-175
Utility and Helper Verification
Utilities for string normalization, DN processing, and LDAP3 response conversion are tested in isolation to ensure high precision in data handling.
Data Normalization
The FlextLdapUtilities class is verified for its ability to normalize values across different LDAP server types:
- Case Normalization: Converting strings to upper/lower case for case-insensitive comparisons.
- Value Conversion: Converting
ldap3attribute values (bytes/lists) into standard Python strings. - Truthiness Filtering: Removing empty or null attributes from dictionaries before processing.
LDAP3 Adapter Helpers
Tests for FlextLdapLdap3Wrappers and ResultConverter use structural mocks of ldap3 entries and connections to verify:
- DN Extraction: Correctly pulling DNs from both LDIF and
ldap3.Entryobjects. - Attribute Mapping: Converting raw LDAP responses into the project's internal
m.Ldif.Entrymodel. - Operation Execution: Ensuring parameters like
size_limitandtime_limitare passed correctly to the underlyingldap3connection.
Sources: tests/unit/test_utilities.py:100-150, tests/unit/test_ldap3_adapter_helpers.py:250-320, tests/unit/test_ldap3_adapter_helpers.py:380-410
Configuration and Metadata
Testing ensures that FlextLdapSettings and related Pydantic models maintain strict validation rules.
Settings Validation
Unit tests for TestsFlextLdapConfig verify the Pydantic model features for LDAP connection settings:
- Port Boundaries: Validating that ports are within the 1-65535 range.
- SSL/TLS Mutual Exclusivity: Checking behavior when various combinations of security flags are provided.
- Singleton State: Ensuring that configuration remains consistent across multiple instantiations within the same session.
Sources: tests/unit/test_config.py:19-45, tests/unit/test_config.py:130-145
Server Detection Strategy
Server detection logic is tested by providing varying sets of RootDSE attributes and supported extensions to detect_server_type.
| Detected Type | Evidence / Pattern |
|---|---|
oid | "Oracle Corporation" vendor name or specific naming contexts. |
openldap | "OpenLDAP" string in vendor name or version. |
ad | Presence of Active Directory specific OIDs (e.g., 1.2.840.113556.1.4.319). |
rfc | Fallback when no specific vendor markers are found. |
Sources: tests/unit/test_utilities.py:228-245, tests/constants.py:165-185
Conclusion
The unit testing strategy for flext-ldap provides a comprehensive safety net for LDAP operations by utilizing isolated component testing, strict model validation, and specialized test utilities. By focusing on connection guards, batch processing resilience, and multi-vendor server detection, the strategy ensures that the library remains stable across diverse LDAP environments while adhering to the FLEXT framework's architectural principles.