A pytest plugin for managing containerlab topologies in tests.
Project description
pytest-clab
pytest-clab is authored by Thomas Bamihas, governed as a benevolent dictatorship, and distributed under the Apache 2.0 license.
Introduction
While containerlab simplifies spinning up network topologies, integrating it into test workflows still requires boilerplate for deployment, teardown, and node interaction. This plugin provides a convenient pytest fixture to manage containerlab topologies with automatic lifecycle management.
Features
- Lab lifecycle management: Deploy and destroy containerlab topologies directly from pytest.
- Multiple lab support: Interact with multiple labs within a single pytest session, for tests that depend on more than one topology.
- Topology readiness checks: Verify dependent labs are ready before running tests.
- Dynamic node inventory: Retrieve node addresses and connection parameters at test runtime instead of hardcoding them in tests.
- Containerlab CLI access: Run containerlab commands from tests for operations not covered by plugin helpers.
Installation
pip install pytest-clab
Requirements: containerlab CLI must be installed and in PATH.
Quickstart
@pytest.fixture(scope="session")
def lab(clab):
return clab("topology.clab.yaml")
@pytest.mark.parametrize("node_name", ["node1", "node2"])
def test_mgmt_interface_status(lab, node_name):
# GIVEN a lab node
node = lab.nodes[node_name]
# GIVEN netmiko params
params = {
"host": node.ipv4_address,
"username": os.getenv("SSH_USERNAME"),
"password": os.getenv("SSH_PASSWORD"),
"device_type": "nokia_srl",
}
# WHEN fetching mgmt status
with netmiko.ConnectHandler(**params) as conn:
output = conn.send_command("show interface mgmt0 brief")
# THEN expect mgmt0 to be up
assert "up" in output
Working with Topologies and Nodes
ClabTopology
The clab fixture is a factory that creates ClabTopology instances.
Properties:
name- Lab name as reported by containerlabtopology_path- Path to the topology YAML filenodes- Collection of nodes
Methods:
cmd(command, parse_json=False)- Execute any containerlab command, optionally parse JSON output
output = lab.cmd("inspect -f json", parse_json=True)
Node Startup Readiness
The plugin automatically polls containerlab inspect and returns only after all nodes report state: "running".
command_timeoutcontrols timeout per containerlab CLI call.startup_timeoutcontrols total startup polling budget.
Service-level readiness (SSH, NETCONF, gNMI, app-level) checks are environment-specific and performed in test logic.
ClabNodes
The nodes property is a collection that supports flexible access patterns.
Methods:
lab.nodes["name"]- Access a node by short name"name" in lab.nodes- Check if a node existslen(lab.nodes)- Get the number of nodesfor node in lab.nodes- Iterate over all nodesfilter_by_kind(kind)- Filter nodes by kind
for node in lab.nodes:
print(node.short_name, node.ipv4_address)
ClabNode
Each node is an immutable dataclass with the following attributes.
Attributes:
short_name- Node name without lab prefix (e.g., "leaf1")name- Full container name (e.g., "clab-mylab-leaf1")lab_name- Name of the labkind- Node kind (e.g., "linux", "nokia_srlinux")image- Container imagestate- Container state (e.g., "running")status- Container status from containerlab (e.g., "healthy")ipv4_address- Management IPv4 addressipv6_address- Management IPv6 addresscontainer_id- Docker container IDproperties- Dictionary containing additional containerlab node properties not listed above
node = lab.nodes["leaf1"]
print(f"{node.short_name} ({node.kind}): {node.ipv4_address}")
Examples
Keep Running Mode
@pytest.fixture(scope="session")
def lab(clab):
return clab("topology.clab.yml", keep_running=True)
JSON Output
def test_json_output(lab):
result = lab.cmd("inspect -f json", parse_json=True)
assert isinstance(result, dict)
Filter by Node Kind
def test_filter_nodes(lab):
srlinux_nodes = lab.nodes.filter_by_kind("nokia_srlinux")
linux_nodes = lab.nodes.filter_by_kind("linux")
assert len(srlinux_nodes) + len(linux_nodes) == len(lab.nodes)
Dynamic Validation Example
This example uses subtests for per-peer test reporting.
def test_bgp_neighbors(lab, subtests):
node = lab.nodes["router1"]
# Use any library to connect to the node (e.g., ncclient, scrapli, netmiko)
with connect(host=node.ipv4_address, ...) as conn:
neighbors = conn.get(filter=BGP_NEIGHBOR_FILTER).data_xml
for neighbor in neighbors:
with subtests.test(peer=neighbor.find("peer-address").text):
assert neighbor.find("state").text == "established"
Configuration
Environment Variables
CONTAINERLAB_EXECUTABLE
Path to containerlab executable
(default: containerlab)
CONTAINERLAB_EXECUTABLE=/usr/local/bin/clab pytest
Fixture Parameters
topology:
Path to containerlab topology YAML file
(required)
lab = clab("topology.clab.yml")
sudo:
Run containerlab commands with sudo
(default: False)
lab = clab("topology.clab.yml", sudo=True)
keep_running:
Keep lab running at session end
(default: False)
lab = clab("topology.clab.yml", keep_running=True)
command_timeout:
Timeout in seconds for each containerlab command
(default: 300)
lab = clab("topology.clab.yml", command_timeout=600)
startup_timeout:
Timeout in seconds for startup-state polling
(default: 30)
lab = clab("topology.clab.yml", startup_timeout=60)
Exceptions
The plugin provides a hierarchy of exceptions for error handling:
ClabError: Base exception for all pytest-clab errorsTopologyNotFoundError: Topology file does not existContainerlabNotFoundError: containerlab executable not found in PATHDeploymentError: Topology deployment failedInspectError: Failed to inspect running topologyCommandError: A containerlab command failedNodeFailedError: A node entered a terminal failed state during startup
Versioning
Releases will follow semantic versioning (major.minor.patch). Before 1.0.0, breaking changes can be included in a minor release, therefore we highly recommend pinning this package.
Contributing
Suggest a feature or report a bug. Read our developer guide.
License
pytest-clab is distributed under the Apache 2.0 license.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pytest_clab-0.1.1.tar.gz.
File metadata
- Download URL: pytest_clab-0.1.1.tar.gz
- Upload date:
- Size: 10.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7cb36c4f715fe6fb09274f1d12147a970df357b7533f91216a21f430c25ee690
|
|
| MD5 |
89dd82714faaa6dd4aaeacbee21d1300
|
|
| BLAKE2b-256 |
13f31feeaccfedc15d418adda3a4e27bcbf7daa409bbcd11e01598743888adcb
|
Provenance
The following attestation bundles were made for pytest_clab-0.1.1.tar.gz:
Publisher:
publish.yml on nomios-opensource/pytest-clab
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytest_clab-0.1.1.tar.gz -
Subject digest:
7cb36c4f715fe6fb09274f1d12147a970df357b7533f91216a21f430c25ee690 - Sigstore transparency entry: 1003753203
- Sigstore integration time:
-
Permalink:
nomios-opensource/pytest-clab@74b978f12ce2d4e81b17b21e3eac91102217923d -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/nomios-opensource
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@74b978f12ce2d4e81b17b21e3eac91102217923d -
Trigger Event:
release
-
Statement type:
File details
Details for the file pytest_clab-0.1.1-py3-none-any.whl.
File metadata
- Download URL: pytest_clab-0.1.1-py3-none-any.whl
- Upload date:
- Size: 17.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c4f5baa2a58705ed65371614f90d5c69ad8370483111d65a5cc4d5aaefd22a6a
|
|
| MD5 |
d24964b1eeb7c2b305d66ea04a90f19a
|
|
| BLAKE2b-256 |
8873ac79076a35cf7be84d9d81649e37a71970d9c19fa2deb03f9373347594f8
|
Provenance
The following attestation bundles were made for pytest_clab-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on nomios-opensource/pytest-clab
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytest_clab-0.1.1-py3-none-any.whl -
Subject digest:
c4f5baa2a58705ed65371614f90d5c69ad8370483111d65a5cc4d5aaefd22a6a - Sigstore transparency entry: 1003753207
- Sigstore integration time:
-
Permalink:
nomios-opensource/pytest-clab@74b978f12ce2d4e81b17b21e3eac91102217923d -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/nomios-opensource
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@74b978f12ce2d4e81b17b21e3eac91102217923d -
Trigger Event:
release
-
Statement type: