【问题标题】:How can I remove CLI arguments using argparse so unittest will accept arg list如何使用 argparse 删除 CLI 参数,以便 unittest 接受 arg list
【发布时间】:2019-09-26 19:12:25
【问题描述】:

我想将我自己的参数传递到为 unittest 设置的文件中。所以像这样从命令行调用它应该可以工作:

python Test.py --c keith.ini SomeTests.test_one

目前我遇到了两个问题。

1) Arg 解析不允许未知参数

用法:Test.py [-h] [--c CONFILE] Test.py:错误:无法识别的参数:SomeTests.test_one

2) 单元测试不允许未知参数。所以 --c fileName 不被 unittest 接受并返回:

AttributeError: 'module' 对象没有属性 'keith'

所以想法是在调用 unittest runner 之前收集我的参数并删除它们。

import unittest
import argparse

myArgs = None

def getArgs( allArgs ):
    parser = argparse.ArgumentParser( )
    parser.add_argument('--c', dest='conFile', type=str, default=None, help='Config file')
    args = parser.parse_args()

    if ( args.conFile == None ):
        parser.print_help()

    return args


class SomeTests(unittest.TestCase):
    def test_one(self):
        theTest( 'keith' )

    def test_two(self):
        otherTest( 'keith' )

if __name__ == '__main__':
    myArgs = getArgs( sys.argv )
    print 'Config File: ' + myArgs.conFile
    unittest.main( argv=sys.argv, testRunner = unittest.TextTestRunner(verbosity=2))

有趣的是我刚刚发现 parse_known_args() 所以我将解析行更改为:

args = parser.parse_known_args(['--c']). 

我认为这会解决我的问题并给我一些东西来传递给单元测试。不幸的是我得到:

Test.py: error: argument --c: expected one argument. 

这不应该工作吗?

【问题讨论】:

  • unittest 有自己的 sys.argv 解析器,可能是 argparse 解析器。我认为它在您的脚本之前运行。我没有办法做你想做的事。
  • 好的,我想通了。 Python的官方文档不正确。它显示包括已知参数的列表,但它仅在您不包含 parse_known_args() 函数的参数列表时才有效。我将 parse 和 extraArgs 都打印出来,它们都返回正确的列表。所以我“应该”能在午餐后完成剩下的工作。
  • 我的评论适用于您使用测试文件作为参数调用 unitest 的情况。您正在从脚本中调用 unitest,因此您拥有更多控制权。
  • @hpaulj OK 终于明白了。我继续并在下面提供了完整的答案。希望这会帮助下一个寻找这个的人。

标签: python python-2.7 argparse python-unittest


【解决方案1】:

OK 费了一番功夫,但还是搞定了。这是完全可能的。 argparse 的文档不正确。函数 parse_known_args() 不应包含已知参数的列表。 argparse 还删除了 arg[0],这对于返回很重要,因此其他命令可以看到有效的参数列表。我认为此删除是一个错误。我已经包含了最后的示例代码。

import unittest
import argparse
import sys

myArgs = None

def getArgs( allArgs ):
    parser = argparse.ArgumentParser( )
    parser.add_argument('--c', dest='conFile', type=str, default=None, help='Configuration file. (Required)')
    args, addArgs = parser.parse_known_args( )

    if ( args.conFile == None ):
        parser.print_help()
        sys.exit(2)

    # argparse strips argv[0] so prepend it
    return args, [ sys.argv[0]] + addArgs

def verify( expected, actual ):
    assert expected == actual, 'Test Failed: '

# Reusable Test
def theTest( exp ):
    print 'myargs: ' + str( myArgs )
    verify( exp, 'keith' )

def otherTest( exp ):
    theTest( exp )

class SomeTests(unittest.TestCase):
    def test_one(self):
        theTest( 'keith' )

    def test_two(self):
        otherTest( 'keith2' )

if __name__ == '__main__':
    myArgs, addArgs = getArgs( sys.argv )
    unittest.main( argv=addArgs, testRunner = unittest.TextTestRunner(verbosity=2))

一旦你把它保存到一个文件中,你就可以像下面的例子那样调用它,它就可以工作了。

python Test.py                     # Requires config file
python Test.py --c keith.ini       # Runs all tests
python Test.py --c keith.ini SomeTests          # Runs Class
python Test.py --c keith.ini SomeTests.test_one # Runs test

HTH,享受吧

【讨论】:

  • 它确实有帮助,谢谢你把它放在一起。不过,就像一个小问题一样,getArgs() 没有使用allArgs(而且addArgs 的名字很奇怪)
  • 这个例子只是展示了如何分离参数。 addArgs 是附加参数的缩写。它们不是我的解决方案需要运行的论点。将附加参数提供给 unittest,因为它们对于控制运行哪个测试很有用。请参阅顶部的示例。对我的实际代码中遗留的 allArgs 感到抱歉。
猜你喜欢
  • 2021-07-15
  • 2016-05-18
  • 2016-06-19
  • 2019-03-12
  • 2011-07-06
  • 2017-12-22
  • 2015-12-24
  • 1970-01-01
  • 2019-08-23
相关资源
最近更新 更多