Răsfoiți Sursa

Skip test_crud_instance for mock/moto 5.x

moto 5.x has a regression in the EC2 backend where DescribeInstances
returns an empty list immediately after RunInstances completes, so
`tests/helpers/standard_interface_tests.check_list` cannot find the
just-created instance and fails the test. A secondary symptom shows
up in cleanup, where the post-delete state lingers as "deleted"
instead of moving to UNKNOWN. Last observed on moto 5.2.1 in the
mock matrix cell.

Add a `skipIfMockMotoVersion(spec, reason)` helper alongside the
existing `skipIfNoService` / `skipIfPython` decorators. It reads the
installed moto version via `importlib.metadata` and matches against
a PEP 440 specifier (`packaging.specifiers.SpecifierSet`). Real-cloud
matrix cells (aws / azure / gcp / openstack) always run the test;
mock runs it normally when moto sits outside the broken range, so
tightening the specifier to `">=5.0.0,<5.X"` when an upstream fix
lands re-enables the test automatically with no further code change.

`packaging` is added explicitly to `REQS_DEV`. moto already pulls it
in transitively, but relying on a transitive is brittle and the IDE
type-checker also could not resolve it.
Nuwan Goonasekera 8 ore în urmă
părinte
comite
98e3bfa11e
3 a modificat fișierele cu 40 adăugiri și 0 ștergeri
  1. 1 0
      setup.py
  2. 30 0
      tests/helpers/__init__.py
  3. 9 0
      tests/test_compute_service.py

+ 1 - 0
setup.py

@@ -68,6 +68,7 @@ REQS_DEV = ([
     'tox>=4.0.0',
     'pytest',
     'moto[ec2,s3]>=5.0.0',
+    'packaging',
     'sphinx>=1.3.1',
     'pydevd',
     'flake8>=3.3.0',

+ 30 - 0
tests/helpers/__init__.py

@@ -44,6 +44,36 @@ def skipIfNoService(services):
     return wrap
 
 
+def skipIfMockMotoVersion(spec, reason):
+    """
+    A decorator for skipping tests when running against the mock
+    provider and the installed moto version matches `spec` (a
+    PEP 440 specifier string such as ">=5.0,<5.3"). Other providers
+    (aws / azure / gcp / openstack) always run the test, and the mock
+    provider runs it normally when moto sits outside the broken range.
+    """
+    def wrap(func):
+        @functools.wraps(func)
+        def wrapper(self, *args, **kwargs):
+            provider = getattr(self, 'provider', None)
+            if provider and getattr(provider, 'PROVIDER_ID', None) == 'mock':
+                from importlib.metadata import PackageNotFoundError
+                from importlib.metadata import version as get_version
+                from packaging.specifiers import SpecifierSet
+                from packaging.version import Version
+                try:
+                    moto_version = Version(get_version('moto'))
+                except PackageNotFoundError:
+                    moto_version = None
+                if moto_version and moto_version in SpecifierSet(spec):
+                    self.skipTest(
+                        "Skipping for mock/moto %s matching %s: %s"
+                        % (moto_version, spec, reason))
+            func(self, *args, **kwargs)
+        return wrapper
+    return wrap
+
+
 def skipIfPython(op, major, minor):
     """
     A decorator for skipping tests if the python

+ 9 - 0
tests/test_compute_service.py

@@ -33,6 +33,15 @@ class CloudComputeServiceTestCase(ProviderTestBase):
                                      self.provider.compute.instances.
                                      _service_event_pattern))
 
+    # moto 5.x regression: DescribeInstances returns an empty list
+    # immediately after RunInstances completes, so the list-after-create
+    # check in standard_interface_tests.check_list fails. A secondary
+    # symptom shows in cleanup, where post-delete state remains
+    # "deleted" instead of becoming UNKNOWN. Last observed on moto
+    # 5.2.1. Tighten the specifier when an upstream fix lands.
+    @helpers.skipIfMockMotoVersion(
+        ">=5.0.0",
+        "moto 5.x RunInstances/DescribeInstances state-sync bug")
     @helpers.skipIfNoService(['compute.instances', 'networking.networks'])
     def test_crud_instance(self):
         label = "cb-instcrud-{0}".format(helpers.get_uuid())