Python unittest传递参数

时间:2012-07-08 03:20:34

标签: python unit-testing

在python中如何将命令行中的参数传递给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] 

8 个答案:

答案 0 :(得分:98)

所以这里的医生说“你说那伤害了?那就不要那样做了!”可能是对的。但是如果你真的想要,这是将参数传递给单元测试的一种方法:

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.USERNAME = sys.argv.pop()
        MyTest.PASSWORD = sys.argv.pop()
    unittest.main()

可以让你运行:

python mytests.py ausername apassword

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

[update]您可能想要研究的另一件事是使用环境变量:

import os
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__":
    MyTest.USERNAME = os.environ.get('TEST_USERNAME', MyTest.USERNAME)            
    MyTest.PASSWORD = os.environ.get('TEST_PASSWORD', MyTest.PASSWORD)
    unittest.main()

这将让你运行:

TEST_USERNAME=ausername TEST_PASSWORD=apassword python mytests.py

它的优点是你不会搞乱unittest自己的参数解析。缺点是它不会像在Windows上那样工作......

答案 1 :(得分:23)

扩展上述关于单元测试的评论。单元测试应该是独立的,因为它们在设置和拆除要求之外没有依赖关系,例如在您设置电子邮件的情况下。这可确保每项测试都有非常特殊的副作用和对测试的反应。传入参数会破坏单元测试的这个属性,从而使它们在某种意义上无效。使用测试配置是最简单的方法,也是更合适的方法,因为单元测试再也不应该依赖外部信息来执行测试。那是集成测试。

答案 2 :(得分:18)

对于那些真正想要这样做的人来说,尽管有正确的评论,你不应该这样做:

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)

答案 3 :(得分:3)

如果您想将steffens21's approachunittest.TestLoader一起使用,则可以修改原始测试加载器(请参阅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)

答案 4 :(得分:0)

Unit testing用于测试非常基本的功能(应用程序的最低级功能),以确保应用程序构建块正常工作。可能没有正式的定义是什么意思,但你应该考虑其他类型的测试更大的功能 - 见Integration testing。单元测试框架可能不是理想的用途。

答案 5 :(得分:0)

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

sys.argv = sys.argv[:1]  

如果需要,可以从main.parseArgs()

中过滤unittest参数

答案 6 :(得分:0)

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

  • 我现在应该使用十几张相同的USB卡进行此测试吗?
  • 我现在应该使用哪个服务器进行此测试?
  • 我应该使用哪个XXX?

对我来说,使用环境变量对于这个puprose是足够好的,因为你不必编写专用代码来传递你的参数;它受Python支持。它干净而简单。

当然,我并不主张完全可参数化的测试。但我们必须务实,正如我所说,在某些情况下,你需要一个或两个参数。我们不应该放弃它:))

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上测试)

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

OK

答案 7 :(得分:0)

这是我的解决方案:

# your test class
class TestingClass(unittest.TestCase):

    # This will only run once for all the tests within this class
    @classmethod
    def setUpClass(cls) -> None:
       if len(sys.argv) > 1:
          cls.email = sys.argv[1]

    def testEmails(self):
        assertEqual(self.email, "my_email@example.com")


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

您可以拥有一个 runner.py 文件,其中包含以下内容:

# your runner.py
loader = unittest.TestLoader()
tests = loader.discover('.') # note that this will find all your tests, you can also provide the name of the package e.g. `loader.discover('tests')
runner = unittest.TextTestRunner(verbose=3)
result = runner.run(tests

使用上面的代码,您应该使用 runner.py my_email@example.com 运行您的测试。