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

Support of pytest capsys #24

Closed
shepherdjay opened this issue Jan 28, 2020 · 9 comments · Fixed by #35
Closed

Support of pytest capsys #24

shepherdjay opened this issue Jan 28, 2020 · 9 comments · Fixed by #35
Assignees
Labels
bug Something isn't working minor
Milestone

Comments

@shepherdjay
Copy link
Contributor

First off great plugin, we were writing a bunch of our own logic and boiler plate for our nagios style tests and I am considering moving over to this plugin to avoid copy paste errors.

The one issue I've had is converting our tests, our current modules use pytest's capsys fixture. To compare the expected output of a check with test data. Sample from one of these tests below.

[.....]
mock_get.return_value.text = test_data
expected_msg = "OK :load average is 2% and max is 10% | " + \
               "load_average=2;75;85;100; load_max=10;75;85;100;\n"
with pytest.raises(SystemExit) as e:
    cpdmain(test_args)
assert capsys.readouterr().out == expected_msg

What's interesting is none of the pytest fixtures for capturing stdout seem to capture nagiosplugins output. More interesting is that the output does appear in the test results summary like this

test_load.py::test_main FAILED [ 56%]LOAD OK - avg is 2 | avg=2;75;85;0;100 max=10;75;85;0;100

As far as I can tell the reason appears to be related to the Runtime class execute method where it prints with the file keyword argument set to self.stdout which itself is just sys.stdout

Since writing to stdout is the default behavior of print I'm curious if it being explicitly specified is to solve a specific problem or if this can be removed to allow test frameworks like pytest to capture the output?

@mpounsett mpounsett added the question Further information is requested label Feb 4, 2020
@mpounsett
Copy link
Owner

I'm not the original author, just the current maintainer, so I can't speak with authority about historical reasons for using Runtime.stdout, but I imagine it's to allow anything using the library to be able to redirect output easily.

That said, I can't see how an explicit print to sys.stdout is any different from an implicit print to stdout by default. I don't think removing it is going to fix your problem.

Can you provide some simple-as-possible example code that demonstrates the problem?

@shepherdjay
Copy link
Contributor Author

The simplest example is to use the Hello World check from the documentation with this pytest code. In this case, the exact code from the tutorial is placed in a file called example_issue24.py

from example_issue24 import main as libmain
import pytest

def test_helloworld(capsys):
    with pytest.raises(SystemExit):
        libmain()
    assert capsys.readouterr().out == 'WORLD OK\n'

The test will fail with the assert not being matched. Specifically with the below

 AssertionError: assert '' == 'WORLD OK\n'

However, if you uninstall nagiosplugin and install this forked version where the only change is to remove the file parameter from Runtime.execute the test passes.

pip install git+https://github.com/shepherdjay/nagiosplugin.git@617a04ff378c1c8045213d264995d83ec4e9f5ad

Its possible that there is a small issue with the fixture I can try to raise an issue with the pytest team as well.

@shepherdjay
Copy link
Contributor Author

Pytest issue raised pytest-dev/pytest#6676

@RonnyPfannschmidt
Copy link

the basic issue is that pytest output redirection has to replace sys.stdout/stderr to do "isolated" redirection

taking a alias simply negates that
as far as i can tell, the TestRuntime also replaces the stdout with a stringio, i believe its fine to do the same from pytest based tests as well

@shepherdjay
Copy link
Contributor Author

shepherdjay commented Feb 5, 2020

@mpounsett A possible solution that came out of the pytest issue is to set Runtime.stdout to None - When passed to the file parameter it uses the default std.out that pytest is redirecting while still allowing it to be overridden for anyone doing so.

I tested this on my issue24 branch I have and all the tox tests passed. https://travis-ci.com/shepherdjay/nagiosplugin/builds/147585561

I can open a pull request if you like; my current branch added a .travis.yml for testing but I can remove that or include it.

@mpounsett
Copy link
Owner

I did some digging into the origin of using sys.stdout there. It was first introduced in 202a19f where a basic print() was replace with a sys.stdout.write() call in order to fix something cross-platform. Later it changed to print(..., file=sys.stdout).

I think I'd like to both understand why print(..., file=sys.stdout) behaves any differently from print(..., file=None) when the latter should still print to "the current sys.stdout" according to the Python docs. I'd also like to make sure that tests aren't broken on Windows.

@RonnyPfannschmidt
Copy link

RonnyPfannschmidt commented Feb 6, 2020

@mpounsett there is a time lag difference and aliasing

#untested
my_alias = sys.stdout
with redirect_stdout(something_else):
   print(..., file=my_alias) # goes to the original stdout
   print(..., file=None) # goes to the current sys.stdout aka something_else

@shepherdjay
Copy link
Contributor Author

@mpounsett as far as the windows tests - I got this semi working in Travis using python 3.7 as well but both on my Windows 10 machine and Travis several tests fail for permissions issues. These tests fail on the most recent release as well as the build that removes the alias. Not sure if this is helpful or not for you but here are the builds.

Issue24 - https://travis-ci.com/shepherdjay/nagiosplugin/builds/147641097
Current Master - https://travis-ci.com/shepherdjay/nagiosplugin/builds/147640379

In my config I did specify windows was allowed to fail given that it is still experimental in Travis.

@mpounsett mpounsett added bug Something isn't working minor and removed question Further information is requested labels Aug 1, 2020
@mpounsett mpounsett added this to the 1.3.x milestone Aug 1, 2020
@mpounsett mpounsett self-assigned this Aug 1, 2020
@mpounsett
Copy link
Owner

Sorry, @shepherdjay .. I seem to have let this drop of my radar.

If you want to send that PR (without the travis config) I'll apply it.

Adding the travis stuff would also be great, but I think that should be a separate PR/issue.

mpounsett added a commit that referenced this issue Oct 12, 2021
@mpounsett mpounsett modified the milestones: 1.3.x, 1.3.3 Feb 6, 2022
dlax added a commit to dalibo/check_patroni that referenced this issue Oct 6, 2023
We basically apply the change from
mpounsett/nagiosplugin#24 as a fixture, but
only when nagiosplugin's version is old.
dlax added a commit to dalibo/check_patroni that referenced this issue Oct 6, 2023
We basically apply the change from
mpounsett/nagiosplugin#24 as a fixture, but
only when nagiosplugin's version is old.
dlax added a commit to dalibo/check_patroni that referenced this issue Oct 6, 2023
We basically apply the change from
mpounsett/nagiosplugin#24 as a fixture, but
only when nagiosplugin's version is old.
dlax added a commit to dalibo/check_patroni that referenced this issue Oct 6, 2023
We basically apply the change from
mpounsett/nagiosplugin#24 as a fixture, but
only when nagiosplugin's version is old.
dlax added a commit to dalibo/check_patroni that referenced this issue Oct 6, 2023
We basically apply the change from
mpounsett/nagiosplugin#24 as a fixture, but
only when nagiosplugin's version is old.
dlax added a commit to dalibo/check_patroni that referenced this issue Oct 13, 2023
We basically apply the change from
mpounsett/nagiosplugin#24 as a fixture, but
only when nagiosplugin's version is old.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working minor
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants