Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DRAFT: Redesign test_subprocess logic #253

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 74 additions & 79 deletions tests/test_subprocess.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""`pytest` tests for `utils/subprocess.py`."""

import itertools
import os
import subprocess
from pathlib import Path
Expand All @@ -17,90 +18,84 @@ def subprocess_handler(self):
"""Return an instance of `SubprocessWrapper` for testing."""
return SubprocessWrapper()

def test_stdout_is_suppressed_in_non_verbose_mode(self, subprocess_handler, capfd):
"""Success case: test stdout is suppressed in non-verbose mode."""
subprocess_handler.run_cmd("echo foo")
captured = capfd.readouterr()
assert not captured.out
assert not captured.err

def test_stderr_is_suppressed_in_non_verbose_mode(self, subprocess_handler, capfd):
"""Success case: test stderr is suppressed in non-verbose mode."""
subprocess_handler.run_cmd("echo foo 1>&2")
captured = capfd.readouterr()
assert not captured.out
assert not captured.err

def test_command_and_stdout_is_printed_in_verbose_mode(
self, subprocess_handler, capfd
):
"""Success case: test command and stdout is printed in verbose mode."""
subprocess_handler.run_cmd("echo foo", verbose=True)
captured = capfd.readouterr()
assert captured.out == "echo foo\nfoo\n"
assert not captured.err

def test_command_and_stderr_is_redirected_to_stdout_in_verbose_mode(
self, subprocess_handler, capfd
):
"""Success case: test command and stderr is redirected to stdout in verbose mode."""
subprocess_handler.run_cmd("echo foo 1>&2", verbose=True)
captured = capfd.readouterr()
assert captured.out == "echo foo 1>&2\nfoo\n"
assert not captured.err

def test_output_is_captured_with_capture_output_enabled(
self, subprocess_handler, capfd
):
"""Success case: test output is captured with capture_output enabled."""
proc = subprocess_handler.run_cmd("echo foo", capture_output=True)
captured = capfd.readouterr()
assert not captured.out
assert not captured.err
assert proc.stdout == "foo\n"
assert not proc.stderr

def test_stderr_captured_to_stdout(self, subprocess_handler, capfd):
"""Success case: test stderr is captured to stdout with capture_output enabled."""
proc = subprocess_handler.run_cmd("echo foo 1>&2", capture_output=True)
captured = capfd.readouterr()
assert not captured.out
# Parameterization
@pytest.fixture(params=list(itertools.product([False, True], repeat=3)))
def generate_params(self, request):
possible_inputs = request.param
return {
"param_verbose": possible_inputs[0],
"param_capture": possible_inputs[1],
"param_file": possible_inputs[2],
}

@pytest.fixture(params=[("echo foo", "foo\n"), ("echo foo 1>&2", "foo\n")])
def generated_input(self, request, generate_params):
command = request.param
return generate_params | {
"command": {
"input": command[0],
"expected": command[1],
}
}

def _test_verbose(self, is_stdout_verbose, param_verbose, captured, command):
assert not captured.err
assert proc.stdout == "foo\n"
expected = command["input"] + "\n"
if param_verbose and is_stdout_verbose:
expected += command["expected"]
if is_stdout_verbose or param_verbose:
assert captured.out == expected
else:
assert not captured.out

def _test_capture_output(self, is_stdout_capture, proc, expected):
assert not proc.stderr
if is_stdout_capture:
assert proc.stdout == expected
else:
assert not proc.stdout

def _test_output_file(self, is_stdout_file, file_path, expected):
if is_stdout_file:
with file_path.open("r", encoding="utf-8") as file:
assert file.read() == expected
else:
# TODO: Check for non-existent file
pass

def test_subprocess_logic(self, subprocess_handler, generated_input, capfd):

is_stdout_verbose, is_stdout_output, is_stdout_capture = (False, False, False)
file_path = None

if generated_input["param_capture"]:
is_stdout_capture = True
elif generated_input["param_file"]:
is_stdout_output = True
file_path = Path("out.txt")
elif generated_input["param_verbose"]:
is_stdout_verbose = True

def test_command_is_printed_and_stdout_is_captured_in_verbose_mode(
self, subprocess_handler, capfd
):
"""Success case: test command is printed and stdout is captured in verbose mode."""
proc = subprocess_handler.run_cmd("echo foo", capture_output=True, verbose=True)
captured = capfd.readouterr()
assert captured.out == "echo foo\n"
assert not captured.err
assert proc.stdout == "foo\n"
assert not proc.stderr

def test_stdout_is_redirected_to_file(self, subprocess_handler, capfd):
"""Success case: test stdout is redirected to file."""
file_path = Path("out.txt")
subprocess_handler.run_cmd("echo foo", output_file=file_path)
with file_path.open("r", encoding="utf-8") as file:
assert file.read() == "foo\n"
proc = subprocess_handler.run_cmd(
generated_input["command"]["input"],
verbose=generated_input["param_verbose"],
capture_output=generated_input["param_capture"],
output_file=file_path,
)
captured = capfd.readouterr()
assert not captured.out
assert not captured.err

def test_command_is_printed_and_stdout_is_redirected_to_file_in_verbose_mode(
self, subprocess_handler, capfd
):
"""Success case: test command is printed and stdout is redirected to file in verbose mode."""
file_path = Path("out.txt")
subprocess_handler.run_cmd("echo foo", output_file=file_path, verbose=True)
with file_path.open("r", encoding="utf-8") as file:
assert file.read() == "foo\n"
captured = capfd.readouterr()
assert captured.out == "echo foo\n"
assert not captured.err
self._test_verbose(
is_stdout_verbose,
generated_input["param_verbose"],
captured,
generated_input["command"],
)
self._test_capture_output(
is_stdout_capture, proc, generated_input["command"]["expected"]
)
self._test_output_file(
is_stdout_output, file_path, generated_input["command"]["expected"]
)

def test_command_is_run_with_environment(self, subprocess_handler):
"""Success case: test command is run with environment."""
Expand Down
Loading