Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从TestCase派生类会引发两个错误_Python_Unit Testing - Fatal编程技术网

Python 从TestCase派生类会引发两个错误

Python 从TestCase派生类会引发两个错误,python,unit-testing,Python,Unit Testing,我有一些基本的设置/拆卸代码,我想在一大堆单元测试中重用它们。所以我有了一个好主意,创建一些派生类,以避免在每个测试类中重复代码 在这样做的过程中,我收到了两个奇怪的错误。第一,我无法解决。这是一个无法解决的问题: AttributeError: 'TestDesktopRootController' object has no attribute '_testMethodName' 这是我的基本类: import unittest import twill import cherrypy f

我有一些基本的设置/拆卸代码,我想在一大堆单元测试中重用它们。所以我有了一个好主意,创建一些派生类,以避免在每个测试类中重复代码

在这样做的过程中,我收到了两个奇怪的错误。第一,我无法解决。这是一个无法解决的问题:

AttributeError: 'TestDesktopRootController' object has no attribute '_testMethodName'
这是我的基本类:

import unittest
import twill
import cherrypy
from cherrypy._cpwsgi import CPWSGIApp


class BaseControllerTest(unittest.TestCase):

    def __init__(self):
        self.controller = None

    def setUp(self):
        app = cherrypy.Application(self.controller)

        wsgi = CPWSGIApp(app)

        twill.add_wsgi_intercept('localhost', 8080, lambda : wsgi)

    def tearDown(self):
        twill.remove_wsgi_intercept('localhost', 8080)
这是我的派生类:

import twill
from base_controller_test import BaseControllerTest

class TestMyController(BaseControllerTest):

    def __init__(self, args):
        self.controller = MyController()
        BaseControllerTest.__init__(self)

    def test_root(self):
        script = "find 'Contacts'"
        twill.execute_string(script, initial_url='http://localhost:8080/')
另一个奇怪的错误是:

TypeError: __init__() takes exactly 1 argument (2 given)
对此的“解决方案”是在派生类的
\uuu init\uuu
函数中添加“args”一词。有什么办法可以避免吗


记住,我在这一个中有两个错误。

BaseController
\uuuu init\uuuu
中,您需要调用
unittest.TestCase
\uu init\uuu
就像在
TestMyController
中一样

从框架构造TestCase的调用可能传递了一个参数。对于派生类,处理此问题的最佳方法是:

class my_subclass(parentclass):
    def __init__(self, *args, **kw):
        parentclass.__init__(self, *args, **kw)
        ...

这是因为您不正确地重写了
\uuuu init\uuuu()
。几乎可以肯定的是,您根本不想覆盖
\uuuu init\uuuu()
;您应该在
setUp()
中完成所有操作。我已经使用
unittest
10年了,我想我从来没有重写过
\uuuu init\uuuu()

但是,如果您确实需要重写
\uuuu init\uuuu()
,请记住,您无法控制构造函数的调用位置——框架会为您调用它。所以你必须提供一个它可以调用的签名。从源代码(
unittest/case.py
)中,该签名是:

def __init__(self, methodName='runTest'):
这样做的安全方法是接受任何参数并将其传递给基类。以下是一个工作实现:

class BaseTest(unittest.TestCase):
    def __init__(self, *args, **kwargs):
        unittest.TestCase.__init__(self, *args, **kwargs)

    def setUp(self):
        print "Base.setUp()"

    def tearDown(self):
        print "Base.tearDown()"


class TestSomething(BaseTest):
    def __init__(self, *args, **kwargs):
        BaseTest.__init__(self, *args, **kwargs)
        self.controller = object()

    def test_silly(self):
        self.assertTrue(1+1 == 2)

为什么要重写
\uuuu init\uuuu()
?通常,我们覆盖
设置
。我很好奇……为什么不使用init呢?在我的情况下,我正在用一个通用类对Django的TestCase进行子类化,然后将其子类化以创建特定的测试。测试之间的唯一区别在于类属性,它是放入
\uuuu init\uuuu()
的完美工具。我在这里遗漏了什么?@mlissner:首先,你的术语搞错了。如果要在
\uuuu init\uuuu()
中设置属性,则它不是类属性,而是实例属性。当您在类作用域中,在任何方法之外设置某个对象时,它就是一个类属性。@mlissner:其次,重写
TestCase是非常罕见的。\uuu init\uu()
,因为它根本不是必需的。对于每个测试,
unittest
创建一个新的测试类实例(调用
\uuu init\uuu()
),调用
setUp()
,调用正在运行的
test*()
方法,然后调用
tearDown()
setUp()
是官方指定的扩展点,每次调用
\uuuu init\uuuu()
时,
setUp()
也是如此。谢谢@GregWard。所以,一句话:传统。Unittest是一个奇怪的工具,按照惯例,它希望在
设置中使用这种工具。所以我想现在是unittest的约定与Python的问题。还感谢您对术语的更正。