Pythonunit testing传递参数

在Python中,我如何将命令行中的parameter passing给unittest函数。 这是迄今的代码…我知道这是错的。

class TestingClass(unittest.TestCase): def testEmails(self): assertEqual(email_from_argument, "my_email@example.com") if __name__ == "__main__": unittest.main(argv=[sys.argv[1]]) email_from_argument = sys.argv[1] 

用上面关于unit testing的评论来扩展。 unit testing应该是独立的,因为它们在设置之外没有任何依赖关系,并且可以拆除需求,比如在你的情况下设置一个电子邮件。 这确保每个testing对testing都有非常特殊的副作用和反应。 传入参数会破坏unit testing的这个属性,从而使它们在某种意义上是无效的。 使用testingconfiguration是最简单的方法,也是更合适的,因为unit testing再也不应该依靠外部信息来执行testing。 这是集成testing。

所以这里的医生说:“你说伤了,不要那样做!” 可能是对的。 但是,如果你真的想要的话,这里有一个方法将parameter passing给unittesttesting:

 import sys import unittest class MyTest(unittest.TestCase): USERNAME = "jemima" PASSWORD = "password" def test_logins_or_something(self): print 'username', self.USERNAME print 'password', self.PASSWORD if __name__ == "__main__": if len(sys.argv) > 1: MyTest.PASSWORD = sys.argv.pop() MyTest.USERNAME = sys.argv.pop() unittest.main() 

你需要argv.pop s,所以你的命令行参数不会argv.pop unittest自己…

[更新]你可能要考虑的另一件事是py.test 。 所有的酷孩子都说这是最好的Pythontesting框架,它可以让你参数化testing :

对于那些真正想要这样做的人的另一种方法,不pipe正确的说法,你不应该这样做:

 import unittest class MyTest(unittest.TestCase): def __init__(self, testName, extraArg): super(MyTest, self).__init__(testName) # calling the super class init varies for different python versions. This works for 2.7 self.myExtraArg = extraArg def test_something(self): print self.myExtraArg # call your test suite = unittest.TestSuite() suite.addTest(MyTest('test_something', extraArg)) unittest.TextTestRunner(verbosity=2).run(suite) 

unit testing是为了testing非常基本的function(应用程序的最低级别的function),以确保您的应用程序构build块正常工作。 可能没有什么正式的定义是什么意思,但你应该考虑其他types的更大function的testing – 请参阅集成testing 。 unit testing框架可能不是理想的目的。

如果你想在unittest.TestLoader使用steffens21的方法 ,你可以修改原来的testing加载器(见unittest.py ):

 import unittest from unittest import suite class TestLoaderWithKwargs(unittest.TestLoader): """A test loader which allows to parse keyword arguments to the test case class.""" def loadTestsFromTestCase(self, testCaseClass, **kwargs): """Return a suite of all tests cases contained in testCaseClass.""" if issubclass(testCaseClass, suite.TestSuite): raise TypeError("Test cases should not be derived from "\ "TestSuite. Maybe you meant to derive from"\ " TestCase?") testCaseNames = self.getTestCaseNames(testCaseClass) if not testCaseNames and hasattr(testCaseClass, 'runTest'): testCaseNames = ['runTest'] # Modification here: parse keyword arguments to testCaseClass. test_cases = [] for test_case_name in testCaseNames: test_cases.append(testCaseClass(test_case_name, **kwargs)) loaded_suite = self.suiteClass(test_cases) return loaded_suite # call your test loader = TestLoaderWithKwargs() suite = loader.loadTestsFromTestCase(MyTest, extraArg=extraArg) unittest.TextTestRunner(verbosity=2).run(suite) 

有同样的问题。 我的解决scheme是在使用argparse或其他方式parsing参数之后,从sys.argv中删除参数

 sys.argv = sys.argv[:1] 

如果你需要,你可以从main.parseArgs()过滤unittest参数

即使testing大师说我们不应该这样做,我是这样做的。 在某些情况下,使参数驱动testing朝向正确的方向是很有意义的,例如:

  • 我现在应该使用十几张相同的USB卡中的哪一个?
  • 我现在应该使用哪个服务器进行这个testing?
  • 我应该使用哪个XXX?

对我来说,使用环境variables对于这个puprose来说已经足够了,因为你不必编写专门的代码来传递参数。 它由Python支持。 它干净简单。

当然,我并不是主张完全参数化的testing。 但是我们必须务实,正如我所说的,在某些情况下,你需要一个或两个参数。 我们不应该这样做:)

 import os import unittest class MyTest(unittest.TestCase): def setUp(self): self.var1 = os.environ["VAR1"] self.var2 = os.environ["VAR2"] def test_01(self): print("var1: {}, var2: {}".format(self.var1, self.var2)) 

然后从命令行(在Linux上testing)

 $ export VAR1=1 $ export VAR2=2 $ python -m unittest MyTest var1: 1, var2: 2 . ---------------------------------------------------------------------- Ran 1 test in 0.000s OK