]> git-server-git.apps.pok.os.sepia.ceph.com Git - teuthology.git/commitdiff
scripts/tests: Speed up tests with importlib scripts-tests 2214/head
authorZack Cerza <zack@cerza.org>
Sat, 30 May 2026 04:46:24 +0000 (22:46 -0600)
committerZack Cerza <zack@cerza.org>
Tue, 2 Jun 2026 19:42:59 +0000 (13:42 -0600)
These take one second instead of 31.

Signed-off-by: Zack Cerza <zack@cerza.org>
13 files changed:
scripts/test/script.py
scripts/test/test_dispatcher_.py
scripts/test/test_exporter_.py
scripts/test/test_lock.py
scripts/test/test_ls.py
scripts/test/test_prune_logs.py
scripts/test/test_report.py
scripts/test/test_results.py
scripts/test/test_run.py
scripts/test/test_schedule.py
scripts/test/test_suite.py
scripts/test/test_supervisor_.py
scripts/test/test_updatekeys.py

index fdabd1b5538412e517919d77caff7ecd86627989..a178c8a3fe5ec8683d8bcf8ec6e47033b027f19d 100644 (file)
@@ -1,16 +1,53 @@
-import subprocess
-from pytest import raises
+import sys
+import pytest
+from importlib import import_module
 
 
 class Script(object):
-    script_name = 'teuthology'
+    script_name = "teuthology"
+    script_module = None  # Override in subclasses, e.g., 'scripts.run'
 
-    def test_help(self):
-        args = (self.script_name, '--help')
-        out = subprocess.check_output(args).decode()
-        assert out.startswith('usage')
+    @pytest.fixture(scope="class")
+    def module_name(self) -> str:
+        # e.g., 'teuthology-dispatcher' -> 'scripts.dispatcher'
+        return self.script_name.replace("teuthology-", "").replace("teuthology", "run")
 
-    def test_invalid(self):
-        args = (self.script_name, '--invalid-option')
-        with raises(subprocess.CalledProcessError):
-            subprocess.check_call(args)
+    @pytest.fixture(scope="class")
+    def module(self, module_name):
+        return import_module(self.script_module or f"scripts.{module_name}")
+
+    def test_help(self, capsys: pytest.CaptureFixture[str], module):
+        # docopt
+        if module.__doc__ and "usage" in module.__doc__.lower():
+            return
+        if hasattr(module, "doc") and module.doc and "usage" in module.doc.lower():
+            return
+        # argparse
+        if hasattr(module, "parse_args"):
+            with pytest.raises(SystemExit):
+                module.parse_args([])
+            captured = capsys.readouterr()
+            assert "usage: " in captured.err
+            return
+        # If neither, fail
+        raise AssertionError(
+            f"{self.script_name} has neither a docstring/doc variable with usage info "
+            f"nor a parse_args function"
+        )
+
+    def test_invalid(self, module):
+        original_argv = sys.argv
+        try:
+            sys.argv = [self.script_name, "--invalid-option"]
+            with pytest.raises(SystemExit):
+                if hasattr(module, "parse_args"):
+                    module.parse_args(sys.argv[1:])
+                elif hasattr(module, "main"):
+                    # For docopt-based scripts, main() will call docopt which exits on error
+                    module.main()
+                else:
+                    raise NotImplementedError(
+                        f"Don't know how to test {self.script_name}"
+                    )
+        finally:
+            sys.argv = original_argv
index 4d201aae5d5823435a23677ee3f65311a07626c8..3dc16593f3da51e1338dd2a10b5fe6d703834851 100644 (file)
@@ -3,3 +3,4 @@ from script import Script
 
 class TestDispatcher(Script):
     script_name = 'teuthology-dispatcher'
+    script_module = 'scripts.dispatcher'
index b0611a337c5e3a014cabc0a84040469be3570a79..0d3c171eb81e64e4335c525339d96009b23353de 100644 (file)
@@ -3,3 +3,4 @@ from script import Script
 
 class TestExporter(Script):
     script_name = 'teuthology-exporter'
+    script_module = 'scripts.exporter'
index 3fc803aae66f0696dd4b09ea727ed510c0d70e6e..b1687c1216e4699f76042b9ed1e11cc1ca34f061 100644 (file)
@@ -3,3 +3,4 @@ from script import Script
 
 class TestLock(Script):
     script_name = 'teuthology-lock'
+    script_module = 'scripts.lock'
index d0e4d81451ce4cc4afe687116ab2f36d6209e7de..296578960bf9f60673ed18db3fb2402be1669419 100644 (file)
@@ -8,6 +8,7 @@ doc = ls.__doc__
 
 class TestLs(Script):
     script_name = 'teuthology-ls'
+    script_module = 'scripts.ls'
 
     def test_args(self):
         args = docopt.docopt(doc, ["--verbose", "some/archive/dir"])
index 8e967522f0e88a40ea9691182161b23072369995..1688017c2aa9c996111de6545690eb52f9989e7c 100644 (file)
@@ -3,3 +3,4 @@ from script import Script
 
 class TestPruneLogs(Script):
     script_name = 'teuthology-prune-logs'
+    script_module = 'scripts.prune_logs'
index c8065fd1f82cacfd19f0e98d82e36d32c4d8eb2a..40b750a19e223c0baf34a1e93ccbff10dae1fe68 100644 (file)
@@ -3,3 +3,4 @@ from script import Script
 
 class TestReport(Script):
     script_name = 'teuthology-report'
+    script_module = 'scripts.report'
index a97981cb6b4ba7ea108a88ab5628f57615bc8313..9f201b80eb1cbee79792a4a46db7fb28a15c9a72 100644 (file)
@@ -3,3 +3,4 @@ from script import Script
 
 class TestResults(Script):
     script_name = 'teuthology-results'
+    script_module = 'scripts.results'
index 74fa1b9263479009cd741e6e38c0468de98ebc87..de33e6e69f40ba7705eef500c79fd66476fac3fd 100644 (file)
@@ -8,6 +8,7 @@ doc = run.__doc__
 
 class TestRun(Script):
     script_name = 'teuthology'
+    script_module = 'scripts.run'
 
     def test_all_args(self):
         args = docopt.docopt(doc, [
index e89f983a7a6bcd840e7187fafff3f47edfe46375..d69c13a7b210816ef9ed458f8a52368170e017a8 100644 (file)
@@ -3,3 +3,4 @@ from script import Script
 
 class TestSchedule(Script):
     script_name = 'teuthology-schedule'
+    script_module = 'scripts.schedule'
index 062aba470d7b234b10a474ec58fb0ea5cf2670e4..f890c800df0f80c93e1c42023d1f981e5d505097 100644 (file)
@@ -3,3 +3,4 @@ from script import Script
 
 class TestSuite(Script):
     script_name = 'teuthology-suite'
+    script_module = 'scripts.suite'
index 81298995c56b92d7d11d7447cdb78ee2bea107cc..dad7882c8a737b3382f28f47373c5e8b0badcae6 100644 (file)
@@ -3,3 +3,4 @@ from script import Script
 
 class TestSupervisor(Script):
     script_name = 'teuthology-supervisor'
+    script_module = 'scripts.supervisor'
index c4122b0f781e0b507e513092a098c3a21d1c47aa..5a388290176c2b972a17edf1ac813146648ff60d 100644 (file)
@@ -1,21 +1,22 @@
 from script import Script
-import subprocess
+import docopt
 from pytest import raises
 from pytest import skip
+from scripts import updatekeys
 
 
 class TestUpdatekeys(Script):
     script_name = 'teuthology-updatekeys'
+    script_module = 'scripts.updatekeys'
 
     def test_invalid(self):
         skip("teuthology.lock needs to be partially refactored to allow" +
              "teuthology-updatekeys to return nonzero in all erorr cases")
 
     def test_all_and_targets(self):
-        args = (self.script_name, '-a', '-t', 'foo')
-        with raises(subprocess.CalledProcessError):
-            subprocess.check_call(args)
+        with raises(docopt.DocoptExit):
+            docopt.docopt(updatekeys.doc, ['-a', '-t', 'foo'])
 
     def test_no_args(self):
-        with raises(subprocess.CalledProcessError):
-            subprocess.check_call(self.script_name)
+        with raises(docopt.DocoptExit):
+            docopt.docopt(updatekeys.doc, [])