How do I set sys.argv so I can unit test it?
Solution 1:
Changing sys.argv at runtime is a pretty fragile way of testing. You should use mock's patch functionality, which can be used as a context manager to substitute one object (or attribute, method, function, etc.) with another, within a given block of code.
The following example uses patch()
to effectively "replace" sys.argv
with the specified return value (testargs
).
try:
# python 3.4+ should use builtin unittest.mock not mock package
from unittest.mock import patch
except ImportError:
from mock import patch
def test_parse_args():
testargs = ["prog", "-f", "/home/fenton/project/setup.py"]
with patch.object(sys, 'argv', testargs):
setup = get_setup_file()
assert setup == "/home/fenton/project/setup.py"
Solution 2:
test_argparse.py
, the official argparse
unittest file, uses several means of setting/using argv
:
parser.parse_args(args)
where args
is a list of 'words', e.g. ['--foo','test']
or --foo test'.split()
.
old_sys_argv = sys.argv
sys.argv = [old_sys_argv[0]] + args
try:
return parser.parse_args()
finally:
sys.argv = old_sys_argv
This pushes the args onto sys.argv
.
I just came across a case (using mutually_exclusive_groups
) where ['--foo','test']
produces different behavior than '--foo test'.split()
. It's a subtle point involving the id
of strings like test
.