Skip to content

feat: parallel testing infrastructure and SQL Server backend improvements - #2

Merged
vistart merged 29 commits into
release/v1.0.0.dev3from
feature/parallel-testing
Aug 29, 2026
Merged

vistart merged 29 commits into
release/v1.0.0.dev3from
feature/parallel-testing

Conversation

@vistart

@vistart vistart commented Aug 29, 2026 •

Copy link
Copy Markdown
Contributor

Description

This PR brings parallel testing support and coordinated SQL Server backend changes to the release/v1.0.0.dev3 line, aligned with python-activerecord PR #118 (feature/parallel-testing merged into release/v1.0.0.dev30).

Issues: (add issue numbers here)

Type of change

  • feat: A new feature
  • docs: Documentation only changes (if related to the new feature)
  • test: Adding missing tests or correcting existing tests (for the new feature)
  • chore: Changes to the build process or auxiliary tools and libraries such as documentation generation (if related to the new feature)
  • ci: Changes to our CI configuration files and scripts (if related to the new feature)
  • build: Changes that affect the build system or external dependencies (if related to the new feature)
  • revert: Reverts a previous commit

Breaking Change

  • No breaking changes

Related Repositories/Packages

  • python-activerecord / release/v1.0.0.dev30 — parallel testing infrastructure, expression/serialization, CLI unification (PR #118)
  • python-activerecord-testsuite / release/v1.0.0.dev17 — parallel-testing plugin, pool/serial mechanism, two-level execution classification, cross-schema fixtures, shared expression round-trip utils (PR #20)

Changes

CI / Infrastructure

  • feat: parallelize testsuite tests with database pooling for CI
  • ci: use -n 8 parallelism for server-type tests
  • ci(test): merge xdist coverage via pytest-cov; restore codecov fidelity
  • ci: update rhosocial-activerecord branch to release/v1.0.0.dev30
  • ci: update rhosocial-activerecord-testsuite branch to release/v1.0.0.dev17

SQL Server-Specific Fixes

  • fix(sqlserver): delegate set_deadlock_priority to backend whitelist validation
  • fix(introspection): parameterize SQL Server introspector SQL and harden SET statements
  • fix(backend): remove %s→? placeholder guessing at execute layer
  • fix(cli): honour encrypt/trust flags with defined precedence over --ssl
  • fix(adapters): date adapter branch ordering
  • fix(adapters): module-level ET import and WKT point separators

SQL Server-Specific Features

  • feat(sqlserver): add named CLI examples and fix named-procedure CLI adapter
  • feat(dialect): declare supports_schema; add cross-schema provider fixtures
  • test: use native ? placeholders in remaining SQL Server tests

Security Hardening

  • test: add SET whitelist and identifier quoting balance tests
  • test: fix SQL Server whitelist and bracket-balance security tests
  • test: fix SQL Server security test dateformat casing and bracket-skip logic

CLI

  • feat: CLI async unification, --ssl param; sqlserver fixes (user/username unification, RICH_AVAILABLE removal, disconnect_async guard)
  • docs(cli): clarify statement input forms
  • fix(test): pass --driver from scenario config in sqlserver blackbox conn_args

Adapter / Test Enhancements

  • test(sqlserver): CLI black-box suites, adapters and dialect version-grid units
  • test(backend): adapter suggestion cache behavior without a live server
  • test(provider): provision mixed default/non-default schema fixtures
  • test: add is_auto_increment/DDL regression tests
  • test(expression): add serialization round-trip coverage for SQL Server expressions
  • fix(test): check for simultaneous double-hold instead of id uniqueness

Testing

  • I have added new tests to cover my changes.
  • I have updated existing tests to reflect my changes.
  • All existing tests pass.
  • This change has been tested on [SQL Server, with xdist/local].

Test Plan:

PYTHONPATH=src .venv3.8/bin/pytest tests/ -v --tb=short

(Skipped local verification; CI will run full SQL Server matrix after PR creation.)

Checklist

  • My code follows the project's code style guidelines.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have made corresponding changes to the documentation (Docstrings, README.md, etc.).
  • My changes generate no new warnings.
  • I have added a Changelog fragment (changelog.d/<issue_number>.<type>.md).
  • I have verified that my changes do not introduce SQL injection vulnerabilities.
  • I have checked for potential performance regressions.

Additional Notes

Targets release: release/v1.0.0.dev3

vistart added 27 commits August 18, 2026 11:53
- wire the testsuite database pool and pooling providers so scenario tests
  run in parallel (pytest-xdist -n auto) against per-worker pooled
  databases instead of the shared scenario database
- reset handler skips DROP/CREATE DATABASE when the slot is already clean
- enable READ_COMMITTED_SNAPSHOT on pooled databases to avoid deadlock-
  induced rollback failures in concurrent transaction tests
- install activerecord and testsuite from feature/parallel-testing in CI
…ame unification, RICH_AVAILABLE removal, disconnect_async guard)
…onn_args

The sqlserver CLI defaults --driver to ODBC Driver 18 for SQL Server, but CI
runners only install ODBC Driver 17. The blackbox conn_args did not forward
the scenario driver, so query/status/async tests failed with missing ODBC
Driver 18. Forward config.driver via --driver so the correct installed
driver is used.
…dapter

- Fix cli/named_procedure.py adapter: remove invalid get_dialect/execute_query
  kwargs and ExecutionOptions import (core handle_named_procedure rejects them)
- Add named_connections examples (development/production) with 6 connections
- Add named_expressions order_expressions (import-safe, prepare_orders_demo helper)
- Add named_procedures order_workflow (OrderProcessingProcedure, max_concurrency=1
  for pyodbc single-connection concurrency limit)
- Add cli demo scripts: named_connection_demo, named_query_demo, named_procedure_demo
- Update examples README with new directories
Dialect-level tests (no DB needed) verifying:
1. is_auto_increment=True produces correct auto-increment DDL keyword
2. All standard types (Integer/Text/Boolean/VarChar/Timestamp) compile
3. BooleanType + DEFAULT True is accepted
4. TimestampType maps to correct backend-specific type

Prevents recurrence of bugs found in rbac cross-backend testing.
The single uploading job ran coverage run under pytest-xdist without a
combine step (59.49% -> 26.46%). Move to pytest-cov reporting and fail on
upload errors. Investigation plan recorded locally under .claude/plan/2026-08-26.
Locks the registered-type set (datetime/date/time/Decimal/UUID/dict/list)
and documents that primitives intentionally rely on default binding;
addresses the backend_mixin gap from the coverage plan.
…rid units

238 cases across the four CLI entrypoints (parser contracts, fake-backend
handle() outputs, error exits), 10 adapters bidirectional round-trips, and
a SQL Server version grid for pagination/capability/temp-table/hint/MERGE
rendering. Defects (XML dict adapter NameError, WKT commas, date-adapter
dead branch) recorded in test comments only.
S1: hoist 'import xml.etree.ElementTree as ET' to module scope so
SQLServerXMLAdapter dict rendering works instead of raising NameError.

S2: _dict_to_wkt now separates coordinate pairs with commas
(LINESTRING(1 2, 3 4), POLYGON((0 0, 0 1, 1 1, 0 0))) producing valid WKT.

Anchor flip: NameError-pinning XML test replaced with positive round-trip
assertions (text/nested/repeated nodes); LineString/Polygon expectations
updated to comma-separated WKT.
S4: resolve_connection_config_from_args now reads --encrypt/--no-encrypt
and --trust-server-certificate/--no-trust-server-certificate. Flags use a
None sentinel default so explicit usage is detectable; explicit flags take
precedence over --ssl derivation. The default --ssl auto no longer implies
encrypt=True. Default matrix documented in the module docstring.

Anchor flip: parser-contract tests assert None sentinel defaults; SSL
mapping rewritten as a full five-mode matrix plus flag-combination
precedence cases.
S3: SQLServerDateAdapter checks datetime before date (datetime is an
isinstance of date) so to_database/from_database truncate datetimes to
their date component; the value.date() branches are no longer dead code.

Anchor flip: dead-branch pinning test replaced with datetime->date
truncation assertions in both directions plus a date-only passthrough case.
S6: query --help epilog now states the three statement input forms
(positional argument, -f/--file, stdin pipe) and that no -q short option
exists by design. Documentation only; no behaviour change.
Unify placeholder handling per the get_parameter_placeholder() contract:
callers provide native '?' markers and _prepare_sql_and_params only performs
the SQL Server-specific table hint relocation. Update CRUD tests to use '?'.
Completes the placeholder unification contract: all remaining raw SQL in
tests (transaction isolation, connection pool) switches from MySQL-style
'%s' to SQL Server native '?' markers.
…en SET statements

- Convert all 7 _build_*_sql methods in the SQL Server introspector from
  f-string identifier interpolation to '?' placeholders, returning (sql,
  params) tuples consistent with the base IntrospectorMixin contract.
- _build_primary_key_sql now returns (sql, params); update sync/async
  list_columns callers to pass params to executor.execute.
- IDENT_CURRENT and DBCC CHECKIDENT now take table/seed as bound
  parameters instead of raw string embedding.
- Add whitelist validation for SET LANGUAGE, SET DATEFORMAT, and
  SET DEADLOCK_PRIORITY (int range -10..10 or LOW/NORMAL/HIGH).
Test the actual whitelist constants (_SQLSERVER_LANGUAGES / _DATE_FORMATS /
_DEADLOCK_PRIORITIES) and fix the bracket-balance assertion to correctly
check that every embedded ] is escaped as ]].
… logic

- SET DATEFORMAT validation lowercases input, so mdY is valid; keep only
  genuinely invalid formats in the negative case.
- bracket-balance check now actually skips escaped ]] pairs via index skip.
…alidation

Transaction manager's set_deadlock_priority now reuses the backend mixin's
whitelist (-10..10 or LOW/NORMAL/HIGH) instead of bare f-string concat.
@vistart vistart self-assigned this Aug 29, 2026
@codecov

codecov Bot commented Aug 29, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 72.14%. Comparing base (c642975) to head (cc3fbf5).

Additional details and impacted files
@@                   Coverage Diff                    @@
##           release/v1.0.0.dev3       #2       +/-   ##
========================================================
+ Coverage                59.49%   72.14%   +12.65%     
========================================================
  Files                       85       86        +1     
  Lines                     5742     5783       +41     
  Branches                   927      934        +7     
========================================================
+ Hits                      3416     4172      +756     
+ Misses                    2049     1325      -724     
- Partials                   277      286        +9     
Flag Coverage Δ
python-3.14 72.14% <100.00%> (+12.65%) ⬆️
sqlserver-2025 72.14% <100.00%> (+12.65%) ⬆️
unittests 72.14% <100.00%> (+12.65%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

- cover backend_mixin validation branches (deadlock priority range/
  whitelist, language whitelist, dateformat whitelist) and parameterized
  IDENT_CURRENT/CHECKIDENT queries via mocked cursors
- cover introspector parameterized SQL builders (table/column/primary
  key/index/foreign key/view/trigger) offline
- cover __main__.parse_args with custom argv
- cover transaction manager set_deadlock_priority backend delegation
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
C Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@vistart
vistart merged commit f25368f into release/v1.0.0.dev3 Aug 29, 2026
12 of 13 checks passed
vistart added a commit that referenced this pull request Sep 24, 2026
…ents (#2)

* feat: parallelize testsuite tests with database pooling for CI

- wire the testsuite database pool and pooling providers so scenario tests
  run in parallel (pytest-xdist -n auto) against per-worker pooled
  databases instead of the shared scenario database
- reset handler skips DROP/CREATE DATABASE when the slot is already clean
- enable READ_COMMITTED_SNAPSHOT on pooled databases to avoid deadlock-
  induced rollback failures in concurrent transaction tests
- install activerecord and testsuite from feature/parallel-testing in CI

* ci: use -n 8 parallelism for server-type tests

* fix(test): check for simultaneous double-hold instead of id uniqueness

* feat: CLI async unification, --ssl param; sqlserver fixes (user/username unification, RICH_AVAILABLE removal, disconnect_async guard)

* fix(test): pass --driver from scenario config in sqlserver blackbox conn_args

The sqlserver CLI defaults --driver to ODBC Driver 18 for SQL Server, but CI
runners only install ODBC Driver 17. The blackbox conn_args did not forward
the scenario driver, so query/status/async tests failed with missing ODBC
Driver 18. Forward config.driver via --driver so the correct installed
driver is used.

* feat(sqlserver): add named CLI examples and fix named-procedure CLI adapter

- Fix cli/named_procedure.py adapter: remove invalid get_dialect/execute_query
  kwargs and ExecutionOptions import (core handle_named_procedure rejects them)
- Add named_connections examples (development/production) with 6 connections
- Add named_expressions order_expressions (import-safe, prepare_orders_demo helper)
- Add named_procedures order_workflow (OrderProcessingProcedure, max_concurrency=1
  for pyodbc single-connection concurrency limit)
- Add cli demo scripts: named_connection_demo, named_query_demo, named_procedure_demo
- Update examples README with new directories

* test(expression): add serialization round-trip coverage for SQL Server expressions

* test: add is_auto_increment/DDL regression tests

Dialect-level tests (no DB needed) verifying:
1. is_auto_increment=True produces correct auto-increment DDL keyword
2. All standard types (Integer/Text/Boolean/VarChar/Timestamp) compile
3. BooleanType + DEFAULT True is accepted
4. TimestampType maps to correct backend-specific type

Prevents recurrence of bugs found in rbac cross-backend testing.

* feat(dialect): declare supports_schema; add cross-schema provider fixtures

* test(provider): provision mixed default/non-default schema fixtures

* ci(test): merge xdist coverage via pytest-cov; restore codecov fidelity

The single uploading job ran coverage run under pytest-xdist without a
combine step (59.49% -> 26.46%). Move to pytest-cov reporting and fail on
upload errors. Investigation plan recorded locally under .claude/plan/2026-08-26.

* test(backend): adapter suggestion cache behavior without a live server

Locks the registered-type set (datetime/date/time/Decimal/UUID/dict/list)
and documents that primitives intentionally rely on default binding;
addresses the backend_mixin gap from the coverage plan.

* test(sqlserver): CLI black-box suites, adapters and dialect version-grid units

238 cases across the four CLI entrypoints (parser contracts, fake-backend
handle() outputs, error exits), 10 adapters bidirectional round-trips, and
a SQL Server version grid for pagination/capability/temp-table/hint/MERGE
rendering. Defects (XML dict adapter NameError, WKT commas, date-adapter
dead branch) recorded in test comments only.

* fix(adapters): module-level ET import and WKT point separators

S1: hoist 'import xml.etree.ElementTree as ET' to module scope so
SQLServerXMLAdapter dict rendering works instead of raising NameError.

S2: _dict_to_wkt now separates coordinate pairs with commas
(LINESTRING(1 2, 3 4), POLYGON((0 0, 0 1, 1 1, 0 0))) producing valid WKT.

Anchor flip: NameError-pinning XML test replaced with positive round-trip
assertions (text/nested/repeated nodes); LineString/Polygon expectations
updated to comma-separated WKT.

* fix(cli): honour encrypt/trust flags with defined precedence over --ssl

S4: resolve_connection_config_from_args now reads --encrypt/--no-encrypt
and --trust-server-certificate/--no-trust-server-certificate. Flags use a
None sentinel default so explicit usage is detectable; explicit flags take
precedence over --ssl derivation. The default --ssl auto no longer implies
encrypt=True. Default matrix documented in the module docstring.

Anchor flip: parser-contract tests assert None sentinel defaults; SSL
mapping rewritten as a full five-mode matrix plus flag-combination
precedence cases.

* fix(adapters): date adapter branch ordering

S3: SQLServerDateAdapter checks datetime before date (datetime is an
isinstance of date) so to_database/from_database truncate datetimes to
their date component; the value.date() branches are no longer dead code.

Anchor flip: dead-branch pinning test replaced with datetime->date
truncation assertions in both directions plus a date-only passthrough case.

* docs(cli): clarify statement input forms

S6: query --help epilog now states the three statement input forms
(positional argument, -f/--file, stdin pipe) and that no -q short option
exists by design. Documentation only; no behaviour change.

* fix(backend): remove %s->? placeholder guessing at execute layer

Unify placeholder handling per the get_parameter_placeholder() contract:
callers provide native '?' markers and _prepare_sql_and_params only performs
the SQL Server-specific table hint relocation. Update CRUD tests to use '?'.

* test: use native '?' placeholders in remaining SQL Server tests

Completes the placeholder unification contract: all remaining raw SQL in
tests (transaction isolation, connection pool) switches from MySQL-style
'%s' to SQL Server native '?' markers.

* fix(introspection): parameterize SQL Server introspector SQL and harden SET statements

- Convert all 7 _build_*_sql methods in the SQL Server introspector from
  f-string identifier interpolation to '?' placeholders, returning (sql,
  params) tuples consistent with the base IntrospectorMixin contract.
- _build_primary_key_sql now returns (sql, params); update sync/async
  list_columns callers to pass params to executor.execute.
- IDENT_CURRENT and DBCC CHECKIDENT now take table/seed as bound
  parameters instead of raw string embedding.
- Add whitelist validation for SET LANGUAGE, SET DATEFORMAT, and
  SET DEADLOCK_PRIORITY (int range -10..10 or LOW/NORMAL/HIGH).

* test: add SET whitelist and identifier quoting balance tests

* test: fix SQL Server whitelist and bracket-balance security tests

Test the actual whitelist constants (_SQLSERVER_LANGUAGES / _DATE_FORMATS /
_DEADLOCK_PRIORITIES) and fix the bracket-balance assertion to correctly
check that every embedded ] is escaped as ]].

* test: fix SQL Server security test dateformat casing and bracket-skip logic

- SET DATEFORMAT validation lowercases input, so mdY is valid; keep only
  genuinely invalid formats in the negative case.
- bracket-balance check now actually skips escaped ]] pairs via index skip.

* fix(sqlserver): delegate set_deadlock_priority to backend whitelist validation

Transaction manager's set_deadlock_priority now reuses the backend mixin's
whitelist (-10..10 or LOW/NORMAL/HIGH) instead of bare f-string concat.

* ci: update testsuite branch to release/v1.0.0.dev17

* ci: update rhosocial-activerecord branch to release/v1.0.0.dev30

* ci: update testsuite branch to release/v1.0.0.dev17

* test: add targeted coverage for low-coverage patch areas

- cover backend_mixin validation branches (deadlock priority range/
  whitelist, language whitelist, dateformat whitelist) and parameterized
  IDENT_CURRENT/CHECKIDENT queries via mocked cursors
- cover introspector parameterized SQL builders (table/column/primary
  key/index/foreign key/view/trigger) offline
- cover __main__.parse_args with custom argv
- cover transaction manager set_deadlock_priority backend delegation

* chore: add changelog fragment for PR #2
@vistart
vistart deleted the feature/parallel-testing branch October 1, 2026 03:52
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