Преглед изворни кода

Closes #21862: Stabilize ScriptModule tests and reduce CI noise (#21867)

Martin Hauser пре 18 часа
родитељ
комит
a93aae12fa
2 измењених фајлова са 40 додато и 9 уклоњено
  1. 24 7
      netbox/extras/tests/test_api.py
  2. 16 2
      netbox/extras/tests/test_views.py

+ 24 - 7
netbox/extras/tests/test_api.py

@@ -1,5 +1,6 @@
 import datetime
 import hashlib
+import io
 from unittest.mock import MagicMock, patch
 
 from django.contrib.contenttypes.models import ContentType
@@ -1013,10 +1014,14 @@ class ScriptTest(APITestCase):
 
     @classmethod
     def setUpTestData(cls):
-        module = ScriptModule.objects.create(
-            file_root=ManagedFileRootPathChoices.SCRIPTS,
-            file_path='script.py',
-        )
+        # Avoid trying to import a non-existent on-disk module during setup.
+        # This test creates the Script row explicitly and monkey-patches
+        # Script.python_class below.
+        with patch.object(ScriptModule, 'sync_classes'):
+            module = ScriptModule.objects.create(
+                file_root=ManagedFileRootPathChoices.SCRIPTS,
+                file_path='script.py',
+            )
         script = Script.objects.create(
             module=module,
             name='Test script',
@@ -1419,9 +1424,20 @@ class ScriptModuleTest(APITestCase):
         upload_file = SimpleUploadedFile('test_upload.py', script_content, content_type='text/plain')
         mock_storage = MagicMock()
         mock_storage.save.return_value = 'test_upload.py'
-        with patch('extras.api.serializers_.scripts.storages') as mock_storages:
-            mock_storages.create_storage.return_value = mock_storage
-            mock_storages.backends = {'scripts': {}}
+
+        # The upload serializer writes the file via storages.create_storage(...).save(),
+        # but ScriptModule.sync_classes() later imports it via storages["scripts"].open().
+        # Provide both behaviors so the uploaded module can actually be loaded during the test.
+        mock_storage.open.side_effect = lambda *args, **kwargs: io.BytesIO(script_content)
+
+        with (
+            patch('extras.api.serializers_.scripts.storages') as mock_serializer_storages,
+            patch('extras.models.mixins.storages') as mock_module_storages,
+        ):
+            mock_serializer_storages.create_storage.return_value = mock_storage
+            mock_serializer_storages.backends = {'scripts': {}}
+            mock_module_storages.__getitem__.return_value = mock_storage
+
             response = self.client.post(
                 self.url,
                 {'file': upload_file},
@@ -1432,6 +1448,7 @@ class ScriptModuleTest(APITestCase):
         self.assertEqual(response.data['file_path'], 'test_upload.py')
         mock_storage.save.assert_called_once()
         self.assertTrue(ScriptModule.objects.filter(file_path='test_upload.py').exists())
+        self.assertTrue(Script.objects.filter(module__file_path='test_upload.py', name='TestScript').exists())
 
     def test_upload_script_module_without_file_fails(self):
         self.add_permissions('extras.add_scriptmodule', 'core.add_managedfile')

+ 16 - 2
netbox/extras/tests/test_views.py

@@ -924,7 +924,14 @@ class ScriptValidationErrorTest(TestCase):
 
     @classmethod
     def setUpTestData(cls):
-        module = ScriptModule.objects.create(file_root=ManagedFileRootPathChoices.SCRIPTS, file_path='test_script.py')
+        # Avoid trying to import a non-existent on-disk module during setup.
+        # This test creates the Script row explicitly and monkey-patches
+        # Script.python_class below.
+        with patch.object(ScriptModule, 'sync_classes'):
+            module = ScriptModule.objects.create(
+                file_root=ManagedFileRootPathChoices.SCRIPTS,
+                file_path='test_script.py',
+            )
         cls.script = Script.objects.create(module=module, name='Test script', is_executable=True)
 
     def setUp(self):
@@ -986,7 +993,14 @@ class ScriptDefaultValuesTest(TestCase):
 
     @classmethod
     def setUpTestData(cls):
-        module = ScriptModule.objects.create(file_root=ManagedFileRootPathChoices.SCRIPTS, file_path='test_script.py')
+        # Avoid trying to import a non-existent on-disk module during setup.
+        # This test creates the Script row explicitly and monkey-patches
+        # Script.python_class below.
+        with patch.object(ScriptModule, 'sync_classes'):
+            module = ScriptModule.objects.create(
+                file_root=ManagedFileRootPathChoices.SCRIPTS,
+                file_path='test_script.py',
+            )
         cls.script = Script.objects.create(module=module, name='Test script', is_executable=True)
 
     def setUp(self):