From f4dc5f3b935072cf9f580000879a5b107b5bda63 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Fri, 8 Mar 2024 13:14:02 +0200 Subject: [PATCH] tests: Print output in case subprocess returns unexpected code Signed-off-by: Povilas Kanapickas --- tests/test_podman_compose.py | 29 +++--------- tests/test_podman_compose_config.py | 10 ++--- tests/test_podman_compose_include.py | 27 +++-------- tests/test_podman_compose_tests.py | 67 ++++++++++++---------------- tests/test_podman_compose_up_down.py | 12 +++-- tests/test_utils.py | 24 ++++++++++ 6 files changed, 75 insertions(+), 94 deletions(-) create mode 100644 tests/test_utils.py diff --git a/tests/test_podman_compose.py b/tests/test_podman_compose.py index e5718051..0d3800b0 100644 --- a/tests/test_podman_compose.py +++ b/tests/test_podman_compose.py @@ -1,19 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 from pathlib import Path -import subprocess import os import unittest - - -def run_subprocess(command): - proc = subprocess.Popen( - command, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) - out, err = proc.communicate() - return out, err, proc.returncode +from .test_utils import RunSubprocessMixin def base_path(): @@ -31,7 +21,7 @@ def podman_compose_path(): return os.path.join(base_path(), "podman_compose.py") -class TestPodmanCompose(unittest.TestCase): +class TestPodmanCompose(unittest.TestCase, RunSubprocessMixin): def test_extends_w_file_subdir(self): """ Test that podman-compose can execute podman-compose -f up with extended File which @@ -69,18 +59,14 @@ def test_extends_w_file_subdir(self): "docker.io/library/busybox", ] - out, _, returncode = run_subprocess(command_up) - self.assertEqual(returncode, 0) + self.run_subprocess_assert_returncode(command_up) # check container was created and exists - out, err, returncode = run_subprocess(command_check_container) - self.assertEqual(returncode, 0) + out, _ = self.run_subprocess_assert_returncode(command_check_container) self.assertEqual(out, b'localhost/subdir_test:me\n') - out, _, returncode = run_subprocess(command_down) # cleanup test image(tags) - self.assertEqual(returncode, 0) + self.run_subprocess_assert_returncode(command_down) # check container did not exists anymore - out, _, returncode = run_subprocess(command_check_container) - self.assertEqual(returncode, 0) + out, _ = self.run_subprocess_assert_returncode(command_check_container) self.assertEqual(out, b'') def test_extends_w_empty_service(self): @@ -100,5 +86,4 @@ def test_extends_w_empty_service(self): "-d", ] - _, _, returncode = run_subprocess(command_up) - self.assertEqual(returncode, 0) + self.run_subprocess_assert_returncode(command_up) diff --git a/tests/test_podman_compose_config.py b/tests/test_podman_compose_config.py index dfeddce9..ef383b23 100644 --- a/tests/test_podman_compose_config.py +++ b/tests/test_podman_compose_config.py @@ -9,8 +9,8 @@ # pylint: disable=redefined-outer-name import os from .test_podman_compose import podman_compose_path -from .test_podman_compose import run_subprocess from .test_podman_compose import test_path +from .test_utils import RunSubprocessMixin import unittest from parameterized import parameterized @@ -20,7 +20,7 @@ def profile_compose_file(): return os.path.join(test_path(), "profile", "docker-compose.yml") -class TestComposeConfig(unittest.TestCase): +class TestComposeConfig(unittest.TestCase, RunSubprocessMixin): def test_config_no_profiles(self): """ Tests podman-compose config command without profile enablement. @@ -34,8 +34,7 @@ def test_config_no_profiles(self): "config", ] - out, _, return_code = run_subprocess(config_cmd) - self.assertEqual(return_code, 0) + out, _ = self.run_subprocess_assert_returncode(config_cmd) string_output = out.decode("utf-8") self.assertIn("default-service", string_output) @@ -68,8 +67,7 @@ def test_config_profiles(self, profiles, expected_services): config_cmd = ["coverage", "run", podman_compose_path(), "-f", profile_compose_file()] config_cmd.extend(profiles) - out, _, return_code = run_subprocess(config_cmd) - self.assertEqual(return_code, 0) + out, _ = self.run_subprocess_assert_returncode(config_cmd) actual_output = out.decode("utf-8") diff --git a/tests/test_podman_compose_include.py b/tests/test_podman_compose_include.py index c09df321..7aae8ae7 100644 --- a/tests/test_podman_compose_include.py +++ b/tests/test_podman_compose_include.py @@ -4,18 +4,10 @@ import subprocess import unittest +from .test_utils import RunSubprocessMixin -def run_subprocess(command): - proc = subprocess.Popen( - command, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) - out, err = proc.communicate() - return out, err, proc.returncode - -class TestPodmanComposeInclude(unittest.TestCase): +class TestPodmanComposeInclude(unittest.TestCase, RunSubprocessMixin): def test_podman_compose_include(self): """ Test that podman-compose can execute podman-compose -f up with include @@ -55,22 +47,17 @@ def test_podman_compose_include(self): command_down = ["podman", "rm", "--force", "CONTAINER_ID"] - out, _, returncode = run_subprocess(command_up) - self.assertEqual(returncode, 0) - out, _, returncode = run_subprocess(command_check_container) - self.assertEqual(returncode, 0) + self.run_subprocess_assert_returncode(command_up) + out, _ = self.run_subprocess_assert_returncode(command_check_container) self.assertEqual(out, b'"docker.io/library/busybox:latest"\n') # Get container ID to remove it - out, _, returncode = run_subprocess(command_container_id) - self.assertEqual(returncode, 0) + out, _ = self.run_subprocess_assert_returncode(command_container_id) self.assertNotEqual(out, b"") container_id = out.decode().strip().replace('"', "") command_down[3] = container_id - out, _, returncode = run_subprocess(command_down) + out, _ = self.run_subprocess_assert_returncode(command_down) # cleanup test image(tags) - self.assertEqual(returncode, 0) self.assertNotEqual(out, b"") # check container did not exists anymore - out, _, returncode = run_subprocess(command_check_container) - self.assertEqual(returncode, 0) + out, _ = self.run_subprocess_assert_returncode(command_check_container) self.assertEqual(out, b"") diff --git a/tests/test_podman_compose_tests.py b/tests/test_podman_compose_tests.py index 575c90ab..de1f019c 100644 --- a/tests/test_podman_compose_tests.py +++ b/tests/test_podman_compose_tests.py @@ -11,12 +11,12 @@ import time import unittest -from .test_podman_compose import run_subprocess from .test_podman_compose import podman_compose_path from .test_podman_compose import test_path +from .test_utils import RunSubprocessMixin -class TestPodmanCompose(unittest.TestCase): +class TestPodmanCompose(unittest.TestCase, RunSubprocessMixin): def test_exit_from(self): up_cmd = [ "coverage", @@ -27,11 +27,8 @@ def test_exit_from(self): "up", ] - out, _, return_code = run_subprocess(up_cmd + ["--exit-code-from", "sh1"]) - self.assertEqual(return_code, 1) - - out, _, return_code = run_subprocess(up_cmd + ["--exit-code-from", "sh2"]) - self.assertEqual(return_code, 2) + self.run_subprocess_assert_returncode(up_cmd + ["--exit-code-from", "sh1"], 1) + self.run_subprocess_assert_returncode(up_cmd + ["--exit-code-from", "sh2"], 2) def test_run(self): """ @@ -51,7 +48,7 @@ def test_run(self): "wget -q -O - http://web:8000/hosts", ] - out, _, return_code = run_subprocess(run_cmd) + out, _ = self.run_subprocess_assert_returncode(run_cmd) self.assertIn(b'127.0.0.1\tlocalhost', out) # Run it again to make sure we can run it twice. I saw an issue where a second run, with the container left up, @@ -70,9 +67,8 @@ def test_run(self): "wget -q -O - http://web:8000/hosts", ] - out, _, return_code = run_subprocess(run_cmd) - assert b'127.0.0.1\tlocalhost' in out - self.assertEqual(return_code, 0) + out, _ = self.run_subprocess_assert_returncode(run_cmd) + self.assertIn(b'127.0.0.1\tlocalhost', out) # This leaves a container running. Not sure it's intended, but it matches docker-compose down_cmd = [ @@ -84,8 +80,7 @@ def test_run(self): "down", ] - out, _, return_code = run_subprocess(run_cmd) - self.assertEqual(return_code, 0) + self.run_subprocess_assert_returncode(down_cmd) def test_up_with_ports(self): up_cmd = [ @@ -110,12 +105,10 @@ def test_up_with_ports(self): ] try: - out, _, return_code = run_subprocess(up_cmd) - self.assertEqual(return_code, 0) + self.run_subprocess_assert_returncode(up_cmd) finally: - out, _, return_code = run_subprocess(down_cmd) - self.assertEqual(return_code, 0) + self.run_subprocess_assert_returncode(down_cmd) def test_down_with_vols(self): up_cmd = [ @@ -139,29 +132,25 @@ def test_down_with_vols(self): ] try: - out, _, return_code = run_subprocess(["podman", "volume", "create", "my-app-data"]) - self.assertEqual(return_code, 0) - out, _, return_code = run_subprocess([ + self.run_subprocess_assert_returncode(["podman", "volume", "create", "my-app-data"]) + self.run_subprocess_assert_returncode([ "podman", "volume", "create", "actual-name-of-volume", ]) - self.assertEqual(return_code, 0) - out, _, return_code = run_subprocess(up_cmd) - self.assertEqual(return_code, 0) - - run_subprocess(["podman", "inspect", "volume", ""]) + self.run_subprocess_assert_returncode(up_cmd) + self.run_subprocess(["podman", "inspect", "volume", ""]) finally: - out, _, return_code = run_subprocess(down_cmd) - run_subprocess(["podman", "volume", "rm", "my-app-data"]) - run_subprocess(["podman", "volume", "rm", "actual-name-of-volume"]) + out, _, return_code = self.run_subprocess(down_cmd) + self.run_subprocess(["podman", "volume", "rm", "my-app-data"]) + self.run_subprocess(["podman", "volume", "rm", "actual-name-of-volume"]) self.assertEqual(return_code, 0) def test_down_with_orphans(self): - container_id, _, return_code = run_subprocess([ + container_id, _ = self.run_subprocess_assert_returncode([ "podman", "run", "--rm", @@ -187,14 +176,14 @@ def test_down_with_orphans(self): "--remove-orphans", ] - out, _, return_code = run_subprocess(down_cmd) - self.assertEqual(return_code, 0) - - _, _, exists = run_subprocess([ - "podman", - "container", - "exists", - container_id.decode("utf-8"), - ]) + self.run_subprocess_assert_returncode(down_cmd) - self.assertEqual(exists, 1) + self.run_subprocess_assert_returncode( + [ + "podman", + "container", + "exists", + container_id.decode("utf-8"), + ], + 1, + ) diff --git a/tests/test_podman_compose_up_down.py b/tests/test_podman_compose_up_down.py index 4e7bba79..f7c3880e 100644 --- a/tests/test_podman_compose_up_down.py +++ b/tests/test_podman_compose_up_down.py @@ -8,9 +8,9 @@ # pylint: disable=redefined-outer-name import os -from .test_podman_compose import run_subprocess from .test_podman_compose import podman_compose_path from .test_podman_compose import test_path +from .test_utils import RunSubprocessMixin from parameterized import parameterized import unittest @@ -20,7 +20,7 @@ def profile_compose_file(): return os.path.join(test_path(), "profile", "docker-compose.yml") -class TestUpDown(unittest.TestCase): +class TestUpDown(unittest.TestCase, RunSubprocessMixin): def tearDown(self): """ Ensures that the services within the "profile compose file" are removed between each test case. @@ -39,7 +39,7 @@ def tearDown(self): profile_compose_file(), "down", ] - run_subprocess(down_cmd) + self.run_subprocess(down_cmd) @parameterized.expand( [ @@ -67,8 +67,7 @@ def test_up(self, profiles, expected_services): ] up_cmd.extend(profiles) - out, _, return_code = run_subprocess(up_cmd) - self.assertEqual(return_code, 0) + self.run_subprocess_assert_returncode(up_cmd) check_cmd = [ "podman", @@ -77,8 +76,7 @@ def test_up(self, profiles, expected_services): "--format", '"{{.Names}}"', ] - out, _, return_code = run_subprocess(check_cmd) - self.assertEqual(return_code, 0) + out, _ = self.run_subprocess_assert_returncode(check_cmd) self.assertEqual(len(expected_services), 3) actual_output = out.decode("utf-8") diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 00000000..e491e135 --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 + +import subprocess + + +class RunSubprocessMixin: + def run_subprocess(self, args): + proc = subprocess.Popen( + args, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + out, err = proc.communicate() + return out, err, proc.returncode + + def run_subprocess_assert_returncode(self, args, expected_returncode=0): + out, err, returncode = self.run_subprocess(args) + self.assertEqual( + returncode, + expected_returncode, + f"Invalid return code of process {returncode} != {expected_returncode}\n" + f"stdout: {out}\nstderr: {err}\n", + ) + return out, err