0

Please help me to write the unit test to this:

I have a simple program with one function which returns only doubled "name" when run the program with argparse argument --double. Otherwise returns a single name

    # code.py
    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument("name")
    parser.add_argument('-d', '--double', action="store_true")
    
    args = parser.parse_args()
    
    def double_name(new_name):
      if args.double:
        return new_name + new_name
      else:
        return new_name
    
    print(double_name(args.name))
  1. run in cmd python code.py test-name I have a result: test-name
  2. run in cmd python code.py test-name -d I have a result: test-nametest-name

I want to write unittest to check this function, but I don't know how to call this function with argparse arguments in unit test.

    # test_code.py
    import unittest
    import code
    
    class Test_Code(unittest.TestCase):
    
      def test_double_name(self):
        # without -d
        self.assertEqual(code.double_name('test-name'), 'test-name')
        # with -d
        self.assertEqual(code.double_name('test-name'), 'test-nametest-name')
    
    if __name__ == "__main__":
      unittest.main()

How should look the run command this test? If I add to code:

    code.args = code.parser.parse_args(["test-name", "-d"])

the standard commands python -m unittest test_code.py raise AttributeError

AttributeError: 'module' object has no attribute 'py'

Pshowo
  • 1
  • 2

2 Answers2

0

Do the accessing of parsed data outside of the function, and pass the data in. Then it doesn't matter where the data comes from:

def double_name(new_name, double):
  if double:
    return new_name + new_name
  else:
    return new_name

print(double_name(args.name, args.double))

Then:

self.assertEqual(code.double_name('test-name', False), 'test-name')
Carcigenicate
  • 43,494
  • 9
  • 68
  • 117
0

You can call parse_args with your own list of arguments, letting it produce an appropriate value to use. This requires rewriting code slightly to avoid having it call parse_arg on import:

# code.py
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("name")
parser.add_argument('-d', '--double', action="store_true")


def double_name(new_name):
  if args.double:
    return new_name + new_name
  else:
    return new_name


if __name__ == "__main__":
    args = parser.parse_args()
    print(double_name(args.name))

Then

# test_code.py
import unittest
import code


class Test_Code(unittest.TestCase):

  def test_double_name(self):
    code.args = code.parser.parse_args([])
    self.assertEqual(code.double_name('test-name'), 'test-name')

    code.args = code.parser.parse_args(["-d"])
    self.assertEqual(code.double_name('test-name'), 'test-nametest-name')


if __name__ == "__main__":
  unittest.main()

In your test function, you need to make sure that you set the value of code.args, since that's the variable used by code.double_name.

chepner
  • 497,756
  • 71
  • 530
  • 681