8

I am trying to use unittest with a program that uses the argparse module and having some difficulties. I referenced this helpful post as a starting point but I'm clearly still missing something.

Here is the basic program:

#arg_test.py
import sys
import argparse


class Thingy:
    def __init__(self, name):
        self.name = name

    def parse_args(args):
        parser = argparse.ArgumentParser(description='description here')
        parser.add_argument('-v', '--version', action='version', version='%(prog)s 0.1')
        parser.add_argument('-a', '--arg1', required=True, help='this is for arg1')
        parser.add_argument('-b', '--arg2', required=True, help='this is for arg2')
        return parser.parse_args()


def main():
    parser = Thingy.parse_args(sys.argv[1:])
    print('the args are: {}'.format(parser))
    if parser.arg1:
        print('the value of arg1 is : {}'.format(parser.arg1))
    if parser.arg2:
        print('the value of arg2 is : {}'.format(parser.arg2))


if __name__ == '__main__':
    main()

Running this:

python arg_test.py --arg1 asdf --arg2 qwer

Results in the expected output of:

the args are: Namespace(arg1='asdf', arg2='qwer')
the value of arg1 is : asdf
the value of arg2 is : qwer

Now here is the simple unittest program:

#test/test_arg_test.py
import unittest
from arg_test import Thingy


def test_parser(self):
    parser = Thingy.parse_args(['--arg1'])
    self.assertTrue(parser.arg1,'asdf')


if __name__ == '__main__':
    main()

Running this:

python -m unittest -v test/test_arg_test.py --arg1 asdf --arg2 qwer

Results in this:

python -m unittest -v test/test_arg_test.py --arg1 asdf --arg2 qwer
usage: python -m unittest [-h] [-v] [-q] [--locals] [-f] [-c] [-b]
                          [tests [tests ...]]
python -m unittest: error: unrecognized arguments: --arg1 asdf --arg2 qwer

Can someone please point me in the right direction on how to run these tests?

Thanks.

Update #1

Here is the updated unittest program based on the helpful recommendations below but something is still missing.

#import unittest
from arg_test import Thingy

class TestThingys(unittest.TestCase):
    def test_isupper(self):
        self.assertTrue('FOO'.isupper())
        self.assertFalse('Foo'.isupper())

    def test_parser(self):
        argv1 = ['--arg1', 'asdf', '--arg2', 'qwer']
        parser = Thingy().parse_args(argv1)
        self.assertTrue(parser.arg1,'asdf')

if __name__ == '__main__':
    main()

Running this:

python -m unittest -v test/test_arg_test.py

Results in this:

test_isupper (test.test_arg_test.TestThingys) ... ok
test_parser (test.test_arg_test.TestThingys) ... ERROR

======================================================================
ERROR: test_parser (test.test_arg_test.TestThingys)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/username/scripts/python/arg_test/test/test_arg_test.py", line 12, in test_parser
    parser = Thingy().parse_args(argv1)
TypeError: __init__() missing 1 required positional argument: 'name'

----------------------------------------------------------------------
Ran 2 tests in 0.001s

FAILED (errors=1)

Update #2

#test/test_arg_test.py
import unittest
from arg_test import Thingy

class TestThingys(unittest.TestCase):
    def test_isupper(self):
        self.assertTrue('FOO'.isupper())
        self.assertFalse('Foo'.isupper())

    def test_parser(self):
        argv1 = ['--arg1', 'asdf', '--arg2', 'qwer']
        parser = Thingy('name').parse_args(argv1)
        self.assertEquals(parser.arg1,'asdf')

if __name__ == '__main__':
    main()

Running this:

python -m unittest -v test/test_arg_test.py

Results in this:

test_isupper (test.test_arg_test.TestThingys) ... ok
test_parser (test.test_arg_test.TestThingys) ... ERROR

======================================================================
ERROR: test_parser (test.test_arg_test.TestThingys)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/username/scripts/python/arg_test/test/test_arg_test.py", line 12, in test_parser
    parser = Thingy('name').parse_args(argv1)
TypeError: parse_args() takes 1 positional argument but 2 were given

----------------------------------------------------------------------
Ran 2 tests in 0.001s

FAILED (errors=1)
5
  • 1
    unittest runs its own parser that doesn't recognize your arguments. You are seeing its usage, not your's. Commented Apr 15, 2018 at 2:48
  • In addition, you already specified the arguments for the test in the test; you don't need to put them on the command line. Commented Apr 15, 2018 at 3:20
  • 2 changes needed, Thingy() to be Thingy('name'), and self.assertTrue(parser.arg1,'asdf') to be replaced with self.assertEquals() Commented Apr 15, 2018 at 17:51
  • It is not an answer to you question, but I think you should not test directly args parsing (assume it works, as it is standalone well tested module) and simply do not use it directly in your code. To stub args object use NamedTuple (or equivalent type) Commented Apr 15, 2018 at 18:02
  • 2
    @R2RT, the reason to test is ensure the options has been used will not get changed without a warning. The purpose is not to test argparse. Commented Apr 15, 2018 at 18:35

1 Answer 1

4

use argv inside class TestThingy

def test_parser(self):
    argv1 = ['--arg1', 'asdf', '--arg2', 'qwer']
    parser = Thingy('name').parse_args(argv1)
    self.assertEquals(parser.arg1,'asdf')

    argv2 = ['--trigger_exception`, 'asdf`]
    with self.assertRaise(Exception):
        parser = Thingy('name').parse_args(argv2)
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the feedback. I updated the code based on your recommendations, tested and put the results above, could you please have a look?
@user9074332, my mistake, I updated my code with the bug fixed, thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.