File: test_unit.py

package info (click to toggle)
subprocess-tee 0.4.2-1.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 172 kB
  • sloc: python: 266; makefile: 4
file content (152 lines) | stat: -rw-r--r-- 4,830 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
"""Unittests."""

import subprocess
import sys
from typing import Dict

import pytest
from _pytest.capture import CaptureFixture

from subprocess_tee import run


def test_run_string() -> None:
    """Valida run() called with a single string command."""
    cmd = "echo 111 && >&2 echo 222"
    old_result = subprocess.run(
        cmd,
        shell=True,
        universal_newlines=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        check=False,
    )
    result = run(cmd)
    assert result.returncode == old_result.returncode
    assert result.stdout == old_result.stdout
    assert result.stderr == old_result.stderr


def test_run_list() -> None:
    """Validate run call with a command made of list of strings."""
    # NOTICE: subprocess.run() does fail to capture any output when cmd is
    # a list and you specific shell=True. Still, when not mentioning shell,
    # it does work.
    cmd = [sys.executable, "--version"]
    old_result = subprocess.run(
        cmd,
        # shell=True,
        universal_newlines=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        check=False,
    )
    result = run(cmd)
    assert result.returncode == old_result.returncode
    assert result.stdout == old_result.stdout
    assert result.stderr == old_result.stderr


def test_run_echo(capsys: CaptureFixture[str]) -> None:
    """Validate run call with echo dumps command."""
    cmd = [sys.executable, "--version"]
    old_result = subprocess.run(
        cmd,
        # shell=True,
        universal_newlines=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        check=False,
    )
    result = run(cmd, echo=True)
    assert result.returncode == old_result.returncode
    assert result.stdout == old_result.stdout
    assert result.stderr == old_result.stderr
    out, err = capsys.readouterr()
    assert out.startswith("COMMAND:")
    assert err == ""


@pytest.mark.parametrize(
    "env",
    [{}, {"SHELL": "/bin/sh"}, {"SHELL": "/bin/bash"}, {"SHELL": "/bin/zsh"}],
    ids=["auto", "sh", "bash", "zsh"],
)
def test_run_with_env(env: Dict[str, str]) -> None:
    """Validate that passing custom env to run() works."""
    env["FOO"] = "BAR"
    result = run("echo $FOO", env=env, echo=True)
    assert result.stdout == "BAR\n"


def test_run_shell() -> None:
    """Validate run call with multiple shell commands works."""
    cmd = "echo a && echo b && false || exit 4"
    # "python --version"
    result = run(cmd, echo=True)
    assert result.returncode == 4
    assert result.stdout == "a\nb\n"


def test_run_shell_undefined() -> None:
    """Validate run call with multiple shell commands works."""
    cmd = "echo a && echo b && false || exit 4"
    # "python --version"
    result = run(cmd, echo=True, env={})
    assert result.returncode == 4
    assert result.stdout == "a\nb\n"


def test_run_cwd() -> None:
    """Validate that run accepts cwd and respects it."""
    cmd = "pwd"
    result = run(cmd, echo=True, cwd="/")
    assert result.returncode == 0
    assert result.stdout == "/\n"


def test_run_with_check_raise() -> None:
    """Asure compatibility with subprocess.run when using check (return 1)."""
    with pytest.raises(subprocess.CalledProcessError) as ours:
        run("false", check=True)
    with pytest.raises(subprocess.CalledProcessError) as original:
        subprocess.run("false", check=True, universal_newlines=True)
    assert ours.value.returncode == original.value.returncode
    assert ours.value.cmd == original.value.cmd
    assert ours.value.output == original.value.output
    assert ours.value.stdout == original.value.stdout
    assert ours.value.stderr == original.value.stderr


def test_run_with_check_pass() -> None:
    """Asure compatibility with subprocess.run when using check (return 0)."""
    ours = run("true", check=True)
    original = subprocess.run("true", check=True, universal_newlines=True)
    assert ours.returncode == original.returncode
    assert ours.args == original.args
    assert ours.stdout == original.stdout
    assert ours.stderr == original.stderr


def test_run_compat() -> None:
    """Assure compatiblity with subprocess.run()."""
    cmd = ["seq", "10"]
    ours = run(cmd)
    original = subprocess.run(
        cmd,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        universal_newlines=True,
        check=False,
    )
    assert ours.returncode == original.returncode
    assert ours.stdout == original.stdout
    assert ours.stderr == original.stderr
    assert ours.args == original.args


def test_run_waits_for_completion(tmp_path):
    """run() should always wait for the process to complete."""
    tmpfile = tmp_path / "output.txt"
    run(f"sleep 0.1 && echo 42 > {str(tmpfile)}")
    assert tmpfile.read_text() == "42\n"