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("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 errors
  • TopologyNotFoundError: Topology file does not exist
  • ContainerlabNotFoundError: containerlab executable not found in PATH
  • DeploymentError: Topology deployment failed
  • InspectError: Failed to inspect running topology
  • CommandError: A containerlab command failed
  • NodeFailedError: 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

pytest_clab-0.1.2.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.2-py3-none-any.whl (17.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: pytest_clab-0.1.2.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.2.tar.gz
Algorithm Hash digest
SHA256 493ac97d7e737d086f4cc59eae7be72a94e12811ba41ffee145aff28422f42be
MD5 9a9bc810226f27a8c4b4f2bb2c80bef7
BLAKE2b-256 5f7414a3932a979b7def08ac6567ad17428e1badd07105cf1c0e3d4e6f81541a

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_clab-0.1.2.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.2-py3-none-any.whl.

File metadata

  • Download URL: pytest_clab-0.1.2-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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 3a1435ecb8c4f6bb1564b581a6a520a330a88852e9688e6289d9959fa6d5212c
MD5 4a2b5329a1e95cdb6b2ec81a0c7803c8
BLAKE2b-256 589d00b0ad9673cd24d42d24384af3f74355ddb8fc0c144557aed2957bbcf25e

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_clab-0.1.2-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