# How to Run Unit Tests in Switchyard: A Complete Guide

> Learn to run unit tests in Switchyard with this guide. Install uv, sync dependencies, and execute pytest tests easily without API keys or external services.

- Repository: [NVIDIA-NeMo/Switchyard](https://github.com/NVIDIA-NeMo/Switchyard)
- Tags: how-to-guide
- Published: 2026-08-23

---

**To run unit tests in Switchyard, install the `uv` package manager, execute `uv sync` to install development dependencies, then run `uv run pytest tests/ -v` to execute the complete pytest suite without requiring API keys or external services.**

Switchyard is an open-source Python project maintained by NVIDIA that provides a lightweight framework for model evaluation and routing. Whether you are contributing new features or verifying local changes, running the unit test suite ensures your code maintains compatibility with the existing codebase. This guide covers the exact commands and workflow documented in the repository's [`DEVELOPMENT.md`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/DEVELOPMENT.md) to help you run unit tests in Switchyard using the modern `uv` toolchain.

## Prerequisites: Install uv

Switchyard uses **uv** as its package manager and task runner. Unlike traditional pip workflows, uv provides faster dependency resolution and execution isolation.

Install uv using the official installer:

```bash
curl -LsSf https://astral.sh/uv/install.sh | sh

```

Once installed, clone the repository and navigate to the project root:

```bash
git clone https://github.com/NVIDIA-NeMo/Switchyard.git
cd Switchyard

```

## Setting Up the Development Environment

### Installing Dependencies with uv sync

The [`DEVELOPMENT.md`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/DEVELOPMENT.md) file specifies that you must synchronize dependencies before running tests. The `uv sync` command creates a virtual environment and installs both core and development dependencies, including `pytest`, `ruff`, and `mypy`.

```bash
uv sync

```

According to the source code in `DEVELOPMENT.md#L25-L27`, this command automatically pulls the **dev** dependency group defined in [`pyproject.toml`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/pyproject.toml) (conforming to PEP 735), ensuring the test runner and linting tools are available.

### Activating the Virtual Environment

While `uv run` can execute commands without explicit activation, the documented workflow recommends activating the environment for interactive development:

```bash
source .venv/bin/activate

```

This places the project's Python interpreter and installed packages on your `$PATH`.

## Running the Test Suite

### Full Test Run

To execute the complete unit test suite, use `uv run pytest` with the tests directory:

```bash
uv run pytest tests/ -v

```

As documented in `DEVELOPMENT.md#L55-L57`, this command runs every Python file in the `tests/` directory with verbose output. The `uv run` prefix guarantees that pytest executes using the exact package versions locked in `uv.lock`, eliminating "works on my machine" discrepancies.

### Running Specific Test Files

For faster iteration during development, target individual test modules. For example, to run only the core API bindings tests:

```bash
uv run pytest tests/test_libsy_minimal_bindings.py -v

```

This file contains representative unit tests such as `test_random_rejects_invalid_weights()`, which validates that the routing algorithms correctly reject malformed weight configurations.

### Excluding Integration Tests

The repository includes end-to-end tests that require external credentials. To skip these and run only the self-contained unit tests:

```bash
uv run pytest tests/ -v -m "not e2e"

```

This marker-based exclusion keeps the unit test execution fast and free of external dependencies.

## Test Structure and Key Files

The `tests/` directory contains pure Python tests that require no external services or API keys. The primary test file [`tests/test_libsy_minimal_bindings.py`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/tests/test_libsy_minimal_bindings.py) exercises the core Python libsy API with functions like:

```python
def test_random_rejects_invalid_weights() -> None:
    targets = ["fast", "capable"]
    with pytest.raises(ValueError, match="expected 2 weights, got 1"):
        algorithms.random(targets, weights=[1])

```

Configuration is managed across three critical files:
- **[`pyproject.toml`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/pyproject.toml)** declares the development dependency group (`dev`) that includes `pytest`
- **`uv.lock`** pins the exact versions of all dependencies used by the test runner
- **[`DEVELOPMENT.md`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/DEVELOPMENT.md)** serves as the primary developer guide containing the canonical test commands

## Linting and Type Checking

The development workflow includes running code quality checks alongside tests. Execute these commands to ensure your changes meet the project's standards:

```bash

# Lint the codebase

uv run ruff check .

# Type check the switchyard package

uv run mypy switchyard

```

These tools are installed automatically by `uv sync` and enforce the coding standards defined in the repository configuration.

## Summary

- **Install uv** using the official installer script to manage the project's Python environment.
- **Run `uv sync`** to create the virtual environment and install the `dev` dependency group containing pytest, ruff, and mypy.
- **Execute `uv run pytest tests/ -v`** to run the complete unit test suite with locked dependency versions.
- **Target specific files** like [`tests/test_libsy_minimal_bindings.py`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/tests/test_libsy_minimal_bindings.py) for rapid iteration during development.
- **Exclude integration tests** using `-m "not e2e"` when you need fast feedback without external service dependencies.

## Frequently Asked Questions

### Do I need API keys to run Switchyard unit tests?

No. According to the repository's [`DEVELOPMENT.md`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/DEVELOPMENT.md), the unit test suite is completely self-contained and does not require any API keys or external services. Only the end-to-end integration tests marked with `e2e` require credentials, and these can be skipped using the `-m "not e2e"` flag.

### What is the difference between `uv run pytest` and running pytest directly?

Using `uv run pytest` spawns a subprocess using the Python interpreter from the project's virtual environment, guaranteeing that the test runner uses the exact package versions declared in `uv.lock`. Running pytest directly may use your global Python environment, which could lead to version mismatches and inconsistent test results compared to the CI environment.

### How do I run only one specific test file?

Use the file path as an argument to pytest. For example, `uv run pytest tests/test_libsy_minimal_bindings.py -v` executes only the tests defined in that specific module. This approach is ideal for debugging or rapid iteration when working on a particular component of the codebase.

### Where are the test dependencies defined?

Test dependencies are declared in the `dev` group within [`pyproject.toml`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/pyproject.toml) following PEP 735 specifications. The `uv sync` command reads this configuration and installs `pytest` along with related tooling. Exact versions are locked in the `uv.lock` file to ensure reproducible test environments across all developer machines and CI pipelines.