Quickstart

This page walks you from a fresh install to four passing quantum tests in under five minutes. Every snippet here is a real test you can copy into a file and run with pytest.

Install qtest

pip install qtest-quantum

That gives you the assertions, the pytest plugin, and the Qiskit backend. If you want Hypothesis-driven property tests, install the extra:

pip install "qtest-quantum[hypothesis]"

Your first quantum test

A Bell state should produce a 50/50 distribution over 00 and 11. assert_distribution_close knows about shot noise — you give it a tolerance, not an exact count.

# test_bell.py
from qiskit import QuantumCircuit
from qtest import assert_distribution_close

def test_bell_state_is_balanced():
    qc = QuantumCircuit(2)
    qc.h(0)
    qc.cx(0, 1)
    qc.measure_all()

    assert_distribution_close(
        qc,
        expected={"00": 0.5, "11": 0.5},
        shots=4096,
        tolerance=0.03,
    )

Run it:

pytest test_bell.py -v

No mocking, no manual backend setup — assert_distribution_close runs the circuit on qtest’s default backend internally, with the seed and tolerance configured via the pytest plugin’s CLI flags.

Asserting on state vectors

For unit tests of single gates, state-vector comparisons are sharper than sampling. qtest.assert_state_close() handles global phase for you.

from qiskit import QuantumCircuit
from qtest import assert_state_close

def test_hadamard_produces_plus_state():
    qc = QuantumCircuit(1)
    qc.h(0)

    # Named reference states ("plus", "minus", "bell", ...) are
    # built in. Global phase is ignored by default.
    assert_state_close(qc, expected_state="plus", tolerance=1e-10)

Verifying that two circuits are equivalent

When you refactor a circuit — say, replacing a sub-routine with an optimised version — you want to confirm it still implements the same unitary up to global phase.

from qiskit import QuantumCircuit
from qtest import assert_circuit_equivalent

def test_two_cnot_decompositions_are_equivalent():
    qc1 = QuantumCircuit(2)
    qc1.cx(0, 1)

    qc2 = QuantumCircuit(2)
    qc2.h(1)
    qc2.cz(0, 1)
    qc2.h(1)

    assert_circuit_equivalent(qc1, qc2, tolerance=1e-10)

Property-based testing with Hypothesis

Real quantum tests aren’t just “this circuit produces this output” — they encode invariants. Hypothesis lets you assert those invariants over many random circuits at once.

from hypothesis import given, settings
from qtest import assert_unitary
from qtest.strategies import quantum_circuits

@given(circuit=quantum_circuits(min_qubits=2, max_qubits=4, max_depth=8))
@settings(deadline=None, max_examples=50)
def test_any_unitary_circuit_is_unitary(circuit):
    assert_unitary(circuit, tolerance=1e-9)

That single test executes against dozens of random unitary circuits per run. When it fails, Hypothesis shrinks the failing circuit to the smallest reproducer — which is exactly what you want when debugging a gate-level bug.

Configuring the plugin from the command line

The pytest plugin exposes three flags that apply to every test in the session:

pytest -v \
    --qtest-shots 8192 \
    --qtest-tolerance 0.02 \
    --qtest-seed 12345

This is how you tune CI: higher shot counts and tighter tolerances on nightly runs, faster defaults on PR runs. See pytest integration for the full configuration model.

Next steps