Repository navigation
chore: Release v1.0.0.dev16 - #19
Merged
Merged
Conversation
Add DRY testsuite for composite primary key support: - ICompositePKProvider interface - Fixture models (OrderItem, StoreInventory, Order) with sync/async variants - Parameterized conftest with scenario-based fixtures - Test files: ActiveRecord CRUD, ActiveQuery, CTE, set operations - Both sync and async test coverage
- Fix skip_test_if_protocol_unsupported to resolve dotted string paths via importlib.import_module instead of silently failing - Update test_fulltext_search_compatibility marker to use IndexSupport protocol with supports_fulltext_search
…earch capability doc
- composite_pk/fixtures/models: add MappedOrderItem/AsyncMappedOrderItem
using Annotated[int, UseColumn('order_id'/'product_id')] to exercise
Python field name != DB column name with composite PK.
- composite_pk/interfaces: declare setup_mapped_order_item_model and
async counterpart on ICompositePKProvider.
- composite_pk/conftest: expose mapped_order_item_class and
async_mapped_order_item_class fixtures.
- composite_pk/test_activerecord: add TestCompositePKWithColumnMapping
covering meta introspection, insert/find_one/find_all by field name
and column name, tuple lookup, duplicate-PK integrity error, and
refresh; switch _build_pk_where_predicate missing-column expectation
from KeyError to ValueError to match current implementation.
- query/test_cross_database_compatibility: annotate fulltext search
test with rationale for using supports_fulltext_search (query capability)
rather than supports_fulltext_index (DDL).
- Rename test_sync_queries.py -> test_queries.py and test_async_queries.py -> test_queries_async.py - Delete stale _sync.py benchmark files and related _sync.py bridge files - Add 70+ new async bridge files for full feature parity - Fix test_example_basic_fixtures_async.py: ActiveRecord -> AsyncActiveRecord - Fix test_bulk_operations_async.py: add missing ColumnNameKey/UpdateValues - Fix test_pydantic_native_validation_async.py: add 13 missing Async* model classes - Fix test_threadsafe_dict_async.py: remove await from sync method
…r, events, derived_field, mixins Root cause: split_tests.py copied sync test files without updating fixture references, causing async tests to use sync fixtures that return sync ActiveRecord models instead of AsyncActiveRecord. Fixes: - composite_pk: order_item_class -> async_order_item_class, etc. - worker: AsyncUser.configure() is async def, need asyncio.run() in subprocess task functions (sync context) - events: add async_event_model fixture + provider support - derived_field: add AsyncProductFormA model + async_product_form_a_class fixture; fix fixture refs for proxy/adapter classes - mixins: add 4 async model classes + 4 async fixtures + provider support - Add await on query chain terminators (.one(), .all()) for async model query_with_deleted() / query_only_deleted() calls
Mirror the core sync/async parity fix (same-name async overrides, AsyncSoftDeleteMixin) across the testsuite: - await _trigger_event/validate_fields/restore in async tests (events, mixins, basic, query, relation, composite_pk, etc.) - switch AsyncTask/AsyncCombinedArticle to AsyncSoftDeleteMixin - add async setup_*/cleanup_after_test_async to events, mixins and derived_field providers - gitignore local src.bak*/ and tools/ scratch directories Co-Authored-By: Claude <noreply@anthropic.com>
Four related changes restoring sync/async parity: 1. Remove feature/query/fixtures/async_mapped_models.py, the only module importing sqlalchemy (Mapped* via mapped_column). It had drifted from the sync MappedUser schema and referenced a dangling AsyncMappedOrder, causing ModuleNotFoundError on CI (Python 3.9 where sqlalchemy is not installed). 2. Add native AsyncMappedUser/Post/Comment to fixtures/models.py, mirroring MappedUser with rhosocial UseColumn annotations and AsyncHasMany/AsyncBelongsTo relations. Field/column mappings are identical to the sync counterpart. 3. Fix test_special_queries_async.py: fixture name typo async_extended_async_order_fixtures -> async_extended_order_fixtures (duplicated async_ prefix), drop unused imports/vars, wrap long line. 4. Move ruff select/ignore under [tool.ruff.lint] to silence the deprecated top-level option warning. Co-Authored-By: Claude <noreply@anthropic.com>
…line-count parity violations Global asyncio_mode=auto (pyproject.toml) makes markers redundant: - Remove 681 @pytest.mark.asyncio decorators across 68 async test files - Remove unused import pytest from 1 file - Update check_markers.py to reject (not require) the marker Fix sync/async parity (P6) violations: - test_parallel_queries: add missing async_query_order_items_task to sync - test_eager_loading_scenarios_async: trim 32 trailing blank lines - test_logging_data_summarization_async: remove dead sync helper functions - test_pydantic_native_validation_async: add missing sync model classes - 4 files with excess blank lines normalized Fix bug: _count_async_test_methods now counts top-level async functions Adjust P6 thresholds: P6_file_lines at actual_extra < -40, P6_file_lines_extra at actual_extra > 20 Update rule docs: sync_async_parity.md, test_case_naming_and_markers.md, development_tools.md
…sync duplicates - Add __parity__ = "async_only" to benchmark/fastapi/conftest.py so the sync/async parity checker skips P1 orphan checks for this directory. - Remove 5 sync test files that duplicated async-only benchmarks (test_health.py, test_read.py, test_write.py, test_concurrent_read.py, test_concurrent_transaction.py). - Add docstrings to the corresponding _async.py test functions. - Document the __parity__ convention in .claude/rules/sync_async_parity.md (Rule 1 exception, new Per-directory parity mode section, Known Exceptions entry, updated workflow).
…asic/query
- Delete feature/composite_pk/ and feature/derived_field/ directories
- Move derived_field tests to basic/fields/
- Move composite_pk crud tests to basic/crud/, query tests under query/{basic,cte,set_operations}
- Migrate fixture models/models_py310-312 with composite_pk/derived_field classes
- Reorganize query/relation tests into subdirectories (aggregate, basic, eager_loading, etc.)
- Add new conftest.py fixtures for composite_pk, derived_field scenarios
…le proper teardown The async fixtures in testsuite/feature/query/conftest.py were calling backend.disconnect() BEFORE provider.cleanup_after_test(). This caused the subsequent provider's DROP TABLE statements to silently fail because the connection was already closed, leaving test tables in the database between tests. Removal lets cleanup_after_test() handle both DROP TABLE and disconnect in the correct order, ensuring reliable test isolation across scenarios and within sequential test runs. Affects 10 fixtures: async_order_fixtures, async_blog_fixtures, async_json_user_fixture, async_tree_fixtures, async_combined_fixtures, async_extended_order_fixtures, async_annotated_query_fixtures, async_mapped_models_fixtures, async_profile_fixtures, and leaves async_order_item_class (already correct) unchanged.
… contracts Add the first batch of transaction contract suites covering three subsystems: - Savepoint API black-box contracts (test_savepoint_api.py / test_savepoint_api_async.py): 32 tests for TransactionManager savepoint(), release(), and rollback_to() including auto-naming, explicit names, unknown-name and out-of-transaction error paths, non-stack truncation semantics, data-level rollback proof, and outermost commit with unreleased savepoints. - Pool transaction dispatch contracts (test_pool_transaction_paths.py / _async.py): 30 tests for BackendPool.transaction and AsyncBackendPool.transaction covering three exclusive dispatch branches: existing-transaction reuse (Path 1), connection-only begin/commit and token cleanup (Path 2), and fresh-acquire cycle with commit/release (Path 3), plus rollback-on-exception paths and precedence ordering. - AsyncTransactionManager cross-task owner-task warning (test_async_ owner_task.py): 7 tests verifying the _owner_task safeguard at AsyncTransactionManager.transaction() entry. The I/O layer is stubbed because aiosqlite's worker thread prevents a second asyncio task from safely reusing the same backend instance; the stub isolates the pure state-machine contract. All sync/async mirrors created. 69 new tests pass against the SQLite provider; 30 existing connection tests pass without regression.
Several testsuite tests asserted strict equality of created_at, updated_at, and deleted_at across database round-trips. These broke on backends that store timestamps with less than 6-digit Python precision: - Firebird: TIMESTAMP defaults to 4-digit sub-second precision (.124674 -> .124600). - Oracle: DATE carries no fractional seconds. - SQL Server: datetime rounds to 1/300-second ticks (~3.3 ms). Replace strict equality with a new helper pair in rhosocial.activerecord.testsuite.utils: - assert_datetime_equal(actual, expected, *, tolerance=10ms) - assert_datetime_close(actual, reference, *, tolerance=10ms) Default tolerance (10 ms) is generous enough to cover Firebird, Oracle DATE, and SQL Server rounding, while still surfacing real off-by-large-interval bugs. Tests comparing two in-memory model fields (no DB round-trip) explicitly pass tolerance=timedelta(0) to preserve the original strict semantics. Affected tests: - basic/crud/test_crud.py::test_update_user (and _async) - mixins/test_soft_delete.py::test_soft_delete_basic (and _async) - mixins/test_combined_articles.py::test_combined_update (and _async) - mixins/test_timestamps.py (3 cases) - mixins/test_timestamps_async.py (3 cases) Add tests/rhosocial/activerecord/testsuite/utils/test_datetime_helpers.py with 10 unit tests covering normal/tolerance/strict/tz/None/error- message behaviour. All pass; ruff clean; mypy unchanged (only pre-existing missing-annotation errors remain).
…_protocol contracts Move the ALTER TABLE IF [NOT] EXISTS coverage from a standalone top-level 'feature/ddl' topic into the 'basic' topic as a second-level ddl subtopic. The tests are a generic expression/dialect contract: unsupported backends skip via @requires_protocol(AlterTableModifierSupport, ...) markers instead of in-test capability branches.
str.removeprefix was added in Python 3.9; the testsuite targets 3.8+.
Use replace('supports_', '') to strip the capability prefix in the
requires_protocol skip message.
…xture Rename relation/derived test_derived_field* files to unique basenames so the full feature tree collects under default pytest import mode, and drop the undefined 'fixtures' fixture parameter from feature/test_features*.py that caused 6 collection errors on every backend. Mark the root conftest's pytest_collection_modifyitems hook as trylast so backend-owned collection hooks take precedence. Also rename the async savepoint fixture to async_txn_backend per the async naming convention.
…rtions - Register generic --scenarios pytest option, early-parsed into TESTSUITE_ACTIVE_SCENARIOS before provider modules import - Make datetime field assertions precision-tolerant via supports_microsecond_timestamp() dialect capability - Skip explain assertions when dialect lacks supports_explain_plan() - Use case-insensitive SQL fragment assertions (order_number, CTE names) - Accept "validation error" as NOT NULL violation message - Add changelog fragment
|
vistart
added a commit
that referenced
this pull request
Aug 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.




Description
Release
python-activerecord-testsuitev1.0.0.dev16 to main.Key highlights of this release:
composite_pk,worker,events,derived_field,mixins; removed redundant@pytest.mark.asynciodecorators and resolved P6 line-count parity violations.composite_pk/derived_fieldfeatures intobasic/query; declaredbenchmark/fastapiasasync_only.--scenariospytest option (early-parsed intoTESTSUITE_ACTIVE_SCENARIOS), precision-tolerant datetime assertions, explain-plan skips.test_derived_field*→test_relation_derived_field*) and undefinedfixturesfixture;pytest_collection_modifyitemshook markedtrylast.FOR UPDATE(e.g. Oracle), eliminating lost updates.str.removeprefix.Release/Hotfix Details
v1.0.0.dev16Related Issues/PRs
None (changelog fragments not recorded for the test suite).
Breaking Change
Testing
As a shared test suite library, verification occurs through integration in
dependent
rhosocial-activerecordbackend projects and the core project.(e.g.,
python-activerecord-oraclewithtest_concurrent_transactions_isolationpassing on 18c/21c/23c; core/mysql/postgres/mariadb/sqlserver/firebird CI green).Test Plan:
Confirmed CI runs across the backend ecosystem using this test suite version
(
release/v1.0.0.dev16): core dev29, mysql dev19, postgres dev16, mariadb/oracle/sqlserver dev2, firebird dev1.Checklist
CHANGELOG.mdusingtowncrier build(for releases). (No fragments — test suite does not record changelog fragments.)Additional Notes
This release is part of a coordinated series release (core dev29 ↔ test suite dev16 ↔ backends).