# How to Run Tests for the graphviz2drawio Project

> Quickly run tests for the graphviz2drawio project. Execute unit tests with pytest and specification tests with test_specs.sh after installing dependencies.

- Repository: [Harold Martin/graphviz2drawio](https://github.com/hbmartin/graphviz2drawio)
- Tags: how-to-guide
- Published: 2026-03-03

---

**Run `pytest -q test` for unit tests and `./test_specs.sh test/ specs/ tmp_out/` for specification tests after installing GraphViz and Python dependencies.**

The graphviz2drawio project converts GraphViz DOT files into Draw.io XML diagrams. To ensure the conversion logic remains stable across Python versions and GraphViz releases, the repository maintains two distinct test suites. This guide explains how to run tests for the graphviz2drawio project using both the **pytest** unit suite and the **specification (spec)** integration suite.

## Install Prerequisites for Running Tests

Before executing any test suite, you must install the external GraphViz binary and the Python dependencies required by the library and its tests.

### Install the GraphViz System Binary

The library shells out to the external `dot` executable from GraphViz to parse DOT syntax. Install it via your system package manager:

```bash

# macOS

brew install graphviz

# Debian/Ubuntu

sudo apt-get install graphviz

```

### Install Python Test Dependencies

Create a virtual environment and install the runtime and test-specific packages listed in [`requirements.txt`](https://github.com/hbmartin/graphviz2drawio/blob/main/requirements.txt) and [`test/requirements.txt`](https://github.com/hbmartin/graphviz2drawio/blob/main/test/requirements.txt):

```bash
python3 -m venv .venv
source .venv/bin/activate

# 1. Install runtime dependencies (puremagic, pygraphviz, svg.path)

pip install -r requirements.txt

# 2. Install test-only dependencies (pytest, pytest-cov, diagrams)

pip install -r test/requirements.txt

```

## Run the Unit Test Suite

The **unit tests** validate isolated Python logic such as curve mathematics, Bezier approximations, and XML generation. These tests live in the `test/` directory and execute with **pytest**.

Run all unit tests from the repository root:

```bash
pytest -q test

```

Typical output confirms the test count and duration:

```

.................                                                   [100%]
17 passed in 0.62s

```

Key test modules and their coverage include:

- **[`test/test_curve.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/test/test_curve.py)** – Verifies the internal `_line` helper and its handling of vertical lines.
- **[`test/test_bezier.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/test/test_bezier.py)** – Tests cubic-to-quadratic conversion via `approximate_cubic_bezier_as_quadratic` and inflection subdivision via `subdivide_inflections`.
- **[`test/test_graphs.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/test/test_graphs.py)** – End-to-end checks that the CLI produces correct XML for various DOT constructs (simple graphs, clusters, ports).
- **[`test/test_rect.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/test/test_rect.py)** and **[`test/test_diagrams_generate.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/test/test_diagrams_generate.py)** – Validate rectangle handling and diagram generation helpers.

## Run the Specification (Spec) Tests

The **specification tests** provide end-to-end regression testing by converting GraphViz [`.gv.txt`](https://github.com/hbmartin/graphviz2drawio/blob/main/.gv.txt) files and comparing the output against reference XML stored in `specs/`. A Bash helper script automates this workflow.

Execute the spec suite:

```bash
mkdir -p tmp_out
./test_specs.sh test/ specs/ tmp_out/

```

The script performs the following steps:

1. Discovers every `*.gv.txt` file under the source tree (e.g., `test/`).
2. Invokes the CLI (`python -m graphviz2drawio`) to convert each file to XML.
3. Writes output to `tmp_out/` with the same relative path but `.xml` extension.
4. Compares generated XML against the reference files in `specs/`, normalizing unstable IDs that change between runs.

Successful execution prints:

```

Processing files from test/ to tmp_out
Processed: test/undirected/polylines.gv.txt -> tmp_out/undirected/polylines.xml (0)
...
No differences found (ignoring unstable IDs). Test passed.

```

If differences exist, the script displays the offending path and diff output, exiting with a non-zero status. The CI pipeline defined in [`.github/workflows/spec_test.yml`](https://github.com/hbmartin/graphviz2drawio/blob/main/.github/workflows/spec_test.yml) runs this same script on every push to ensure regression safety.

## Continuous Integration Test Configuration

The repository uses **GitHub Actions** to automate the spec test suite. The workflow file [`.github/workflows/spec_test.yml`](https://github.com/hbmartin/graphviz2drawio/blob/main/.github/workflows/spec_test.yml) triggers on pushes and pull requests, installing GraphViz and Python dependencies before executing [`test_specs.sh`](https://github.com/hbmartin/graphviz2drawio/blob/main/test_specs.sh). This ensures that conversion output remains stable across different environments and dependency updates.

## Summary

- **Install prerequisites**: GraphViz system binary plus dependencies from [`requirements.txt`](https://github.com/hbmartin/graphviz2drawio/blob/main/requirements.txt) and [`test/requirements.txt`](https://github.com/hbmartin/graphviz2drawio/blob/main/test/requirements.txt).
- **Run unit tests**: Execute `pytest -q test` to validate curve math, Bezier logic, and XML generation in [`test/test_curve.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/test/test_curve.py), [`test/test_bezier.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/test/test_bezier.py), and [`test/test_graphs.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/test/test_graphs.py).
- **Run spec tests**: Execute `./test_specs.sh test/ specs/ tmp_out/` to perform end-to-end regression testing against reference XML in `specs/`.
- **CI verification**: The [`.github/workflows/spec_test.yml`](https://github.com/hbmartin/graphviz2drawio/blob/main/.github/workflows/spec_test.yml) workflow automates spec tests on every commit.

## Frequently Asked Questions

### What is the difference between unit tests and spec tests in graphviz2drawio?

**Unit tests** verify isolated Python functions such as `_line` in [`test/test_curve.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/test/test_curve.py) and `approximate_cubic_bezier_as_quadratic` in [`test/test_bezier.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/test/test_bezier.py) using pytest. **Spec tests** are end-to-end integration tests that convert entire [`.gv.txt`](https://github.com/hbmartin/graphviz2drawio/blob/main/.gv.txt) files and compare the generated Draw.io XML against canonical reference files stored in `specs/`, ensuring the complete conversion pipeline remains stable.

### Do I need GraphViz installed to run the tests?

Yes. The library shells out to the external `dot` binary from GraphViz to parse DOT syntax. Both unit tests (which invoke the CLI indirectly) and spec tests (which explicitly run `python -m graphviz2drawio`) require the GraphViz system package to be installed via `brew`, `apt-get`, or your platform’s package manager.

### How do I run a single test file instead of the entire suite?

Use pytest’s path argument to target a specific module. For example, to run only the Bezier conversion tests:

```bash
pytest test/test_bezier.py -v

```

This executes only the tests defined in [`test/test_bezier.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/test/test_bezier.py), such as those covering `subdivide_inflections` and quadratic approximation logic.

### What should I do if spec tests fail due to ID differences?

The [`test_specs.sh`](https://github.com/hbmartin/graphviz2drawio/blob/main/test_specs.sh) script automatically normalizes unstable IDs that change between runs (such as auto-generated element identifiers). If failures persist after this normalization, the diff indicates a genuine regression in XML generation logic. Inspect the diff output to identify the specific XML nodes that differ, then verify the conversion logic in [`graphviz2drawio/__main__.py`](https://github.com/hbmartin/graphviz2drawio/blob/main/graphviz2drawio/__main__.py) or the underlying coordinate transformation code.