【问题标题】:Python 2.6: proper usage of unittest.TestSuitePython 2.6:正确使用 unittest.TestSuite
【发布时间】:2011-02-27 21:36:40
【问题描述】:

使用Python 2.6,我在一个目录下的python文件中做了一个非常简单的测试:

#mytest.py
import unittest

class BasicTests(unittest.TestCase):
    def test_ok(self):
        self.assertTrue(True)

suite = unittest.TestLoader().loadTestsFromTestCase(BasicTests)

我切换到目录并运行python -m unittest mytest.suite,我收到以下错误:

Traceback (most recent call last):
  File "/usr/lib/python2.6/runpy.py", line 122, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.6/runpy.py", line 34, in _run_code
    exec code in run_globals
  File "/usr/lib/python2.6/unittest.py", line 875, in <module>
    main(module=None)
  File "/usr/lib/python2.6/unittest.py", line 816, in __init__
    self.parseArgs(argv)
  File "/usr/lib/python2.6/unittest.py", line 843, in parseArgs
    self.createTests()
  File "/usr/lib/python2.6/unittest.py", line 849, in createTests
    self.module)
  File "/usr/lib/python2.6/unittest.py", line 613, in loadTestsFromNames
    suites = [self.loadTestsFromName(name, module) for name in names]
  File "/usr/lib/python2.6/unittest.py", line 598, in loadTestsFromName
    test = obj()
  File "/usr/lib/python2.6/unittest.py", line 464, in __call__
    return self.run(*args, **kwds)
TypeError: run() takes exactly 2 arguments (1 given)

我尝试了几种变体(例如unittest.makeSuiteunittest.LoadTestFromNames),但它们都给了我相同的基本错误。我错过了什么?我保留reading the documentation,我似乎遵循规范。

【问题讨论】:

  • 只是猜测:在命令行中是否需要另一个参数?
  • 您可以通过使用unittest2nosepy.text 提供的测试运行程序来避免手动创建测试套件。
  • 令人沮丧的是你需要下载一个包来做一些简单的事情,比如为 python 获得一个像样的测试运行器,即使是 2.6 的新版本。 :(

标签: python unit-testing


【解决方案1】:

我通常不在命令行上使用unittest,但我有自己的测试运行脚本。

你需要在模块中添加一个函数suite

def suite():
    return unittest.TestLoader().loadTestsFromTestCase(BasicTests)

然后将其称为python -m unittest mytest.suite。但是后来我遇到了以下问题:

TypeError: calling <function suite at 0x00C1FB70> returned <unittest.TestSuite tests=[<mysite.BasicTests testMethod=test_ok>]>, not a test

这是因为unittest 使用了类似isinstance(mytest.suite(), TestSuite) 的东西,但是通过使用-m 执行,你会得到TestSuite 类的两个不同版本(一个是__main__.TestSuite,另一个是unittest.TestSuite),所以isinstance 返回错误。
对我来说,这看起来像一个错误。通过在loadTestsFromName 的开头插入from unittest import TestSuite, TestCase 来修补unittest.py 解决了isinstance 问题。抱歉,我无法为您提供“正确”解决方案(如果有的话)。

【讨论】:

  • 我已经对源代码进行了一些挖掘,这似乎是我的发行版构建的 python 2.6 中的一个错误。当我在 2.7 下执行时,问题就消失了。啊!
  • @dave:刚刚检查过了。他们在那里添加了一个特殊的__main__.py 文件,该文件有效地像我的解决方法一样工作。还在想 Python 2.6 是否有好的解决方案。
【解决方案2】:

更新:看起来我上面的内容实际上是正确的。当我安装 Python 2.7 的副本时,一切正常。我翻遍了unittest.py 源代码,发现这行代码并没有按照预期的方式运行:

    elif isinstance(obj, TestSuite):
        return obj
    elif hasattr(obj, '__call__'):
        test = obj()

第一个elif 条件失败,因此它落入引发异常之后的条件。我仍然不确定那是如何远程发生的——也许是一个糟糕的编译——但我​​已经继续前进并与提供者联系filed a bug

【讨论】:

  • 您可以简单地引用我的回答,而不是“出于任何原因”,我在其中清楚地描述了它失败的原因。下次请使用 Python 的 bug tracker,Launchpad 是为 Ubuntu 包设计的,而不是上游的。
【解决方案3】:

你可能想试试:

mytest.py:

import unittest

class BasicTests(unittest.TestCase):
    def test_ok(self):
        self.assertTrue(True)

if __name__ == '__main__':
    unittest.sys.argv.insert(1,'--verbose')
    unittest.main(argv = unittest.sys.argv)    

那么,

% python mytest.py

TestCase 的所有子类中运行所有测试,并且

% python mytest.py BasicTests.test_ok

只运行test_ok。当您知道某个测试存在问题并且不想运行每个测试时,该命令的第二种形式很有用。

【讨论】:

  • 是的,这很棒。但是为什么我不能只使用 unittest.main(argv = '-v'),这是一个错误吗?
  • 是否有某种功能可以将多个 TestCase 类添加到运行器?像 unittest.TestLoader().loadTestsFromTestCases([TestCases])?
  • @jaimechen:两个好问题。不幸的是,我对两者的回答都是……我不知道。请为每个问题设置一个新问题,以便其他人能够回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-02
  • 1970-01-01
  • 1970-01-01
  • 2015-05-17
  • 1970-01-01
  • 2013-05-17
  • 2018-09-20
相关资源
最近更新 更多