Skip to main content

A native pytest plugin for testing and verifying quantum circuits - Qiskit, Cirq, PennyLane (via OpenQASM), simulators and real hardware.

Project description

qcoherence

A native pytest plugin for testing and verifying quantum circuits — across Qiskit, Cirq, and PennyLane (via OpenQASM), on simulators and real IBM Quantum hardware.

Why this exists

Only 31% of quantum developers use any quantum-specific testing tooling — most still debug with print statements and circuit visualizations, because observing a quantum state collapses it, so classical debugging habits don't transfer. Several academic tools have tried to close this gap (Muskit, QuCAT, Quito, MorphQ, QuCheck, QUTest), but each requires writing tests as custom classes inheriting from a project-specific runner, each is tied to Qiskit only, and none validates against real hardware.

qcoherence is different on all three counts:

  1. Native pytest. Install it, write def test_x():, run pytest. No base class, no custom runner.
  2. Cross-framework. Accepts Qiskit QuantumCircuits, OpenQASM 2/3 strings/files, Cirq circuits, and PennyLane circuits (via QASM export).
  3. Real hardware, opt-in. Re-run your golden tests on actual IBM Quantum devices with --qc-hardware, with noise-realistic tolerances.

Install

pip install qcoherence            # core (Qiskit + Aer)
pip install qcoherence[cirq]      # + Cirq ingestion
pip install qcoherence[pennylane] # + PennyLane examples
pip install qcoherence[hardware]  # + IBM Quantum real-device validation
pip install qcoherence[all]       # everything

Quickstart

import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector
from qcoherence import assert_state_equal, assert_entangled, run_statevector

def bell_circuit():
    qc = QuantumCircuit(2)
    qc.h(0)
    qc.cx(0, 1)
    return qc

def test_bell_state():
    expected = Statevector(np.array([1, 0, 0, 1]) / np.sqrt(2))
    actual = run_statevector(bell_circuit())
    assert_state_equal(actual, expected)
    assert_entangled(actual, qubits=[0])

Run it like any other test suite: pytest.

From Cirq or PennyLane

from qcoherence import to_qiskit, run_statevector

# Cirq: pass the circuit object directly
qc = to_qiskit(my_cirq_circuit)

# PennyLane: export to OpenQASM, pass the string
qasm = qml.workflow.construct_tape(my_qnode)().to_openqasm(measure_all=False)
qc = to_qiskit(qasm)

What's proven, not just claimed

tests/test_bug_demo.py demonstrates the core value proposition: a Bell-state circuit missing its entangling gate is a bug that looks completely fine under naive inspection (it's a valid, normalized quantum state) but is caught immediately by assert_entangled and assert_state_equal:

pytest tests/test_bug_demo.py -v

Assertion API

Function Checks
assert_state_equal(actual, expected, tol=1e-6) State fidelity ≈ 1 (equal up to global phase)
assert_distribution_close(counts, probs, tol=0.05) Total variation distance, simple tolerance
assert_distribution_fits(counts, probs, alpha=0.01) Chi-square goodness-of-fit with a real p-value
assert_entangled(state, qubits) Reduced-state purity < 1
assert_separable(state, qubits) Reduced-state purity ≈ 1
holm_bonferroni(pvalues, alpha) Family-wise error control across a suite of statistical tests

pytest integration

  • pytest -m quantum_test — run only qcoherence-marked tests.
  • pytest --qc-hardware — also run @pytest.mark.hardware tests on real IBM Quantum devices (requires a free IBM Quantum account; skipped by default so CI stays green).
  • --qc-shots N / --qc-seed N — shot count and reproducibility seed.

Real-hardware validation

import pytest
from qcoherence.hardware import run_counts_on_hardware, assert_hardware_distribution_close

@pytest.mark.hardware
def test_bell_on_real_device():
    counts = run_counts_on_hardware(bell_circuit(), shots=4096)
    assert_hardware_distribution_close(counts, {"00": 0.5, "11": 0.5})  # tol=0.15, NISQ-realistic

Extending qcoherence

Register custom assertions/backends programmatically or from a separate pip package via entry points — see qcoherence/registry.py:

from qcoherence.registry import register_assertion

@register_assertion("assert_w_state_like")
def assert_w_state_like(state, *, tol=1e-6):
    ...
# in another package's pyproject.toml
[project.entry-points."qcoherence.assertions"]
assert_my_thing = "mypkg.assertions:assert_my_thing"

Golden benchmarks

tests/golden/ contains verified reference circuits used as both examples and a regression suite: Bell state, GHZ state (3-qubit entanglement), and a VQE ground-state search checked against exact numpy diagonalization computed in-test.

Prior art

This project builds on ideas published in the quantum software testing research literature, particularly Muskit (mutation testing), QuCAT (combinatorial testing), Quito (coverage-guided generation), MorphQ (metamorphic testing), QuCheck (property-based testing and the statistical multiple-testing insight), and QUTest (native assertion testing). Its contribution is a native pytest integration layer with cross-framework ingestion and opt-in hardware validation, not a new testing paradigm.

License

MIT

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

qcoherence-1.0.0.tar.gz (18.3 kB view details)

Uploaded Source

Built Distribution

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

qcoherence-1.0.0-py3-none-any.whl (16.3 kB view details)

Uploaded Python 3

File details

Details for the file qcoherence-1.0.0.tar.gz.

File metadata

  • Download URL: qcoherence-1.0.0.tar.gz
  • Upload date:
  • Size: 18.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for qcoherence-1.0.0.tar.gz
Algorithm Hash digest
SHA256 429dfaa85a023e59551f72938514aa634fe79911d07a37f3d485e62327d6cc9c
MD5 d792e8f1755ba297f31588f4d1ef8cf2
BLAKE2b-256 9a0c31951e366e10d595c6da7de5a48e146c3677b44a672e8f47773223070706

See more details on using hashes here.

File details

Details for the file qcoherence-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: qcoherence-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 16.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for qcoherence-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c5ffe9b8cafec8f7422933decaf74ddb4aa9f2dc83479fd9f660f98ec07c238a
MD5 fb5a2b0af862b12d7d11a6bde619bee4
BLAKE2b-256 97658c162b01f6594b1a8fa7e64e8f41d03a591ea7fdfb046f3671eb92a05a3e

See more details on using hashes here.

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