如何更改Python中TestCase类的文档字符串?

1 投票
2 回答
1415 浏览
提问于 2025-04-16 16:45

在Python 2.5(实际上是Jython)中,对于UnitTest的TestCase类,没有SetUpClass这个方法,而且__init__方法也不太合适(因为没有对self的引用)。

当我尝试在TestCase里面修改文档字符串时:

import os
fileName = os.path.split(__file__)[1]
testCaseName = os.path.splitext(fileName)[0]
setattr(__name__, '__doc__', testCaseName)

我得到了:

setattr(__name__, '__doc__', testCaseName)
TypeError: readonly attribute

我试着通过把它实例化成一个对象来改变文档字符串(在这个地方self.__doc__是可以写的)。

更新:但我想避免在子类中增加额外的代码(也就是说,不想继承父类的功能来设置子类的文档字符串),例如:

文件DynamicTestCase.py包含:

class DynamicTestCase(unittest.TestCase):
    def setDocstring(self, testCaseDocstring=None):
        if not testCaseDocstring:
            fileName = os.path.split(__file__)[1]
            testCaseDocstring = os.path.splitext(fileName)[0]
        setattr(self, '__doc__', testCaseDocstring)

文件MyTestCase.py包含:

class MyTestCase(DynamicTestCase):
    def test_print_docstring(self):
        self.setDocstring()
        print 'MyTestCase Docstring = ', self.__doc__

但是,unittest的运行结果还是:

MyTestCase Docstring = DynamicTestCase

而我原本期待的是MyTestCase Docstring = MyTestCase

2 个回答

0

你现在获取的是动态测试案例文件的文件名,而不是调用这个函数的文件名。要想得到调用文件的名字,你需要查看它的调用栈。

  import inspect

  class DynamicTestCase(unittest.TestCase):
    def setDocstring(self, testCaseDocstring=None):
        if not testCaseDocstring:
            fileName = 'unknown.py'

            # Go up one stack frame and grab the file name
            stack = inspect.stack()
            try:
                frame = stack[1][0]
                fileName = frame.f_code.co_filename        
            finally:
                del stack

            testCaseDocstring = os.path.splitext(fileName)[0]
1

更新 - __file__ 是当前模块加载时的路径名,所以在 DynamicTestCase.py 文件中使用 __file__ 会得到路径 DynamicTestCase.py。不过,你可以从子类中像这样把路径传给 setDocstring()

DynamicTestCase.py:

class DynamicTestCase(unittest.TestCase):
    def setDocstring(self, docstring=None):
        if docstring is None:
            docstring = __file__
        if os.path.exists(docstring):
            name = os.path.split(docstring)[1]
            docstring = os.path.splitext(name)[0]
        setattr(self, '__doc__', docstring)

MyTestCase.py:

class MyTestCase(DynamicTestCase):
    def __init__(self, *args, **kwargs):
        DynamicTestCase.__init__(self, *args, **kwargs)
        self.setDocstring(__file__)

    def test_print_docstring(self):
        print 'MyTestCase Docstring = ', self.__doc__

    def test_new_docstring(self):
        self.setDocstring('hello')
        print 'MyTestCase Docstring = ', self.__doc__

输出:

MyTestCase Docstring =  MyTestCase
MyTestCase Docstring =  hello

答案的其余部分

在你上面的代码中,__name__ 是一个字符串,而不是一个类。Jython 正确地拒绝修改 str 类型的 __doc__ 属性。

你能稍微解释一下 为什么 想要改变 TestCase 的文档字符串吗?比如,你可以创建一个 TestCase 的子类,并给它自己的文档字符串:

class MyTestCase(unittest.TestCase):
    "Docstring of MyTestCase"

不确定你是否试过,但 unittest2 包 的 TestCase 有 setUpClass, tearDownClass 这些类方法。这是将 Python 2.7 的改进移植到 Python 2.6 及之前版本的。

Jython 允许你设置新式类的 __doc__,但 CPython 不允许。因此,如果你想让你的代码可移植,可能需要找其他方法来实现你的目标:

Jython 2.2.1 on java1.6.0_24
>>> unittest.TestCase.__doc__ = 'foo bar'
>>> unittest.TestCase.__doc__
'foo bar'

Python 2.6.6 (r266:84292, Feb 12 2011, 01:07:21)
>>> unittest.TestCase.__doc__ = 'foo bar'
AttributeError: attribute '__doc__' of 'type' objects is not writable

撰写回答