Posted on 13 Feb 2020
“Testing”, in general programming terms, is the practice of writing code (separate from your actual application code) that invokes the code it tests to help determine if there are any errors. It does not prove that code is correct (which is only possible under very restricted circumstances). It merely reports if the conditions the tester thought of are handled correctly.
In this blog we discuss few methods used to handle/cover input(), print() functions.
from nose.tools import * from unittest import mock from unittest.mock import patch import io def foo(): print("Something") # Solution one: testing print with @patch @patch('sys.stdout', new_callable=io.StringIO) def test_foo_one(mock_stdout): foo() assert mock_stdout.getvalue() == 'Something\n' # Solution two: testing print with with-statement def test_foo_two(): with mock.patch('sys.stdout', new=io.StringIO()) as fake_stdout: foo() assert fake_stdout.getvalue() == 'Something\n' # Solution three: testing print with with-statement # and assert_has_calls def test_foo_three(): with mock.patch('sys.stdout') as fake_stdout: foo() fake_stdout.assert_has_calls([ mock.call.write('Something'), mock.call.write('\n') ])
from nose.tools import * from unittest import mock def bar(): ans = input("enter yes or no") if ans == "yes": return "you entered yes" if ans == "no": return "you entered no" def test_bar_yes(): original_input = mock.builtins.input mock.builtins.input = lambda _: "yes" assert_equal(bar(), "you entered yes") mock.builtins.input = original_input def test_bar_no(): original_input = mock.builtins.input mock.builtins.input = lambda _: "no" assert_equal(bar(), "you entered no") mock.builtins.input = original_input
Interesting one.. Python Mocking 101: Fake It Before You Make It
__name__ == '__main__' from the coverage report , of course you can do that only if you already have a test case for your
main() function in your tests.
As for why I choose to exclude rather than writing a new test case for the whole script is because if as I stated you already have a test case for your
main() function the fact that you add an other test case for the script (just for having a 100 % coverage) will be just a duplicated one.
def main(): pass if __name__ == "__main__": main()
For how to exclude the if
__name__ == '__main__' you can write a coverage configuration file and add in the section report:
[report] exclude_lines = if __name__ == .__main__.:
The default name for configuration files is
.coveragerc, in the same directory coverage.py is being run in.
More info about the coverage configuration file can be found here
Please refer Galactic one of my project where I learnt how to implement the above.
Share your thoughts via twitter @aravind_kumar_g