Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove most of qiskit.test #11445

Merged
merged 1 commit into from
Jan 15, 2024
Merged

Conversation

jakelishman
Copy link
Member

@jakelishman jakelishman commented Dec 20, 2023

Summary

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.

Details and comments

This is effectively a rework of most of #10998 (which I forgot existed when I started doing this), but separates out the concerns a little bit. This PR severely trims down the content of qiskit.test without moving any of the remaining content - we can do that in a follow-up if we choose to, but we don't technically need to.

We can technically leave qiskit.test in place after its "removal", because it's not documented, so is not part of our public interface. If we do choose to remove it completely, and move its remaining components to the test "package" (like #10998 does), it's probably better to do that step in a separate PR, since it touches every single test file in the repo, so is at large risk of merge conflicts.

Relevant deprecations are in #11001.


You can see what's left in qiskit.test here. Everything in there is suitable for moving to the test.python root, though pragmatically, I think there might be some dynamic-circuits tests in IBM-internal code that use the canonicalisation in qiskit.test._canonical. For the most part, those changes are no longer necessary as QuantumCircuit.__eq__ now does most of the canonicalisation on-the-fly during the comparison.

@jakelishman jakelishman added type: qa Issues and PRs that relate to testing and code quality Changelog: Removal Include in the Removed section of the changelog labels Dec 20, 2023
@jakelishman jakelishman added this to the 1.0.0 milestone Dec 20, 2023
@jakelishman jakelishman requested review from jyu00 and a team as code owners December 20, 2023 18:51
@qiskit-bot
Copy link
Collaborator

One or more of the the following people are requested to review this:

  • @Qiskit/terra-core

@jakelishman jakelishman mentioned this pull request Dec 20, 2023
@jakelishman jakelishman force-pushed the remove-test-decorators branch from 0fe2844 to b6d9fd4 Compare December 20, 2023 19:06
Copy link
Member Author

@jakelishman jakelishman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's all the changes to and where they went / why.

Comment on lines -102 to -114
@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))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't used.

qiskit/test/base.py Outdated Show resolved Hide resolved
qiskit/test/decorators.py Outdated Show resolved Hide resolved
Comment on lines -283 to -222
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()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inlined the one use of this still in use - checking if run_slow is in the QISKIT_TESTS environment variable.

Comment on lines -22 to -75
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
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved this to be BasicAerBackendTestMixin in test.python.basicaer, which is the only place it's used within Qiskit.

Comment on lines -38 to -64
def setup_test_logging(logger, log_level, filename):
"""Set logging to file and stdout for a logger.

Args:
logger (Logger): logger object to be updated.
log_level (str): logging level.
filename (str): name of the output file.
"""
# Set up formatter.
log_fmt = f"{logger.name}.%(funcName)s:%(levelname)s:%(asctime)s: %(message)s"
formatter = logging.Formatter(log_fmt)

# Set up the file handler.
file_handler = logging.FileHandler(filename)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)

if os.getenv("STREAM_LOG"):
# Set up the stream handler.
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(formatter)
logger.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)
logger.setLevel(level)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inlined into QiskitTestCase.setUpClass.

Comment on lines -67 to -87
class Case(dict):
"""<no description>"""

pass


def generate_cases(docstring, dsc=None, name=None, **kwargs):
"""Combines kwargs in Cartesian product and creates Case with them"""
ret = []
keys = kwargs.keys()
vals = kwargs.values()
for values in product(*vals):
case = Case(zip(keys, values))
if docstring is not None:
setattr(case, "__doc__", docstring.format(**case))
if dsc is not None:
setattr(case, "__doc__", dsc.format(**case))
if name is not None:
setattr(case, "__name__", name.format(**case))
ret.append(case)
return ret
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to test/__init__.py, which is the only place it was used.

Comment on lines -20 to -59
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)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inlined into the BasicAer provider test, which was the only user.

test/python/test_examples.py Outdated Show resolved Hide resolved
test/python/tools/jupyter/test_notebooks.py Outdated Show resolved Hide resolved
@coveralls
Copy link

coveralls commented Dec 20, 2023

Pull Request Test Coverage Report for Build 7502969833

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.03%) to 89.367%

Totals Coverage Status
Change from base Build 7495874156: 0.03%
Covered Lines: 59264
Relevant Lines: 66315

💛 - Coveralls

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.
@jakelishman jakelishman force-pushed the remove-test-decorators branch from b6d9fd4 to bc3df08 Compare January 12, 2024 13:43
@jakelishman
Copy link
Member Author

Now rebased over #11513.

@1ucian0 1ucian0 self-assigned this Jan 12, 2024
Copy link
Member

@1ucian0 1ucian0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.. such a nice cleaning up feeling :)

@1ucian0 1ucian0 added this pull request to the merge queue Jan 15, 2024
@jakelishman
Copy link
Member Author

Yeah, it's a nice feeling now until we have to deal with all the little bits and bobs all over the place that things like the IBM Runtime are using and we didn't know about... :(.

But at least we've the promise of reduced maintenance burden down the road; getting all this stuff cleaned up improves loads of stuff for us across the board - less to keep updated with changing libraries and Python versions, less to run pylint against on every CI job, less stuff in the test suite burning CPU cycles for no gain, etc etc.

@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Jan 15, 2024
@1ucian0 1ucian0 added this pull request to the merge queue Jan 15, 2024
@1ucian0
Copy link
Member

1ucian0 commented Jan 15, 2024

Yeah, it's a nice feeling now until we have to deal with all the little bits and bobs all over the place that things like the IBM Runtime are using and we didn't know about... :(.

Hopefully, we learn about then soon, as some dependants check against main.

Merged via the queue into Qiskit:main with commit 75c30e2 Jan 15, 2024
13 checks passed
@jakelishman jakelishman deleted the remove-test-decorators branch January 15, 2024 15:54
ShellyGarion pushed a commit to ShellyGarion/qiskit-terra that referenced this pull request Jan 18, 2024
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: Removal Include in the Removed section of the changelog type: qa Issues and PRs that relate to testing and code quality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants