Skip to content

Testing

QPyth has a comprehensive test suite with 100% code coverage. This document explains how to run tests and write new tests.

Running Tests

Run All Tests

pytest

Run with Coverage

pytest --cov=quantumpytho --cov-report=html

This generates an HTML coverage report in htmlcov/index.html.

Run Specific Test File

pytest tests/test_bloch_ascii.py

Run Specific Test

pytest tests/test_bloch_ascii.py::test_one_qubit_from_angles

Run Tests Matching Pattern

pytest -k "bloch"

Run Tests in Parallel

pytest -n auto

Skip Slow Tests

pytest -m "not slow"

Run Integration Tests Only

pytest -m integration

Test Organization

tests/
├── test_bloch_ascii.py          # Bloch sphere tests
├── test_bloch_ascii_run.py      # Bloch ASCII runner tests
├── test_circuit_explorer.py     # Circuit explorer tests
├── test_config.py               # Configuration tests
├── test_decoherence_toggle.py   # Decoherence tests
├── test_hardware_ibm.py         # IBM hardware tests
├── test_main.py                 # Main module tests
├── test_menu.py                 # CLI menu tests
├── test_qec_shor.py             # Shor code tests
├── test_qec_steane.py           # Steane code tests
├── test_qrng_sacred.py          # QRNG tests
├── test_smoke.py                # Smoke tests
├── test_teleport_bridge.py      # Teleportation tests
├── test_tmt_sierpinski.py       # Sierpinski tests
├── test_vqe_core.py             # VQE core tests
├── test_vqe_h2.py               # H2 VQE tests
├── test_vqe_h2_cli.py           # H2 VQE CLI tests
├── test_vqe_h2_exact.py         # H2 VQE exact tests
├── test_vqe_h2_extra.py         # H2 VQE extra tests
├── test_vqe_molecules.py        # Molecule tests
└── test_vqe_utils.py            # VQE utility tests

Writing Tests

Basic Test Structure

import pytest
from quantumpytho.modules.bloch_ascii import run_bloch_ascii

def test_run_bloch_ascii_zero_state(capsys):
    """Test Bloch visualization for |0⟩ state."""
    run_bloch_ascii(theta=0, phi=0)
    captured = capsys.readouterr()
    assert "|0> state:" in captured.out
    assert "100.00%" in captured.out

Using Fixtures

import pytest
from qiskit import QuantumCircuit

@pytest.fixture
def bell_circuit():
    """Create a Bell pair circuit."""
    qc = QuantumCircuit(2)
    qc.h(0)
    qc.cx(0, 1)
    qc.measure_all()
    return qc

def test_bell_circuit_structure(bell_circuit):
    """Test Bell circuit has correct structure."""
    assert bell_circuit.num_qubits == 2
    assert bell_circuit.depth() == 2

Mocking External Dependencies

import pytest
from unittest.mock import Mock, patch
from quantumpytho.modules.hardware_ibm import IBMHardwareEngine

def test_connect_with_mock():
    """Test connection with mocked IBM service."""
    with patch('quantumpytho.modules.hardware_ibm.QiskitRuntimeService') as mock_service:
        mock_instance = Mock()
        mock_service.return_value = mock_instance

        engine = IBMHardwareEngine()
        engine.connect()

        mock_service.assert_called_once()

Parameterized Tests

import pytest

@pytest.mark.parametrize("theta,phi,expected", [
    (0, 0, "|0⟩"),
    (3.14159, 0, "|1⟩"),
    (1.5708, 0, "|+⟩"),
])
def test_bloch_states(theta, phi, expected):
    """Test various Bloch sphere states."""
    from quantumpytho.modules.bloch_ascii import run_bloch_ascii
    run_bloch_ascii(theta=theta, phi=phi)
    # Assert expected behavior

Testing Exceptions

import pytest

def test_invalid_input_raises_error():
    """Test that invalid input raises appropriate error."""
    from quantumpytho.modules.bloch_ascii import run_bloch_ascii

    with pytest.raises(ValueError):
        run_bloch_ascii(theta=10, phi=0)  # Invalid theta

Testing Async Code

import pytest
import asyncio

@pytest.mark.asyncio
async def test_async_function():
    """Test async function."""
    result = await async_function()
    assert result is not None

Test Markers

QPyth uses pytest markers for test categorization. These markers help organize tests and allow selective execution, which is particularly useful for CI pipelines.

Available Markers

@pytest.mark.slow
def test_slow_operation():
    """Test that takes a long time (e.g., quantum simulation with many shots)."""
    pass

@pytest.mark.integration
def test_hardware_integration():
    """Test that requires hardware access."""
    pass

Slow Tests

The @pytest.mark.slow marker is used for tests that take longer to execute, typically those involving quantum simulations with many shots or complex circuits:

@pytest.mark.slow
def test_teleport_measurement_distribution():
    """Test teleportation measurement distribution (slow test)."""
    qc = build_teleport_circuit()
    backend = AerSimulator()
    job = backend.run(qc, shots=1000)
    result = job.result()
    counts = result.get_counts(qc)
    assert len(counts) > 0

Current slow tests include: - test_bloch_ascii.py::test_bloch_ascii_run - ASCII visualization tests - test_qec_shor.py::test_shor_qec_demo - Shor code error correction - test_qec_steane.py::test_steane_qec_demo - Steane code error correction - test_teleport_bridge.py::test_teleport_measurement_distribution - Teleportation - test_vqe_h2.py::test_vqe_h2 - VQE molecular simulation - test_qrng_sacred.py::test_qrng_sacred - Quantum random number generation

Running Specific Markers

Run only slow tests:

pytest -m slow

Skip slow tests (useful for quick feedback):

pytest -m "not slow"

Run integration tests:

pytest -m integration

Run all tests except slow ones:

pytest -m "not slow"

CI Configuration

In CI pipelines, it's good practice to:

  1. Run fast tests first for quick feedback:

    pytest -m "not slow" --cov=quantumpytho
    

  2. Run slow tests separately (can be in a parallel job):

    pytest -m slow --cov=quantumpytho
    

  3. Combine coverage from both runs for complete reporting

This approach allows developers to get quick feedback on most changes while ensuring comprehensive testing before merging.

Coverage Goals

QPyth maintains 100% code coverage. To check coverage:

pytest --cov=quantumpytho --cov-report=term-missing

This shows which lines are not covered by tests.

Continuous Integration

Tests run automatically on GitHub Actions for every push and pull request. The CI pipeline:

  1. Runs all tests
  2. Checks code coverage (must be 100%)
  3. Runs linter (ruff)
  4. Checks code formatting

Debugging Tests

Run Tests in Debug Mode

pytest --pdb

This drops into pdb on failure.

pytest -s

This shows print statements.

Verbose Output

pytest -v

This shows detailed test information.

Stop on First Failure

pytest -x

Best Practices

  1. Test Isolation - Each test should be independent
  2. Descriptive Names - Use clear, descriptive test names
  3. Arrange-Act-Assert - Structure tests clearly
  4. Mock External Dependencies - Don't rely on external services
  5. Test Edge Cases - Test boundary conditions and error cases
  6. Keep Tests Fast - Use markers for slow tests
  7. Use Fixtures - Reuse common setup code
  8. Test Public API - Focus on public interfaces, not implementation details

Example Test Suite

import pytest
from quantumpytho.modules.bloch_ascii import run_bloch_ascii

class TestBlochAscii:
    """Test suite for Bloch ASCII visualization."""

    def test_zero_state(self, capsys):
        """Test |0⟩ state visualization."""
        run_bloch_ascii(theta=0, phi=0)
        captured = capsys.readouterr()
        assert "|0> state:" in captured.out
        assert "100.00%" in captured.out

    def test_one_state(self, capsys):
        """Test |1⟩ state visualization."""
        run_bloch_ascii(theta=3.14159, phi=0)
        captured = capsys.readouterr()
        assert "|1> state:" in captured.out
        assert "100.00%" in captured.out

    def test_plus_state(self, capsys):
        """Test |+⟩ state visualization."""
        run_bloch_ascii(theta=1.5708, phi=0)
        captured = capsys.readouterr()
        assert "|0> state:" in captured.out
        assert "|1> state:" in captured.out

    @pytest.mark.parametrize("theta,phi", [
        (0, 0),
        (3.14159, 0),
        (1.5708, 0),
        (1.5708, 1.5708),
    ])
    def test_various_states(self, theta, phi, capsys):
        """Test various quantum states."""
        run_bloch_ascii(theta=theta, phi=phi)
        captured = capsys.readouterr()
        assert "State Vector Projection" in captured.out

    def test_invalid_theta_raises_error(self):
        """Test that invalid theta raises error."""
        with pytest.raises(ValueError):
            run_bloch_ascii(theta=10, phi=0)

Troubleshooting

Import Errors

If you get import errors:

pip install -e .[dev,physical,web,hardware]

Missing Dependencies

If tests fail due to missing dependencies:

pip install -e .[dev,physical,web,hardware]

Coverage Not 100%

If coverage is not 100%:

  1. Run coverage report: pytest --cov=quantumpytho --cov-report=html
  2. Open htmlcov/index.html in browser
  3. Find uncovered lines
  4. Write tests for uncovered code

Tests Failing Randomly

If tests are flaky:

  1. Check for external dependencies
  2. Mock external services
  3. Use deterministic random seeds
  4. Check for race conditions

Resources

Next Steps