From 79bf78cb3d0e0de87e8da41ce0d9d0f61bb9ffe2 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Tue, 26 May 2026 13:18:37 -0700 Subject: [PATCH 1/3] add some tests to validate the qsharp API surface --- .../tests/reexports/test_qsharp_shim.py | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 source/qdk_package/tests/reexports/test_qsharp_shim.py diff --git a/source/qdk_package/tests/reexports/test_qsharp_shim.py b/source/qdk_package/tests/reexports/test_qsharp_shim.py new file mode 100644 index 0000000000..0fe29c65a2 --- /dev/null +++ b/source/qdk_package/tests/reexports/test_qsharp_shim.py @@ -0,0 +1,93 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +"""Tests for the ``qsharp`` compatibility shim (source/pip). + +The ``qsharp`` package is a thin deprecation wrapper that re-exports the +public API from ``qdk``. These tests verify that the expected symbols and +submodules are accessible via ``import qsharp``. +""" + +import importlib +import warnings + +import pytest + +# ---- Symbols that must be directly accessible on ``qsharp`` ---- + +_EXPECTED_SYMBOLS = [ + # functions + "init", + "eval", + "run", + "compile", + "circuit", + "estimate", + "estimate_custom", + "logical_counts", + "set_quantum_seed", + "set_classical_seed", + "dump_machine", + "dump_circuit", + # types / classes + "Result", + "Pauli", + "QSharpError", + "TargetProfile", + "StateDump", + "ShotResult", + "PauliNoise", + "DepolarizingNoise", + "BitFlipNoise", + "PhaseFlipNoise", + "CircuitGenerationMethod", +] + +# Submodules that must be importable *and* accessible as attributes +# on the ``qsharp`` module after a bare ``import qsharp``. +_EXPECTED_SUBMODULES = [ + "code", + "estimator", +] + + +@pytest.fixture() +def qsharp_module(): + """Import the ``qsharp`` shim while suppressing the deprecation warning.""" + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + mod = importlib.import_module("qsharp") + return mod + + +def test_deprecation_warning_on_import(): + """Importing ``qsharp`` must emit a DeprecationWarning.""" + with warnings.catch_warnings(record=True) as caught: + warnings.simplefilter("always") + importlib.reload(importlib.import_module("qsharp")) + + deprecations = [w for w in caught if issubclass(w.category, DeprecationWarning)] + assert any("qsharp" in str(w.message) for w in deprecations) + + +@pytest.mark.parametrize("name", _EXPECTED_SYMBOLS) +def test_symbol_accessible(qsharp_module, name): + """Every expected symbol must be an attribute of ``qsharp``.""" + assert hasattr(qsharp_module, name), f"qsharp.{name} is missing" + + +@pytest.mark.parametrize("name", _EXPECTED_SUBMODULES) +def test_submodule_accessible_as_attribute(qsharp_module, name): + """Submodules like ``code`` must be reachable via ``qsharp.`` + without a separate ``from qsharp import ``.""" + attr = getattr(qsharp_module, name, None) + assert attr is not None, f"qsharp.{name} is not accessible as an attribute" + + +@pytest.mark.parametrize("name", _EXPECTED_SUBMODULES) +def test_submodule_importable(name): + """``from qsharp import `` must work.""" + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + mod = importlib.import_module(f"qsharp.{name}") + assert mod is not None From a30c1454a9724b90c9e36ba56db283cabad8e8e3 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Tue, 26 May 2026 15:03:09 -0700 Subject: [PATCH 2/3] install qsharp for test env as we have tests against qsharp now --- build.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/build.py b/build.py index d5a06d3c0c..60e9557062 100755 --- a/build.py +++ b/build.py @@ -514,6 +514,21 @@ def run_ci_historic_benchmark(): build_wheel(python_bin, pip_src, env=pip_env) step_end() + if run_tests and build_qdk: + step_start("Running tests for the qsharp compatibility shim") + # Use the qdk environment where qdk and test deps are already installed. + python_bin, pip_env = use_python_env(qdk_python_src) + + if not args.editable: + install_from_wheels(python_bin, "qsharp", cwd=pip_src) + + run_python_tests( + os.path.join(qdk_python_src, "tests", "reexports"), + python_bin, + pip_env, + ) + step_end() + if build_widgets: step_start("Building the Python widgets") From 0e25737b45d20f4c303d1ef4ff83ba41155154a7 Mon Sep 17 00:00:00 2001 From: Scott Carda Date: Tue, 26 May 2026 17:29:24 -0700 Subject: [PATCH 3/3] Change to tests live under qsharp --- build.py | 42 +++++++++++++------ .../tests}/test_qsharp_shim.py | 2 +- 2 files changed, 31 insertions(+), 13 deletions(-) rename source/{qdk_package/tests/reexports => pip/tests}/test_qsharp_shim.py (97%) diff --git a/build.py b/build.py index 60e9557062..a721f0ad36 100755 --- a/build.py +++ b/build.py @@ -514,20 +514,38 @@ def run_ci_historic_benchmark(): build_wheel(python_bin, pip_src, env=pip_env) step_end() - if run_tests and build_qdk: - step_start("Running tests for the qsharp compatibility shim") - # Use the qdk environment where qdk and test deps are already installed. - python_bin, pip_env = use_python_env(qdk_python_src) + if run_tests: + # The qsharp shim tests require qdk (with its native extension) to be + # installed. If qdk was built in this run it is already available; + # otherwise check the environment. + qdk_available = build_qdk + if not qdk_available: + python_bin_check, _ = use_python_env(qdk_python_src) + result = subprocess.run( + [python_bin_check, "-c", "import qdk"], + capture_output=True, + ) + qdk_available = result.returncode == 0 - if not args.editable: - install_from_wheels(python_bin, "qsharp", cwd=pip_src) + if qdk_available: + step_start("Running tests for the qsharp compatibility shim") + # Use the qdk environment where qdk and test deps are already installed. + python_bin, pip_env = use_python_env(qdk_python_src) - run_python_tests( - os.path.join(qdk_python_src, "tests", "reexports"), - python_bin, - pip_env, - ) - step_end() + if not args.editable: + install_from_wheels(python_bin, "qsharp", cwd=pip_src) + + run_python_tests( + os.path.join(pip_src, "tests"), + python_bin, + pip_env, + ) + step_end() + else: + print( + "Skipping qsharp shim tests: qdk is not installed. " + "Run with --qdk or install qdk first." + ) if build_widgets: diff --git a/source/qdk_package/tests/reexports/test_qsharp_shim.py b/source/pip/tests/test_qsharp_shim.py similarity index 97% rename from source/qdk_package/tests/reexports/test_qsharp_shim.py rename to source/pip/tests/test_qsharp_shim.py index 0fe29c65a2..674ae0e48b 100644 --- a/source/qdk_package/tests/reexports/test_qsharp_shim.py +++ b/source/pip/tests/test_qsharp_shim.py @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. -"""Tests for the ``qsharp`` compatibility shim (source/pip). +"""Tests for the ``qsharp`` compatibility shim. The ``qsharp`` package is a thin deprecation wrapper that re-exports the public API from ``qdk``. These tests verify that the expected symbols and