Python:对包含基类的项目进行鼻子测试
Python: nosetests on project containing baseclasses
我创建了一个包,其中包含一个基础 class,未来的项目将从中继承。我正在尝试自动化测试,并已转向 nosetests。
我是 Python 的新手,如果我的问题出在 trivial/rudimentary。
,我深表歉意
这个项目利用了流行的 Python 有限状态机包 transitions, from which my base class inherits State(如我所见 states.py)。
在 运行 $nosetests
从 base_tester/
中,我收到 3 个重复的错误(为简洁起见只粘贴了 1 个):
E.EE.
======================================================================
ERROR: Failure: TypeError (__init__() missing 1 required positional argument: 'name')
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/user/.pyenv/versions/3.7.1/lib/python3.7/site-packages/nose/failure.py", line 39, in runTest
raise self.exc_val.with_traceback(self.tb)
File "/home/user/.pyenv/versions/3.7.1/lib/python3.7/site-packages/nose/loader.py", line 523, in makeTest
return self._makeTest(obj, parent)
File "/home/user/.pyenv/versions/3.7.1/lib/python3.7/site-packages/nose/loader.py", line 582, in _makeTest
return MethodTestCase(obj)
File "/home/user/.pyenv/versions/3.7.1/lib/python3.7/site-packages/nose/case.py", line 346, in __init__
self.inst = self.cls()
File "/home/user/repos/openrov/production/testers/base_tester/base_tester/states.py", line 6, in __init__
super().__init__(*args, **kwargs)
TypeError: __init__() missing 1 required positional argument: 'name'
但是,当我创建一个小的测试项目,并实现一个继承class时,它按预期工作。我不得不相信我在 test.py 中所做的事情有问题,但无法弄清楚是什么。
谢谢!
项目结构:
base_tester/
├── base_tester/
│ ├── __init__.py
│ └── states.py
├── setup.py
└── test/
├── __init__.py
└── test.py
states.py:
from transitions import State
# Parent class
class TestParent(State):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# To be implemented by inheriting classes
def run_test(self):
raise NotImplementedError()
base_tester/init.py:
from base_tester.states import *
test/test.py:
import unittest
from base_tester import TestParent
class Test1(TestParent):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def run_test(self):
pass
class Tester(unittest.TestCase):
test1 = Test1(name='test1')
def test_1(self):
self.assertTrue(True)
def main(self):
pass
if __name__ == '__main__':
unittest.main()
问题出在TestParent
和Test1
中方法的命名上。更具体地说,是 Test1/TestParent.run_test
引起了麻烦。我假设 nose
认为这些方法是孤立的测试。结果,它尝试创建有问题的 class 的实例并失败,因为 TestParent
、Test1
和 State
没有默认值 name
.
参见docs about finding tests。它提到:
If it looks like a test, it’s a test. Names of directories, modules, classes and functions are compared against the testMatch regular expression, and those that match are considered tests. Any class that is a unittest.TestCase subclass is also collected, so long as it is inside of a module that looks like a test.
这也是您多次收到错误消息的原因。您的输出表明您(尝试)运行 五个测试,其中三个失败。
我只有 4 个,但也有 3 个失败的测试。为了更好地说明这一发现,我将默认的 name
添加到 TestParent
并让 TestParent.run_test
通过。如果我现在执行 nosetests -v
我会得到以下输出:
base_tester.TestParent.run_test ... ok
test.test.Test1.run_test ... ok
test.test.TestParent.run_test ... ok
test_1 (test.test.Tester) ... ok
TestParent.run_test
由于导入执行了两次。一个简单的解决方案是避免方法名称与测试模式正则表达式(提到的 in the docs)匹配,默认情况下是 (?:\b|_)[Tt]est
。但是有时出于语义原因无法避免在方法名称中使用 test
。
测试发现提到以下内容:
If an object defines a __test__ attribute that does not evaluate to True, that object will not be collected, nor will any objects it contains.
在你的情况下,将 __test__ = False
添加到 TestParent
应该也可以解决问题:
# Parent class
class TestParent(State):
__test__ = False # avoid nosetests test discover
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# To be implemented by inheriting classes
def run_test(self):
raise NotImplementedError()
我创建了一个包,其中包含一个基础 class,未来的项目将从中继承。我正在尝试自动化测试,并已转向 nosetests。
我是 Python 的新手,如果我的问题出在 trivial/rudimentary。
,我深表歉意这个项目利用了流行的 Python 有限状态机包 transitions, from which my base class inherits State(如我所见 states.py)。
在 运行 $nosetests
从 base_tester/
中,我收到 3 个重复的错误(为简洁起见只粘贴了 1 个):
E.EE.
======================================================================
ERROR: Failure: TypeError (__init__() missing 1 required positional argument: 'name')
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/user/.pyenv/versions/3.7.1/lib/python3.7/site-packages/nose/failure.py", line 39, in runTest
raise self.exc_val.with_traceback(self.tb)
File "/home/user/.pyenv/versions/3.7.1/lib/python3.7/site-packages/nose/loader.py", line 523, in makeTest
return self._makeTest(obj, parent)
File "/home/user/.pyenv/versions/3.7.1/lib/python3.7/site-packages/nose/loader.py", line 582, in _makeTest
return MethodTestCase(obj)
File "/home/user/.pyenv/versions/3.7.1/lib/python3.7/site-packages/nose/case.py", line 346, in __init__
self.inst = self.cls()
File "/home/user/repos/openrov/production/testers/base_tester/base_tester/states.py", line 6, in __init__
super().__init__(*args, **kwargs)
TypeError: __init__() missing 1 required positional argument: 'name'
但是,当我创建一个小的测试项目,并实现一个继承class时,它按预期工作。我不得不相信我在 test.py 中所做的事情有问题,但无法弄清楚是什么。
谢谢!
项目结构:
base_tester/
├── base_tester/
│ ├── __init__.py
│ └── states.py
├── setup.py
└── test/
├── __init__.py
└── test.py
states.py:
from transitions import State
# Parent class
class TestParent(State):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# To be implemented by inheriting classes
def run_test(self):
raise NotImplementedError()
base_tester/init.py:
from base_tester.states import *
test/test.py:
import unittest
from base_tester import TestParent
class Test1(TestParent):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def run_test(self):
pass
class Tester(unittest.TestCase):
test1 = Test1(name='test1')
def test_1(self):
self.assertTrue(True)
def main(self):
pass
if __name__ == '__main__':
unittest.main()
问题出在TestParent
和Test1
中方法的命名上。更具体地说,是 Test1/TestParent.run_test
引起了麻烦。我假设 nose
认为这些方法是孤立的测试。结果,它尝试创建有问题的 class 的实例并失败,因为 TestParent
、Test1
和 State
没有默认值 name
.
参见docs about finding tests。它提到:
If it looks like a test, it’s a test. Names of directories, modules, classes and functions are compared against the testMatch regular expression, and those that match are considered tests. Any class that is a unittest.TestCase subclass is also collected, so long as it is inside of a module that looks like a test.
这也是您多次收到错误消息的原因。您的输出表明您(尝试)运行 五个测试,其中三个失败。
我只有 4 个,但也有 3 个失败的测试。为了更好地说明这一发现,我将默认的 name
添加到 TestParent
并让 TestParent.run_test
通过。如果我现在执行 nosetests -v
我会得到以下输出:
base_tester.TestParent.run_test ... ok
test.test.Test1.run_test ... ok
test.test.TestParent.run_test ... ok
test_1 (test.test.Tester) ... ok
TestParent.run_test
由于导入执行了两次。一个简单的解决方案是避免方法名称与测试模式正则表达式(提到的 in the docs)匹配,默认情况下是 (?:\b|_)[Tt]est
。但是有时出于语义原因无法避免在方法名称中使用 test
。
测试发现提到以下内容:
If an object defines a __test__ attribute that does not evaluate to True, that object will not be collected, nor will any objects it contains.
在你的情况下,将 __test__ = False
添加到 TestParent
应该也可以解决问题:
# Parent class
class TestParent(State):
__test__ = False # avoid nosetests test discover
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# To be implemented by inheriting classes
def run_test(self):
raise NotImplementedError()