Python 单元测试加载程序在 __init__() 调用期间抛出 TypeError

Python unittest loader throws TypeError during an __init__() call

我已经为我的 Python 应用程序编写了一堆测试,但它们突然似乎不再正常工作!

我在 tests 模块中创建了一堆测试:

tests.__main__.py 中,我包含了以下代码来加载我的测试套件:

import unittest

if __name__ == "__main__":
    loader = unittest.TestLoader()
    start_dir = "."
    suite = loader.discover(start_dir=start_dir, pattern='*_test.py')

    runner = unittest.TextTestRunner()
    runner.run(suite)

我知道我听起来像个菜鸟,但大约一个小时前,这些测试对我来说还算完美。我会通过从我的基本目录中键入 python3 -m tests 来发布它们。但是,我现在收到了一个非常 st运行ge TypeError:

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/Users/yuchen/Desktop/myproj/myapp/tests/__main__.py", line 6, in <module>
    suite = loader.discover(start_dir=start_dir, pattern='*_test.py')
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/loader.py", line 341, in discover
    tests = list(self._find_tests(start_dir, pattern))
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/loader.py", line 406, in _find_tests
    yield from self._find_tests(full_path, pattern, namespace)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/loader.py", line 406, in _find_tests
    yield from self._find_tests(full_path, pattern, namespace)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/loader.py", line 398, in _find_tests
    full_path, pattern, namespace)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/loader.py", line 452, in _find_test_path
    return self.loadTestsFromModule(module, pattern=pattern), False
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/loader.py", line 123, in loadTestsFromModule
    tests.append(self.loadTestsFromTestCase(obj))
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/loader.py", line 92, in loadTestsFromTestCase
    loaded_suite = self.suiteClass(map(testCaseClass, testCaseNames))
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/suite.py", line 24, in __init__
    self.addTests(tests)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/suite.py", line 57, in addTests
    for test in tests:
TypeError: __init__() takes 0 positional arguments but 2 were given

我已经跟踪堆栈跟踪到我认为是导致问题的适当文件,unittest:

suite.py 文件
"""TestSuite"""

import sys

from . import case
from . import util

__unittest = True


def _call_if_exists(parent, attr):
    func = getattr(parent, attr, lambda: None)
    func()


class BaseTestSuite(object):
    """A simple test suite that doesn't provide class or module shared fixtures.
    """
    _cleanup = True

    def __init__(self, tests=()):
        self._tests = []
        self._removed_tests = 0
        print("Tests", tests) # <--- this was added by me
        self.addTests(tests) 

但是,__init__() 签名似乎不需要 0 个位置参数。而且,它显然正在执行,因为我在上面的代码中添加了 print("Tests", tests) 之后,在抛出错误之前我看到了以下输出:

Tests: []
Tests: <map object at 0x11033c0b8>
Tests: <map object at 0x11033c0b8>
Tests: <map object at 0x11033c0b8>
Tests: [<unittest.suite.TestSuite tests=[... a list of my tests]]
Tests: <map object at 0x110483978>
Tests: <map object at 0x110483978>
Traceback (most recent call last):

我对发生的事情一头雾水。堆栈跟踪中打印的错误似乎与我在源代码中看到的完全不一致。

编辑(分辨率):

被接受的答案是正确的。我已经编写了另一个测试 class,并决定简单地为 __init__ 方法添加一个存根:

class MyUnfinishedTest(BaseTest):

    def __init__():
        pass

然后我忘记了它并从事其他工作,运行 测试。那是我开始看到我的错误的时候。从我的测试模块中删除这个 class 后,测试 运行 顺利。

回溯看起来有点混乱的原因之一是行:

for test in tests

实际上是在调用一个生成器,它正在运行中发现并加载测试。

所以我猜这是:

TypeError: __init__() takes 0 positional arguments but 2 were given

实际上意味着发现过程找到了一个无法加载的测试class,可能是因为 class 有自己的 __init__ 方法,其参数数量与发现的不同期待。

我会仔细检查您的测试 classes 是否有 __init__ 方法,并且可能还会更改此行:

start_dir = "."

至:

start_dir = os.path.dirname(__file__)

这意味着发现过程将从 tests 文件夹向下查找,这比“.”更安全。 (当前工作目录)因为当前工作目录可能会根据您开始测试的位置而改变(并且可能最终会选择您不期望的测试)。