I can selectively run test_function_1
, overriding instrumentation from my conftest.py
fixtures1
def test_function_1(instrumentation: dict[str, float]) -> None:
assert instrumentation['a'] > instrumentation['b']
def test_function_2(capsys) -> None:
print("Hello, pytest!")
captured = capsys.readouterr()
assert captured.out == "Hello, pytest!\n"
when I try to call test_function_2
, I don't know how to pass capsys
to it2 :
import tests
import pytest # <--- doesn't help ...
def test_callee_with_instrumentation():
tests.test_function_1({'a': 110, 'b': 55, 'g': 6000})
def test_callee_with_capsys():
# tests.test_function_2() # <--- TypeError: test_function_2() missing 1 required positional argument: 'capsys'
# tests.test_function_2(capsys) # <--- NameError: name 'capsys' is not defined
# tests.test_function_2(pytest.capsys) # <--- AttributeError: module 'pytest' has no attribute 'capsys'
pass
test_callee_with_instrumentation()
test_callee_with_capsys()
I'm pretty sure the conftest.py
fixtures are irrelevant, but for completeness:
import pytest
@pytest.fixture(scope='function')
def instrumentation():
return { 'a': 800, 'b': 620, 'c': 44 }
1 In my real code, the capsys
is one of many parameters.
2 A similar question exists here. It is not a duplicate IMHO, because I'm asking about programmatically running tests, and not about the proper meaning of capsys
.
capsys
is a PyTest fixture.
You can list all the fixtures using:
pytest --fixtures
The source code is found in _pytest/capture.py
. (Note: You should not try to directly instantiate/call the fixture.)
Write your function with an argument:
import tests
def test_callee_with_instrumentation():
tests.test_function_1({'a': 110, 'b': 55, 'g': 6000})
def test_callee_with_capsys(capsys):
tests.test_function_2(capsys)
Then run pytest your_test_file.py
and PyTest will automatically instantiate the fixture and pass it into the test.
If you don't want to use PyTest to run the tests then don't use capsys
to try to capture the standard output.
from contextlib import redirect_stdout
from io import StringIO
def test_function_1(instrumentation) -> None:
assert instrumentation['a'] > instrumentation['b']
def test_function_2() -> None:
with redirect_stdout(StringIO()) as f:
print("Hello, pytest!")
captured = f.getvalue()
assert captured == "Hello, pytest!\n"
If you do want to use PyTest but don't want to directly call PyTest from the console then call pytest.main()
from within your code:
import tests
def test_callee_with_instrumentation():
tests.test_function_1({'a': 110, 'b': 55, 'g': 6000})
def test_callee_with_output(capsys):
tests.test_function_2(capsys)
if __name__ == "__main__":
import pytest
pytest.main()