From bc3df08c77320b0d9842b4aa6d335f54566328c2 Mon Sep 17 00:00:00 2001 From: Jake Lishman Date: Wed, 20 Dec 2023 18:43:55 +0000 Subject: [PATCH] Remove most of `qiskit.test` This removes large tracts of `qiskit.test` that Qiskit itself is no longer using, or inlines a couple of components that were either exceptionally simple or used only once. A few tests that made heavier use of the removed features have been removed rather than replacing the functionality, since those had not actually been running due to dependencies on IBMQ that have not been fulfilled for a long time. This prepares for a more complete removal of `qiskit.test`, if we choose to, but such a change raises the possibility of rather more merge conflicts (due to the need to touch every test file), so is best done separately. --- qiskit/test/__init__.py | 4 +- qiskit/test/base.py | 35 +++---- qiskit/test/decorators.py | 92 +----------------- qiskit/test/providers/__init__.py | 16 ---- qiskit/test/providers/backend.py | 75 --------------- qiskit/test/providers/provider.py | 59 ------------ qiskit/test/reference_circuits.py | 41 -------- qiskit/test/testing_options.py | 93 ------------------- qiskit/test/utils.py | 87 ----------------- .../remove-qiskit-test-8f3f43ed2a185f2f.yaml | 7 ++ test/__init__.py | 23 ++++- test/python/basicaer/__init__.py | 30 ++++++ .../python/basicaer/test_basicaer_backends.py | 20 +++- test/python/basicaer/test_qasm_simulator.py | 14 ++- .../basicaer/test_statevector_simulator.py | 27 ++++-- .../python/basicaer/test_unitary_simulator.py | 16 +++- 16 files changed, 135 insertions(+), 504 deletions(-) delete mode 100644 qiskit/test/providers/__init__.py delete mode 100644 qiskit/test/providers/backend.py delete mode 100644 qiskit/test/providers/provider.py delete mode 100644 qiskit/test/reference_circuits.py delete mode 100644 qiskit/test/testing_options.py delete mode 100644 qiskit/test/utils.py create mode 100644 releasenotes/notes/remove-qiskit-test-8f3f43ed2a185f2f.yaml diff --git a/qiskit/test/__init__.py b/qiskit/test/__init__.py index 09a9a6c22d0f..80213dc7d733 100644 --- a/qiskit/test/__init__.py +++ b/qiskit/test/__init__.py @@ -13,6 +13,4 @@ """Functionality and helpers for testing Qiskit.""" from .base import QiskitTestCase -from .decorators import requires_aer_provider, slow_test -from .reference_circuits import ReferenceCircuits -from .utils import Path +from .decorators import slow_test diff --git a/qiskit/test/base.py b/qiskit/test/base.py index ab1f011a7bb3..5e3a0cb6c6dc 100644 --- a/qiskit/test/base.py +++ b/qiskit/test/base.py @@ -33,7 +33,6 @@ from qiskit.utils import optionals as _optionals from qiskit.circuit import QuantumCircuit from .decorators import enforce_subclasses_call -from .utils import Path, setup_test_logging __unittest = True # Allows shorter stack trace for .assertDictAlmostEqual @@ -100,19 +99,6 @@ def tearDown(self): ) self.__teardown_called = True - @staticmethod - def _get_resource_path(filename, path=Path.TEST): - """Get the absolute path to a resource. - - Args: - filename (string): filename or relative path to the resource. - path (Path): path used as relative to the filename. - - Returns: - str: the absolute path to the resource. - """ - return os.path.normpath(os.path.join(path.value, filename)) - def assertQuantumCircuitEqual(self, qc1, qc2, msg=None): """Extra assertion method to give a better error message when two circuits are unequal.""" if qc1 == qc2: @@ -195,9 +181,24 @@ def setUpClass(cls): super().setUpClass() # Set logging to file and stdout if the LOG_LEVEL envar is set. cls.log = logging.getLogger(cls.__name__) - if os.getenv("LOG_LEVEL"): - filename = "%s.log" % os.path.splitext(inspect.getfile(cls))[0] - setup_test_logging(cls.log, os.getenv("LOG_LEVEL"), filename) + + if log_level := os.getenv("LOG_LEVEL"): + log_fmt = f"{cls.log.name}.%(funcName)s:%(levelname)s:%(asctime)s: %(message)s" + formatter = logging.Formatter(log_fmt) + file_handler = logging.FileHandler(f"{os.path.splitext(inspect.getfile(cls))[0]}.log") + file_handler.setFormatter(formatter) + cls.log.addHandler(file_handler) + + if os.getenv("STREAM_LOG"): + # Set up the stream handler. + stream_handler = logging.StreamHandler() + stream_handler.setFormatter(formatter) + cls.log.addHandler(stream_handler) + + # Set the logging level from the environment variable, defaulting + # to INFO if it is not a valid level. + level = logging._nameToLevel.get(log_level, logging.INFO) + cls.log.setLevel(level) warnings.filterwarnings("error", category=DeprecationWarning) warnings.filterwarnings("error", category=QiskitWarning) diff --git a/qiskit/test/decorators.py b/qiskit/test/decorators.py index c4ca9c67459f..bd250f99b9c2 100644 --- a/qiskit/test/decorators.py +++ b/qiskit/test/decorators.py @@ -13,68 +13,12 @@ """Decorator for using with Qiskit unit tests.""" -import collections.abc import functools -import socket -import sys -from typing import Union, Callable, Type, Iterable +import os import unittest +from typing import Union, Callable, Type, Iterable from qiskit.utils import wrap_method -from .testing_options import get_test_options - -HAS_NET_CONNECTION = None - - -def _has_connection(hostname, port): - """Checks if internet connection exists to host via specified port. - - If any exception is raised while trying to open a socket this will return - false. - - Args: - hostname (str): Hostname to connect to. - port (int): Port to connect to - - Returns: - bool: Has connection or not - - """ - try: - host = socket.gethostbyname(hostname) - socket.create_connection((host, port), 2).close() - return True - except Exception: # pylint: disable=broad-except - return False - - -def is_aer_provider_available(): - """Check if the C++ simulator can be instantiated. - - Returns: - bool: True if simulator executable is available - """ - # TODO: HACK FROM THE DEPTHS OF DESPAIR AS AER DOES NOT WORK ON MAC - if sys.platform == "darwin": - return False - try: - import qiskit.providers.aer # pylint: disable=unused-import - except ImportError: - return False - return True - - -def requires_aer_provider(test_item): - """Decorator that skips test if qiskit aer provider is not available - - Args: - test_item (callable): function or class to be decorated. - - Returns: - callable: the decorated function. - """ - reason = "Aer provider not found, skipping test" - return unittest.skipIf(not is_aer_provider_available(), reason)(test_item) def slow_test(func): @@ -89,10 +33,8 @@ def slow_test(func): @functools.wraps(func) def _wrapper(*args, **kwargs): - skip_slow = not TEST_OPTIONS["run_slow"] - if skip_slow: + if "run_slow" in os.environ.get("QISKIT_TESTS", ""): raise unittest.SkipTest("Skipping slow tests") - return func(*args, **kwargs) return _wrapper @@ -192,31 +134,3 @@ def decorator(cls): return cls return decorator - - -class _TestOptions(collections.abc.Mapping): - """Lazy-loading view onto the test options retrieved from the environment.""" - - __slots__ = ("_options",) - - def __init__(self): - self._options = None - - def _load(self): - if self._options is None: - self._options = get_test_options() - - def __getitem__(self, key): - self._load() - return self._options[key] - - def __iter__(self): - self._load() - return iter(self._options) - - def __len__(self): - self._load() - return len(self._options) - - -TEST_OPTIONS = _TestOptions() diff --git a/qiskit/test/providers/__init__.py b/qiskit/test/providers/__init__.py deleted file mode 100644 index 73c3a1dae785..000000000000 --- a/qiskit/test/providers/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# This code is part of Qiskit. -# -# (C) Copyright IBM 2017, 2019. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - -"""Base TestCases for provider and backends.""" - -from .backend import BackendTestCase -from .provider import ProviderTestCase diff --git a/qiskit/test/providers/backend.py b/qiskit/test/providers/backend.py deleted file mode 100644 index 83832b8a29e7..000000000000 --- a/qiskit/test/providers/backend.py +++ /dev/null @@ -1,75 +0,0 @@ -# This code is part of Qiskit. -# -# (C) Copyright IBM 2017, 2019. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - -"""Base TestCase for testing backends.""" - -from unittest import SkipTest - -from qiskit import execute -from ..base import QiskitTestCase -from ..reference_circuits import ReferenceCircuits - - -class BackendTestCase(QiskitTestCase): - """Test case for backends. - - Implementers of backends are encouraged to subclass and customize this - TestCase, as it contains a "canonical" series of tests in order to ensure - the backend functionality matches the specifications. - - Members: - backend_cls (BaseBackend): backend to be used in this test case. Its - instantiation can be further customized by overriding the - ``_get_backend`` function. - circuit (QuantumCircuit): circuit to be used for the tests. - """ - - backend_cls = None - circuit = ReferenceCircuits.bell() - - def setUp(self): - super().setUp() - self.backend = self._get_backend() - - @classmethod - def setUpClass(cls): - if cls is BackendTestCase: - raise SkipTest("Skipping base class tests") - super().setUpClass() - - def _get_backend(self): - """Return an instance of a Provider.""" - return self.backend_cls() # pylint: disable=not-callable - - def test_configuration(self): - """Test backend.configuration().""" - configuration = self.backend.configuration() - return configuration - - def test_properties(self): - """Test backend.properties().""" - properties = self.backend.properties() - if self.backend.configuration().simulator: - self.assertEqual(properties, None) - return properties - - def test_status(self): - """Test backend.status().""" - status = self.backend.status() - return status - - def test_run_circuit(self): - """Test running a single circuit.""" - job = execute(self.circuit, self.backend) - result = job.result() - self.assertEqual(result.success, True) - return result diff --git a/qiskit/test/providers/provider.py b/qiskit/test/providers/provider.py deleted file mode 100644 index 8170ae35859b..000000000000 --- a/qiskit/test/providers/provider.py +++ /dev/null @@ -1,59 +0,0 @@ -# This code is part of Qiskit. -# -# (C) Copyright IBM 2017, 2019. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - -"""Base TestCase for testing Providers.""" - -from unittest import SkipTest - -from ..base import QiskitTestCase - - -class ProviderTestCase(QiskitTestCase): - """Test case for Providers. - - Implementers of providers are encouraged to subclass and customize this - TestCase, as it contains a "canonical" series of tests in order to ensure - the provider functionality matches the specifications. - - Members: - provider_cls (BaseProvider): provider to be used in this test case. Its - instantiation can be further customized by overriding the - ``_get_provider`` function. - backend_name (str): name of a backend provided by the provider. - """ - - provider_cls = None - backend_name = "" - - def setUp(self): - super().setUp() - self.provider = self._get_provider() - - @classmethod - def setUpClass(cls): - if cls is ProviderTestCase: - raise SkipTest("Skipping base class tests") - super().setUpClass() - - def _get_provider(self): - """Return an instance of a Provider.""" - return self.provider_cls() # pylint: disable=not-callable - - def test_backends(self): - """Test the provider has backends.""" - backends = self.provider.backends() - self.assertTrue(len(backends) > 0) - - def test_get_backend(self): - """Test getting a backend from the provider.""" - backend = self.provider.get_backend(name=self.backend_name) - self.assertEqual(backend.name(), self.backend_name) diff --git a/qiskit/test/reference_circuits.py b/qiskit/test/reference_circuits.py deleted file mode 100644 index 8b94dfa89a28..000000000000 --- a/qiskit/test/reference_circuits.py +++ /dev/null @@ -1,41 +0,0 @@ -# This code is part of Qiskit. -# -# (C) Copyright IBM 2017, 2019. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - -"""Reference circuits used by the tests.""" - -from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister - - -class ReferenceCircuits: - """Container for reference circuits used by the tests.""" - - @staticmethod - def bell(): - """Return a Bell circuit.""" - qr = QuantumRegister(2, name="qr") - cr = ClassicalRegister(2, name="qc") - qc = QuantumCircuit(qr, cr, name="bell") - qc.h(qr[0]) - qc.cx(qr[0], qr[1]) - qc.measure(qr, cr) - - return qc - - @staticmethod - def bell_no_measure(): - """Return a Bell circuit.""" - qr = QuantumRegister(2, name="qr") - qc = QuantumCircuit(qr, name="bell_no_measure") - qc.h(qr[0]) - qc.cx(qr[0], qr[1]) - - return qc diff --git a/qiskit/test/testing_options.py b/qiskit/test/testing_options.py deleted file mode 100644 index 0ecd8beea15d..000000000000 --- a/qiskit/test/testing_options.py +++ /dev/null @@ -1,93 +0,0 @@ -# This code is part of Qiskit. -# -# (C) Copyright IBM 2017, 2018. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - -"""Obtain and set the options in QISKIT_TESTS, used for running the tests.""" - -import os -import logging - -logger = logging.getLogger(__name__) - - -def get_test_options(option_var="QISKIT_TESTS"): - """Read option_var from env and returns a dict in which the test options are set. - - Args: - option_var (str): The env var to read. Default: 'QISKIT_TESTS' - - Returns: - dict: A dictionary with the format {