Skip to main content

A pytest plugin for managing containerlab topologies in tests.

Project description

pytest-clab

GitHub Actions Workflow Status codecov PyPI - Python Version PyPI - Downloads GitHub License

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 containerlab
  • topology_path - Path to the topology YAML file
  • nodes - Collection of nodes

Methods:

  • cmd(command, parse_json=False) - Execute any containerlab command, optionally parse JSON output
output = lab.cmd(f"inspect -t {lab.topology_path} -f json", parse_json=True)

Node Startup Readiness

The plugin automatically polls containerlab inspect and returns only after all nodes report state: "running".

  • command_timeout controls timeout per containerlab CLI call.
  • startup_timeout controls 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 exists
  • len(lab.nodes) - Get the number of nodes
  • for node in lab.nodes - Iterate over all nodes
  • filter_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 lab
  • kind - Node kind (e.g., "linux", "nokia_srlinux")
  • image - Container image
  • state - Container state (e.g., "running")
  • status - Container status from containerlab (e.g., "healthy")
  • ipv4_address - Management IPv4 address
  • ipv6_address - Management IPv6 address
  • container_id - Docker container ID
  • properties - 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("version -j", 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 errors
    • TopologyNotFoundError: Topology file does not exist
    • ContainerlabNotFoundError: containerlab executable not found in PATH
    • DeploymentError: Topology deployment failed
      • NodeFailedError: A node entered a terminal state (exited, dead) during startup
    • InspectError: Failed to inspect running topology
    • CommandError: A containerlab command failed

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

pytest_clab-0.1.3.tar.gz (10.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pytest_clab-0.1.3-py3-none-any.whl (17.4 kB view details)

Uploaded Python 3

File details

Details for the file pytest_clab-0.1.3.tar.gz.

File metadata

  • Download URL: pytest_clab-0.1.3.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

Hashes for pytest_clab-0.1.3.tar.gz
Algorithm Hash digest
SHA256 86647d4583e0af740bb4403486d4fd43f5ffe6fe0ba54e45f4e470771c9faab3
MD5 a809bf04cbe4c1a9f3dc37061a86b60e
BLAKE2b-256 41e5bdd951eb10cc38ea914bc88b528be1c26163a2ade78748372af1a6086109

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_clab-0.1.3.tar.gz:

Publisher: publish.yml on nomios-opensource/pytest-clab

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pytest_clab-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: pytest_clab-0.1.3-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

Hashes for pytest_clab-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 6cd66a052238ab2a5bee110cf1fa51ac23fc0f39c96cc5e78d6df2173499423f
MD5 c86fe591e47344ba93441b90f4b01734
BLAKE2b-256 8c856d21f9f689cc53215a5d59e4e040d8c9afc4e57dd19c57f7db969bee5ea3

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_clab-0.1.3-py3-none-any.whl:

Publisher: publish.yml on nomios-opensource/pytest-clab

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page