Unittest with command-line arguments

时间秒杀一切 提交于 2019-12-24 12:26:20

问题


From what I understand from another SO post, to unittest a script that takes command line arguments through argparse, I should do something like the code below, giving sys.argv[0] as arg.

import unittest
import match_loc

class test_method_main(unittest.TestCase):

    loc = match_loc.main()
    self.assertEqual(loc, [4])


if __name__ == '__main__':
    sys.argv[1] = 'aaaac'
    sys.argv[2] = 'ac'
    unittest.main(sys.argv[0])

This returns the error:

usage: test_match_loc.py [-h] text patterns [patterns ...]
test_match_loc.py: error: the following arguments are required: text, patterns

I would like to understand what is going on here deeper. I understand

if __name__ == '__main__': main()

says that if this is being executed by the 'main', highest level, default interpreter, to just automatically run the 'main' method. I'm assuming

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

just happens to be the way you say this for running unittest scripts.

I understand when any script is run, it automatically has an argv object, a vector collecting all the items on the command line.

But I do not understand what unittest.main(sys.arg[0]) would do. What does 'unittest.main' do with arguments? How can I pre-set the values of sys.argv - doesn't it automatically reset every time you run a script? Furthermore, where does this object 'sys.argv' exist, if outside of any script? Finally, what is the correct way to implement tests of command-line arguments?

I am sorry if my questions are vague and misguided. I would like to understand all the components relevant here so I can actually understand what I am doing.

Thank you very much.


回答1:


Just by playing around with a pair of simple files, I find that modifying sys.argv in the body of the caller module affects the sys.argv that the imported module sees:

import sys
sys.argv[1] = 'aaaac'
sys.argv[2] = 'ac'
class test_method_main(unittest.TestCase):
   ...

But modifying sys.argv in the main block as you do, does not show up in the imported one. We could dig into the documentation (and code) to see exactly why, but I think it's enough to just identify what works.

Here's what I reconstructed from your previous question of the imported module - with a few diagnostic prints

import argparse
import sys
def main():
    print(sys.argv)
    parser = argparse.ArgumentParser(
            description='Takes a series of patterns as fasta files'
            ' or strings and a text as fasta file or string and'
            ' returns the match locations by constructing a trie.')
    parser.add_argument('text')
    parser.add_argument('patterns', nargs='+')
    args = parser.parse_args()
    print(args)
    return 1

You could also test a parser with your own list of strings, recognising that parse_args uses sys.argv[1:] if its argument is missing or None:

def main(argv=None):
    print(argv)
    ...
    args = parser.parse_args(argv)
    print(args)
    return 1

loc = match_loc.main(['abc','ab'])  # and in the caller

Even though I was able to construct a working test case, you really should have given enough information that I didn't need to guess or dig around.



来源:https://stackoverflow.com/questions/32569245/unittest-with-command-line-arguments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!