Skip to content

PYTHON-5784 Increase code coverage for periodic_executor.py#2771

Open
aclark4life wants to merge 11 commits intomongodb:masterfrom
aclark4life:PYTHON-5784
Open

PYTHON-5784 Increase code coverage for periodic_executor.py#2771
aclark4life wants to merge 11 commits intomongodb:masterfrom
aclark4life:PYTHON-5784

Conversation

@aclark4life
Copy link
Copy Markdown
Contributor

@aclark4life aclark4life commented Apr 23, 2026

PYTHON-5784

Changes in this PR

Adds test/test_periodic_executor.py with unit tests for pymongo/periodic_executor.py. Tests cover the full open/close lifecycle, wake(), update_interval(), skip_sleep(), target returning False stopping the executor, exception in target stopping the executor, and the same lifecycle for AsyncPeriodicExecutor.

Test Plan

Added unit tests using threading.Event for synchronization and asyncio.run() for async executor tests. Background thread exceptions are captured via threading.excepthook override to prevent pytest's thread exception plugin from treating them as test failures.

uv run --extra test python -m pytest test/test_periodic_executor.py -v

Checklist

Checklist for Author

  • Did you update the changelog (if necessary)?
  • Is there test coverage?
  • Is any followup work tracked in a JIRA ticket? If so, add link(s).

Checklist for Reviewer

  • Does the title of the PR reference a JIRA Ticket?
  • Do you fully understand the implementation? (Would you be comfortable explaining how this code works to someone else?)
  • Is all relevant documentation (README or docstring) updated?

Copilot AI review requested due to automatic review settings April 23, 2026 21:34
@aclark4life aclark4life requested a review from a team as a code owner April 23, 2026 21:34
@aclark4life aclark4life requested a review from NoahStapp April 23, 2026 21:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a dedicated unit test module for pymongo.periodic_executor, targeting both the threading-based PeriodicExecutor and asyncio-based AsyncPeriodicExecutor, plus module-level executor registration/shutdown helpers, to improve overall coverage.

Changes:

  • Adds new unit tests for PeriodicExecutor lifecycle and control methods (open/close/join/wake/update_interval/skip_sleep, stop conditions).
  • Adds new unit tests for AsyncPeriodicExecutor lifecycle and stop conditions.
  • Adds unit tests for module-level _register_executor() and _shutdown_executors() behavior.

Comment thread test/test_periodic_executor.py Outdated
call_times = []

async def target():
call_times.append(asyncio.get_event_loop().time())
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inside a running coroutine, asyncio.get_event_loop() is deprecated behavior on newer Python versions and can raise warnings; it may also return a different loop than expected. Use asyncio.get_running_loop().time() to record timestamps from the active loop.

Suggested change
call_times.append(asyncio.get_event_loop().time())
call_times.append(asyncio.get_running_loop().time())

Copilot uses AI. Check for mistakes.
Comment thread test/test_periodic_executor.py Outdated
Comment on lines +379 to +380
await ex.join(timeout=2)
self.assertTrue(ex._stopped)
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the async target raises, the underlying task will finish with an exception. Since AsyncPeriodicExecutor.join() uses asyncio.wait() (which doesn’t retrieve the task exception), this test can emit "Task exception was never retrieved" warnings when the task is GC’d. After await ex.join(...), explicitly retrieve the exception from ex._task (or otherwise await the task) to prevent noisy warnings in the test suite.

Suggested change
await ex.join(timeout=2)
self.assertTrue(ex._stopped)
await ex.join(timeout=2)
task_exc = ex._task.exception() if ex._task is not None and ex._task.done() else None
self.assertTrue(ex._stopped)
self.assertIsInstance(task_exc, RuntimeError)

Copilot uses AI. Check for mistakes.
Comment thread test/test_periodic_executor.py Outdated
Comment on lines +260 to +271
stopped = threading.Event()

def target():
stopped.wait(timeout=5)
return True

ex = _make_sync(target=target)
ex.open()
time.sleep(0.05)
_register_executor(ex)
_shutdown_executors()
stopped.set()
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This target blocks for up to 5 seconds, so _shutdown_executors()’s internal executor.join(1) will reliably burn the full 1s timeout before returning (since the target can’t observe close() until stopped is set later). This makes the unit test consistently slow. Consider using a non-blocking target (e.g., one that returns quickly and relies on the executor sleep loop) so shutdown/join can complete promptly.

Suggested change
stopped = threading.Event()
def target():
stopped.wait(timeout=5)
return True
ex = _make_sync(target=target)
ex.open()
time.sleep(0.05)
_register_executor(ex)
_shutdown_executors()
stopped.set()
ran = threading.Event()
def target():
ran.set()
return True
ex = _make_sync(target=target)
ex.open()
self.assertTrue(ran.wait(timeout=2), "target never ran")
_register_executor(ex)
_shutdown_executors()

Copilot uses AI. Check for mistakes.
Comment thread test/test_periodic_executor.py Outdated
import sys
import threading
import time
import weakref
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

weakref is imported but never used in this test module. Removing unused imports helps keep the test file clean and avoids lint failures if the repo enforces import checks.

Suggested change
import weakref

Copilot uses AI. Check for mistakes.
Comment thread test/test_periodic_executor.py Outdated
Comment on lines +254 to +258
# When executor is GC'd the ref is cleaned up.
ref_count_before = len(pe_module._EXECUTORS)
del ex
self.assertLessEqual(len(pe_module._EXECUTORS), ref_count_before)

Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test relies on the executor weakref being removed immediately after del ex, but that cleanup is GC-dependent and the current assertion (<=) doesn’t actually verify that the weakref callback ran. Consider forcing collection (e.g., gc.collect()) and/or waiting until _EXECUTORS shrinks to make the test deterministic across Python implementations.

Copilot uses AI. Check for mistakes.
Comment thread test/test_periodic_executor.py Outdated
ex = _make_sync(target=target)
ex.open()
time.sleep(0.05)
_register_executor(ex)
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PeriodicExecutor.open() already calls _register_executor(self). Registering ex again here adds a duplicate weakref into _EXECUTORS, which can make the test’s behavior harder to reason about and can cause extra work in _shutdown_executors(). Consider removing the extra _register_executor(ex) call (or clearing _EXECUTORS first if the test needs explicit registration).

Suggested change
_register_executor(ex)

Copilot uses AI. Check for mistakes.
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Apr 23, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.05%. Comparing base (a13842f) to head (8ffcf6f).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2771      +/-   ##
==========================================
+ Coverage   87.96%   88.05%   +0.09%     
==========================================
  Files         141      141              
  Lines       24404    24404              
  Branches     4176     4176              
==========================================
+ Hits        21467    21489      +22     
+ Misses       2040     2020      -20     
+ Partials      897      895       -2     
Flag Coverage Δ
auth-aws-rhel8-test-auth-aws-rapid-web-identity-python3.14-cov 35.01% <ø> (ø)
auth-aws-win64-test-auth-aws-rapid-web-identity-python3.14-cov 35.01% <ø> (-0.03%) ⬇️
auth-enterprise-macos-test-standard-auth-latest-python3.11-auth-ssl-sharded-cluster-cov 43.75% <ø> (ø)
auth-enterprise-rhel8-test-standard-auth-latest-python3.11-auth-ssl-sharded-cluster-cov 43.75% <ø> (ø)
auth-enterprise-win64-test-standard-auth-latest-python3.11-auth-ssl-sharded-cluster-cov 43.75% <ø> (-0.02%) ⬇️
auth-oidc-local-ubuntu-22-test-auth-oidc-default 48.57% <ø> (-0.03%) ⬇️
compression-snappy-rhel8-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 59.33% <ø> (-0.01%) ⬇️
compression-snappy-rhel8-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov ?
compression-snappy-rhel8-test-standard-latest-python3.13-async-auth-ssl-sharded-cluster-cov ?
compression-snappy-rhel8-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 59.00% <ø> (+0.01%) ⬆️
compression-zlib-rhel8-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 59.35% <ø> (+0.01%) ⬆️
compression-zlib-rhel8-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov ?
compression-zlib-rhel8-test-standard-latest-python3.13-async-auth-ssl-sharded-cluster-cov ?
compression-zlib-rhel8-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 59.00% <ø> (+0.01%) ⬆️
compression-zstd-rhel8-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 59.33% <ø> (+0.01%) ⬆️
compression-zstd-rhel8-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov ?
compression-zstd-rhel8-test-standard-latest-python3.13-async-auth-ssl-sharded-cluster-cov ?
compression-zstd-rhel8-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 59.01% <ø> (+0.01%) ⬆️
compression-zstd-ubuntu-22-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 58.98% <ø> (+0.01%) ⬆️
coverage-report-coverage-report 88.02% <ø> (+6.91%) ⬆️
disable-test-commands-rhel8-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 59.33% <ø> (+0.01%) ⬆️
disable-test-commands-rhel8-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov ?
disable-test-commands-rhel8-test-standard-latest-python3.13-async-auth-ssl-sharded-cluster-cov ?
disable-test-commands-rhel8-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 58.99% <ø> (+0.01%) ⬆️
encryption-crypt_shared-macos-test-non-standard-latest-python3.13-noauth-nossl-standalone-cov 52.72% <ø> (ø)
encryption-crypt_shared-macos-test-non-standard-latest-python3.14-auth-ssl-sharded-cluster-cov 54.60% <ø> (+0.02%) ⬆️
encryption-crypt_shared-macos-test-non-standard-latest-python3.14t-noauth-ssl-replica-set-cov 54.40% <ø> (ø)
encryption-crypt_shared-rhel8-test-non-standard-latest-python3.13-noauth-nossl-standalone-cov 52.72% <ø> (-0.01%) ⬇️
encryption-crypt_shared-rhel8-test-non-standard-latest-python3.14-auth-ssl-sharded-cluster-cov 54.47% <ø> (+0.01%) ⬆️
encryption-crypt_shared-rhel8-test-non-standard-latest-python3.14t-noauth-ssl-replica-set-cov 54.38% <ø> (-0.03%) ⬇️
encryption-crypt_shared-win64-test-non-standard-latest-python3.13-noauth-nossl-standalone-cov 52.60% <ø> (-0.01%) ⬇️
encryption-crypt_shared-win64-test-non-standard-latest-python3.14-auth-ssl-sharded-cluster-cov 54.58% <ø> (-0.01%) ⬇️
encryption-crypt_shared-win64-test-non-standard-latest-python3.14t-noauth-ssl-replica-set-cov 54.50% <ø> (+0.07%) ⬆️
encryption-macos-test-non-standard-latest-python3.13-noauth-nossl-standalone-cov 52.72% <ø> (+<0.01%) ⬆️
encryption-macos-test-non-standard-latest-python3.14-auth-ssl-sharded-cluster-cov 54.58% <ø> (-0.03%) ⬇️
encryption-macos-test-non-standard-latest-python3.14t-noauth-ssl-replica-set-cov 54.40% <ø> (+0.02%) ⬆️
encryption-pyopenssl-rhel8-test-non-standard-latest-python3.13-noauth-nossl-standalone-cov 53.38% <ø> (-0.01%) ⬇️
encryption-pyopenssl-rhel8-test-non-standard-latest-python3.14-auth-ssl-sharded-cluster-cov 55.14% <ø> (-0.02%) ⬇️
encryption-pyopenssl-rhel8-test-non-standard-latest-python3.14t-noauth-ssl-replica-set-cov 55.09% <ø> (-0.01%) ⬇️
encryption-rhel8-test-non-standard-latest-python3.13-noauth-nossl-standalone-cov 52.72% <ø> (ø)
encryption-rhel8-test-non-standard-latest-python3.14-auth-ssl-sharded-cluster-cov 54.47% <ø> (+<0.01%) ⬆️
encryption-rhel8-test-non-standard-latest-python3.14t-noauth-ssl-replica-set-cov 54.41% <ø> (+<0.01%) ⬆️
encryption-win64-test-non-standard-latest-python3.13-noauth-nossl-standalone-cov 52.61% <ø> (-0.05%) ⬇️
encryption-win64-test-non-standard-latest-python3.14-auth-ssl-sharded-cluster-cov 54.65% <ø> (+0.07%) ⬆️
encryption-win64-test-non-standard-latest-python3.14t-noauth-ssl-replica-set-cov 54.43% <ø> (-0.03%) ⬇️
load-balancer-test-non-standard-latest-python3.14-auth-ssl-sharded-cluster-cov 48.39% <ø> (ø)
mongodb-latest-test-server-version-python3.10-async-auth-ssl-sharded-cluster-min-deps-cov ?
mongodb-latest-test-server-version-python3.10-async-noauth-nossl-standalone-min-deps-cov 59.34% <ø> (+0.01%) ⬆️
mongodb-latest-test-server-version-python3.10-sync-auth-ssl-sharded-cluster-min-deps-cov ?
mongodb-latest-test-server-version-python3.10-sync-noauth-nossl-replica-set-min-deps-cov ?
mongodb-latest-test-server-version-python3.11-async-noauth-nossl-replica-set-cov ?
mongodb-rapid-test-server-version-python3.10-async-auth-ssl-sharded-cluster-min-deps-cov 61.46% <ø> (+<0.01%) ⬆️
mongodb-rapid-test-server-version-python3.10-async-noauth-nossl-standalone-min-deps-cov 59.34% <ø> (+<0.01%) ⬆️
mongodb-rapid-test-server-version-python3.10-sync-auth-ssl-sharded-cluster-min-deps-cov 59.55% <ø> (+0.07%) ⬆️
mongodb-rapid-test-server-version-python3.10-sync-noauth-nossl-replica-set-min-deps-cov 59.67% <ø> (+0.08%) ⬆️
mongodb-rapid-test-server-version-python3.11-async-noauth-nossl-replica-set-cov 61.40% <ø> (+0.01%) ⬆️
mongodb-v4.2-test-server-version-python3.10-async-auth-ssl-sharded-cluster-min-deps-cov 57.17% <ø> (-0.01%) ⬇️
mongodb-v4.2-test-server-version-python3.10-async-noauth-nossl-standalone-min-deps-cov 55.63% <ø> (+0.02%) ⬆️
mongodb-v4.2-test-server-version-python3.10-sync-auth-ssl-sharded-cluster-min-deps-cov 57.12% <ø> (+0.09%) ⬆️
mongodb-v4.2-test-server-version-python3.10-sync-noauth-nossl-replica-set-min-deps-cov 57.24% <ø> (+0.09%) ⬆️
mongodb-v4.2-test-server-version-python3.11-async-noauth-nossl-replica-set-cov 57.35% <ø> (+0.02%) ⬆️
mongodb-v4.4-test-server-version-python3.10-async-auth-ssl-sharded-cluster-min-deps-cov 59.54% <ø> (+0.01%) ⬆️
mongodb-v4.4-test-server-version-python3.10-async-noauth-nossl-standalone-min-deps-cov 57.57% <ø> (+<0.01%) ⬆️
mongodb-v4.4-test-server-version-python3.10-sync-auth-ssl-sharded-cluster-min-deps-cov 57.62% <ø> (+0.07%) ⬆️
mongodb-v4.4-test-server-version-python3.10-sync-noauth-nossl-replica-set-min-deps-cov 57.72% <ø> (+0.08%) ⬆️
mongodb-v4.4-test-server-version-python3.11-async-noauth-nossl-replica-set-cov 59.35% <ø> (-0.01%) ⬇️
mongodb-v5.0-test-server-version-python3.10-async-auth-ssl-sharded-cluster-min-deps-cov 59.73% <ø> (+<0.01%) ⬆️
mongodb-v5.0-test-server-version-python3.10-async-noauth-nossl-standalone-min-deps-cov 57.75% <ø> (+0.03%) ⬆️
mongodb-v5.0-test-server-version-python3.10-sync-auth-ssl-sharded-cluster-min-deps-cov 57.82% <ø> (+0.07%) ⬆️
mongodb-v5.0-test-server-version-python3.10-sync-noauth-nossl-replica-set-min-deps-cov 57.94% <ø> (+0.07%) ⬆️
mongodb-v5.0-test-server-version-python3.11-async-noauth-nossl-replica-set-cov 59.60% <ø> (+0.04%) ⬆️
mongodb-v6.0-test-server-version-python3.10-async-auth-ssl-sharded-cluster-min-deps-cov 59.75% <ø> (+0.01%) ⬆️
mongodb-v6.0-test-server-version-python3.10-async-noauth-nossl-standalone-min-deps-cov 57.74% <ø> (+<0.01%) ⬆️
mongodb-v6.0-test-server-version-python3.10-sync-auth-ssl-sharded-cluster-min-deps-cov 57.84% <ø> (+0.07%) ⬆️
mongodb-v6.0-test-server-version-python3.10-sync-noauth-nossl-replica-set-min-deps-cov 58.01% <ø> (+0.08%) ⬆️
mongodb-v6.0-test-server-version-python3.11-async-noauth-nossl-replica-set-cov 59.74% <ø> (+0.02%) ⬆️
mongodb-v7.0-test-server-version-python3.10-async-auth-ssl-sharded-cluster-min-deps-cov 59.79% <ø> (+0.01%) ⬆️
mongodb-v7.0-test-server-version-python3.10-async-noauth-nossl-standalone-min-deps-cov 57.75% <ø> (+0.02%) ⬆️
mongodb-v7.0-test-server-version-python3.10-sync-auth-ssl-sharded-cluster-min-deps-cov 57.89% <ø> (+0.07%) ⬆️
mongodb-v7.0-test-server-version-python3.10-sync-noauth-nossl-replica-set-min-deps-cov 58.00% <ø> (+0.08%) ⬆️
mongodb-v7.0-test-server-version-python3.11-async-noauth-nossl-replica-set-cov 59.72% <ø> (+<0.01%) ⬆️
mongodb-v8.0-test-server-version-python3.10-async-auth-ssl-sharded-cluster-min-deps-cov 61.46% <ø> (+0.01%) ⬆️
mongodb-v8.0-test-server-version-python3.10-async-noauth-nossl-standalone-min-deps-cov 59.33% <ø> (ø)
mongodb-v8.0-test-server-version-python3.10-sync-auth-ssl-sharded-cluster-min-deps-cov 59.56% <ø> (+0.08%) ⬆️
mongodb-v8.0-test-server-version-python3.10-sync-noauth-nossl-replica-set-min-deps-cov 59.67% <ø> (+0.08%) ⬆️
mongodb-v8.0-test-server-version-python3.11-async-noauth-nossl-replica-set-cov 61.42% <ø> (+0.02%) ⬆️
no-c-ext-rhel8-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 60.54% <ø> (+0.02%) ⬆️
no-c-ext-rhel8-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov ?
no-c-ext-rhel8-test-standard-latest-python3.13-async-auth-ssl-sharded-cluster-cov ?
no-c-ext-rhel8-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 60.21% <ø> (+0.03%) ⬆️
ocsp-rhel8-test-ocsp-ecdsa-valid-cert-server-staples-latest-python3.14-cov 34.20% <ø> (-0.01%) ⬇️
ocsp-rhel8-test-ocsp-rsa-valid-cert-server-staples-latest-python3.14-cov 34.22% <ø> (-0.01%) ⬇️
pyopenssl-macos-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov ?
pyopenssl-rhel8-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov ?
pyopenssl-win64-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov ?
stable-api-accept-v2-rhel8-auth-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 59.33% <ø> (-0.01%) ⬇️
stable-api-accept-v2-rhel8-auth-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 58.99% <ø> (+<0.01%) ⬆️
stable-api-require-v1-rhel8-auth-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 59.30% <ø> (+0.01%) ⬆️
stable-api-require-v1-rhel8-auth-test-standard-latest-python3.13-async-auth-ssl-sharded-cluster-cov ?
stable-api-require-v1-rhel8-auth-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 58.96% <ø> (ø)
storage-inmemory-rhel8-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 59.35% <ø> (+0.01%) ⬆️
storage-inmemory-rhel8-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 59.00% <ø> (ø)
test-macos-arm64-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 59.33% <ø> (+0.02%) ⬆️
test-macos-arm64-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov ?
test-macos-arm64-test-standard-latest-python3.13-async-auth-ssl-sharded-cluster-cov ?
test-macos-arm64-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 58.97% <ø> (ø)
test-macos-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 59.32% <ø> (+0.02%) ⬆️
test-macos-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov 61.45% <ø> (+0.01%) ⬆️
test-macos-test-standard-latest-python3.13-async-auth-ssl-sharded-cluster-cov 61.07% <ø> (+<0.01%) ⬆️
test-macos-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 58.98% <ø> (+<0.01%) ⬆️
test-numpy-macos-arm64-test-numpy-python3.14-python3.14-cov 32.61% <ø> (ø)
test-numpy-macos-test-numpy-python3.14-python3.14-cov 32.61% <ø> (-0.01%) ⬇️
test-numpy-rhel8-test-numpy-python3.14-python3.14-cov 32.61% <ø> (ø)
test-numpy-win32-test-numpy-python3.14-python3.14-cov 32.59% <ø> (ø)
test-numpy-win64-test-numpy-python3.14-python3.14-cov 32.59% <ø> (ø)
test-win32-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 59.20% <ø> (-0.02%) ⬇️
test-win32-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov ?
test-win32-test-standard-latest-python3.13-async-auth-ssl-sharded-cluster-cov ?
test-win32-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 58.86% <ø> (+0.01%) ⬆️
test-win64-test-standard-latest-python3.11-async-noauth-nossl-standalone-cov 59.20% <ø> (ø)
test-win64-test-standard-latest-python3.12-async-noauth-ssl-replica-set-cov ?
test-win64-test-standard-latest-python3.13-async-auth-ssl-sharded-cluster-cov ?
test-win64-test-standard-latest-python3.14-async-noauth-nossl-standalone-cov 58.87% <ø> (+0.02%) ⬆️

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

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

Comment thread test/test_periodic_executor.py Outdated
Comment on lines +52 to +56
async def _default_target():
return True

if target is None:
target = _default_target
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to differ from the way _make_sync above does it?

Comment thread test/test_periodic_executor.py Outdated
Comment on lines +62 to +63
def _run(coroutine):
return asyncio.run(coroutine)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The individual tests that use asynchronous methods should use AsyncUnitTest or another appropriate test class from test/asynchronous/__init__.py instead of this. Each asyncio.run() call adds a significant amount of runtime overhead to setup and teardown the event loop.

Comment thread test/test_periodic_executor.py Outdated

class TestPeriodicExecutorRepr(unittest.TestCase):
def test_repr_contains_class_and_name(self):
ex = _make_sync(name="myexec")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can move all the _make_sync() calls into an asyncSetUp/setUp method on a base class shared by all of the test classes here.

Comment thread test/test_periodic_executor.py Outdated
finally:
ex.close()
ex.join(timeout=2)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, safe closing of each executor can be done in an asyncTearDown/tearDown method on a base class.

Comment thread test/test_periodic_executor.py Outdated
# ---------------------------------------------------------------------------


class TestAsyncPeriodicExecutorRepr(unittest.TestCase):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move the AsyncPeriodicExecutor tests into test/asynchronous/ and generate the synchronous ones using synchro? That would half the amount of code we need to maintain.

…ous/ via synchro

- Create test/asynchronous/test_periodic_executor.py as the single source of
  truth for all periodic executor tests, using AsyncUnitTest with asyncSetUp/
  asyncTearDown base class for executor lifecycle management
- Register test_periodic_executor.py in synchro's converted_tests so the sync
  variant is auto-generated
- Replace the manually-maintained test/test_periodic_executor.py with the
  synchro-generated equivalent, eliminating duplicated async/sync test code
- Use _IS_SYNC branching for the small number of tests that differ between
  threading (PeriodicExecutor) and asyncio (AsyncPeriodicExecutor) behavior
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.

4 participants