testutil: add new mock_command context manager
The new `testutil.mock_command` context manager can be used to
mock commands in PATH and replace them with arbitrary shell
scripts. This is useful in testing to e.g. simulate exact error
conditions that would be hard to trigger otherwise or to replace
long running commands with faked results.
Example:
```
fake_cmd = textwrap.dedent("""\
do-something
""")
with mock_command("some-cmd", fake_cmd):
your_code
```
This commit is contained in:
parent
291f5cc29e
commit
7b5d6e4bd9
2 changed files with 49 additions and 0 deletions
|
|
@ -1,10 +1,12 @@
|
|||
"""
|
||||
Test related utilities
|
||||
"""
|
||||
import contextlib
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
|
||||
def has_executable(executable: str) -> bool:
|
||||
|
|
@ -57,3 +59,21 @@ def assert_jsonschema_error_contains(res, expected_err, expected_num_errs=None):
|
|||
def finder(s): return expected_err in s # pylint: disable=C0321
|
||||
assert any(finder(err_msg)
|
||||
for err_msg in err_msgs), f"{expected_err} not found in {err_msgs}"
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def mock_command(cmd_name: str, script: str):
|
||||
"""
|
||||
mock_command creates a mocked binary with the given :cmd_name: and :script:
|
||||
content. This is useful to e.g. mock errors from binaries.
|
||||
"""
|
||||
original_path = os.environ["PATH"]
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
cmd_path = pathlib.Path(tmpdir) / cmd_name
|
||||
cmd_path.write_text(script, encoding="utf8")
|
||||
cmd_path.chmod(0o755)
|
||||
os.environ["PATH"] = f"{tmpdir}:{original_path}"
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
os.environ["PATH"] = original_path
|
||||
|
|
|
|||
29
test/mod/test_testutil_mock_command.py
Normal file
29
test/mod/test_testutil_mock_command.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#
|
||||
# Tests for the 'osbuild.util.testutil.mock_command' module.
|
||||
#
|
||||
import os
|
||||
import subprocess
|
||||
import textwrap
|
||||
|
||||
from osbuild.testutil import mock_command
|
||||
|
||||
|
||||
def test_mock_command_integration():
|
||||
output = subprocess.check_output(["echo", "hello"])
|
||||
assert output == b"hello\n"
|
||||
fake_echo = textwrap.dedent("""\
|
||||
#!/bin/sh
|
||||
echo i-am-not-echo
|
||||
""")
|
||||
with mock_command("echo", fake_echo):
|
||||
output = subprocess.check_output(["echo", "hello"])
|
||||
assert output == b"i-am-not-echo\n"
|
||||
output = subprocess.check_output(["echo", "hello"])
|
||||
assert output == b"hello\n"
|
||||
|
||||
|
||||
def test_mock_command_environ_is_modified_and_restored():
|
||||
orig_path = os.environ["PATH"]
|
||||
with mock_command("something", "#!/bin/sh\ntrue\n"):
|
||||
assert os.environ["PATH"] != orig_path
|
||||
assert os.environ["PATH"] == orig_path
|
||||
Loading…
Add table
Add a link
Reference in a new issue