Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ basetest = [
test = [
"sbd-eigensolver[basetest]",
"pytest-mpi>=0.6",
# The SQD integration tests drive qiskit-addon-sqd's own entry point, and read the
# reference Hamiltonian from a FCIDUMP with pyscf. Both are in the default test
# extra rather than an opt-in one so that `tox -e py` and `tox -e mpi` cover that
# path; the tests skip themselves if the imports are unavailable anyway.
"qiskit-addon-sqd>=0.13.1",
"pyscf>=2.9",
]
nbtest = [
"sbd-eigensolver[basetest]",
Expand Down
58 changes: 50 additions & 8 deletions test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
# initialized, so tests that need it are skipped rather than failing.
DATA_DIR = Path(__file__).resolve().parents[1] / "vendor" / "sbd-upstream" / "data"

# The curated h2o counts shipped with the examples. Unlike the reference data above this
# is part of the repository proper, so it is always present.
COUNTS_PATH = (
Path(__file__).resolve().parents[1] / "python" / "examples" / "count_dict_h2o.json"
)


# Slow tests are opt-in through a command-line flag rather than excluded by default,
# so that they are reported as skipped with a reason instead of silently deselected.
Expand Down Expand Up @@ -77,19 +83,55 @@ def pytest_report_header():
return f"sbd {sbd.__version__}: backends built {available}, testing {requested}"


@pytest.fixture(scope="session")
def backend():
"""The SBD backend to test, honoring SBD_TEST_DEVICE if it is set.
def _requested_device() -> str | None:
"""``SBD_TEST_DEVICE``, or ``None`` to mean whatever the build defaults to.

A backend named in ``SBD_TEST_DEVICE`` that was not compiled into this build is
reported as a skip, since which backends exist depends on how the package was
built. That a backend is missing is a fact about the build; that ``sbd`` itself is
missing is a failure, and is left to raise.
A backend named there but not compiled into this build is reported as a skip, since
which backends exist depends on how the package was built. That a backend is missing
is a fact about the build; that ``sbd`` itself is missing is a failure, and is left
to raise.
"""
import sbd

device = os.environ.get("SBD_TEST_DEVICE")
available = sbd.available_backends()
if device is not None and device not in available:
pytest.skip(f"backend {device!r} was not built; available: {available}")
return sbd.get_backend(device)
return device


@pytest.fixture(scope="session")
def backend():
"""The SBD backend module to test, for tests calling the extension directly."""
import sbd

return sbd.get_backend(_requested_device())


@pytest.fixture(scope="session")
def device_config():
"""The same selection as ``backend``, in the form the solver wrappers take.

``solve_sci`` and ``solve_sci_batch`` accept a ``DeviceConfig`` rather than a backend
module -- they resolve the module themselves from its ``device`` key -- so the two
fixtures exist to hand each layer the type it expects, off one shared setting.

``None`` when nothing is requested is deliberate: it leaves the wrapper's own backend
resolution in the path, which is what an ordinary caller gets.
"""
from sbd.device_config import DeviceConfig

device = _requested_device()
if device is None:
return None
# The generic constructor accepts every device key, including hyphenated ones like
# 'gpu-omp' that do not correspond to a classmethod name.
return DeviceConfig(device=device)


@pytest.fixture(scope="session")
def counts_path() -> Path:
"""Path to the curated h2o counts file used by the examples."""
if not COUNTS_PATH.is_file():
pytest.skip(f"counts file not found at {COUNTS_PATH}")
return COUNTS_PATH
Loading