Source From Here
PrefaceWhen I had tested code which had called sys.exit(), my usual approach was to use mock. First is the target function to test:
- mypack/mymodu.py
- import sys
- def should_exit(rc=1):
- sys.exit(rc)
- tests/test_mymodu.py
- import unittest
- from mypack import mymodu
- from unittest import mock
- def test_should_exit():
- with mock.patch.object(mymodu.sys, "exit") as mock_exit:
- mymodu.should_exit()
- assert mock_exit.call_args[0][0] == 1
There are few things I don’t like here:
Any Better Way
All that make me wounder: is there a better way? After some experiments I found a better solution (Asserting about exceptions with pytest.raises):
- def test_should_exit_way2():
- with pytest.raises(SystemExit) as pytest_wrapped_e:
- mymodu.should_exit(42)
- assert pytest_wrapped_e.type == SystemExit
- assert pytest_wrapped_e.value.code == 42
This example threats testing code as black box. Actual exit my be called anywhere and refactoring should not break test.
Important note: there are two exits: sys.exit() (normal) and os._exit(), which bypasses all python magic and just calls _exit() function for C (man _exit). Later couldn’t be intercepted by catching SystemExit and the single way to debug such code is still to use mock to match os module. Fortunately,os._exit() is an extremely rare occurrence.
沒有留言:
張貼留言