Testing¶
The pyNetX test suite is located in test/ and is designed to cover only the
non-deprecated public API. Deprecated sync-flow methods are intentionally not
part of the supported API contract tests.
Test dependency installation¶
From the repository root after building or installing pyNetX:
python -m pip install -U pip
python -m pip install -r test/requirements.txt
Default test suite¶
Run all normal tests, excluding optional Netopeer2 tests:
pytest -c test/pytest.ini test -m "not netopeer" -ra --tb=short
Fast-only tests:
pytest -c test/pytest.ini test -m "not integration and not netopeer" -ra --tb=short
Fake NETCONF integration tests:
pytest -c test/pytest.ini test -m "integration and not netopeer" -ra --tb=short
Optional Netopeer2/Sysrepo tests:
PYNETX_RUN_NETOPEER=1 pytest -c test/pytest.ini test -m netopeer -ra --tb=short
Coverage map¶
test_public_api_contract.py¶
Checks public non-deprecated API symbols, constructor keyword support, exception
classes, and NotificationHealthEvent fields including timestamp and
label.
test_constructor_validation.py¶
Checks constructor validation for hostname, port, username, timeouts,
notification queue size, incomplete-notification guards, drop threshold, and
label type handling.
test_event_bus.py¶
Checks process-wide health event behavior, timeout events, timestamp format,
default timeout label, as_dict() schema, event queue count/clear behavior,
invalid timeouts, and global setter validation.
test_notification_helpers_without_subscription.py¶
Checks helper behavior before subscription: queue size, peek behavior, invalid peek values, clear failure for no subscription, and idempotent subscription cleanup.
test_async_errors_without_connection.py¶
Checks async methods on unconnected clients and connection failures against a closed local TCP port.
test_integration_fake_netconf_server.py¶
Uses a local Paramiko-based fake NETCONF-over-SSH server. It tests async connect/RPC/disconnect, built-in RPC builders, subscription flow, notifications, queue-full events, drop summaries, queue recovery, labels, timestamps, default label behavior, and incomplete-notification events, malformed notification events, and coalesced/fragmented notification stream parsing.
test_client_lifecycle_and_concurrency.py¶
Checks concurrent send_rpc_async() calls on one client, primary RPC usability
while a notification session is active, disconnect cleanup after subscription,
two independent clients, and delete-subscription/resubscribe behavior.
test_notification_queue_deep_integration.py¶
Checks queue peek non-destructiveness, FIFO ordering, peek_notifications(-1),
zero-sized bounded queues, high-watermark behavior, incomplete notification
size guards, and bad-device notification stream cases.
test_rpc_payloads_and_framing.py¶
Checks fragmented replies, large RPC payloads, Unicode payloads, and NETCONF 1.0 EOM framing behavior.
test_static_source_contracts.py¶
Runs source-level checks when the source checkout is available. It verifies that
source code, bindings, type stubs, and event construction contain current
timestamp and label contracts.
test_netopeer2_optional_integration.py¶
Optional real NETCONF server tests against Netopeer2/Sysrepo. They check real
SSH NETCONF connection, get-config, get, lock/unlock when supported,
and notification subscription creation when supported.
Manylinux wheel gate¶
Inside the manylinux container, build and repair wheels, then install each repaired wheel into a clean virtual environment and run:
python -m pytest -c /io/test/pytest.ini /io/test -m "not netopeer" -ra --tb=short
Exclude netopeer inside the manylinux upload loop unless Docker or an
external Netopeer2 target is intentionally provided. Manylinux containers often
do not have access to a Docker daemon.
Testing repaired wheels on the host¶
If wheels are built inside a running manylinux container, copy them to the host:
cd ~/Documents/pyNetX/netconf_pybind
mkdir -p wheelhouse dist
sudo docker cp <container-id>:/io/wheelhouse/. ./wheelhouse/
sudo docker cp <container-id>:/io/dist/. ./dist/
Create a clean Python 3.11 environment and install the matching wheel:
python3.11 -m venv /tmp/pynetx-netopeer-test311
source /tmp/pynetx-netopeer-test311/bin/activate
python -m pip install -U pip
python -m pip install pytest pytest-asyncio paramiko
python -m pip install -r /home/sambhu/Documents/pyNetX/netconf_pybind/test/requirements.txt
python -m pip install /home/sambhu/Documents/pyNetX/netconf_pybind/wheelhouse/pynetx-2.0.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Verify from outside the repository root:
cd /tmp/pynetx-netopeer-test311
python - <<'PY'
import pyNetX
print("pyNetX imported from:", pyNetX.__file__)
PY
The path should point into the virtual environment’s site-packages.
Netopeer2/Sysrepo testing¶
Start a Netopeer2/Sysrepo container on the host:
sudo docker rm -f pynetx-netopeer2 2>/dev/null || true
sudo docker run -d \
--name pynetx-netopeer2 \
-p 830:830 \
sysrepo/sysrepo-netopeer2:latest
Run the optional tests from outside the source tree using absolute paths:
cd /tmp/pynetx-netopeer-test311
PYNETX_RUN_NETOPEER=1 \
PYNETX_NETOPEER_HOST=127.0.0.1 \
PYNETX_NETOPEER_PORT=830 \
PYNETX_NETOPEER_USERNAME=netconf \
PYNETX_NETOPEER_PASSWORD=netconf \
python -m pytest \
-c /home/sambhu/Documents/pyNetX/netconf_pybind/test/pytest.ini \
/home/sambhu/Documents/pyNetX/netconf_pybind/test \
-m netopeer \
-ra --tb=short
Expected successful result:
4 passed, 102 deselected in 1.67s
If the container is still starting, the same command may initially skip tests with a message similar to:
external Netopeer2 target 127.0.0.1:830 is not reachable
Run the command again after the container is ready.
Cleanup:
sudo docker rm -f pynetx-netopeer2
deactivate
Recommended release gate¶
Build and repair wheels inside manylinux.
For each repaired wheel, install into a clean venv and run
pytest -m "not netopeer".Copy the repaired wheel to the host.
Install the repaired wheel into a clean matching-Python venv.
Start Netopeer2/Sysrepo.
Run
pytest -m netopeer.Run
twine check.Upload to PyPI only after all required gates pass.