如何更改Python中TestCase类的文档字符串?
在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 个回答
你现在获取的是动态测试案例文件的文件名,而不是调用这个函数的文件名。要想得到调用文件的名字,你需要查看它的调用栈。
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]
更新 - __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