pytest:安装/拆卸方法的过程中获取参数多态值
我的自动化框架使用pytest设置/测试,而不是固定装置的拆卸式。我也有类的几个层次:pytest:安装/拆卸方法的过程中获取参数多态值
BaseClass
- 最高的,所有测试inhriet从中
FeatureClass
- 中,涉及到程序的所有测试功能,从它继承
TestClass
- 保持实际测试
编辑,为例子起见,我改变DB调用一个简单的打印
我想在所有设置/拆卸中添加数据库报告。即我想,一般BaseClass
setup_method
将创建测试DB项,teardown_method
将改变的结果的条目。我已经试过,但我似乎无法在运行时脱身方法的当前运行的测试值。甚至可能吗?如果不是,我该怎么办呢?
样品: (在base.py)
class Base(object):
test_number = 0
def setup_method(self, method):
Base.test_number += 1
self.logger.info(color.Blue("STARTING TEST"))
self.logger.info(color.Blue("Current Test: {}".format(method.__name__)))
self.logger.info(color.Blue("Test Number: {}".format(self.test_number)))
# --->here i'd like to do something with the actual test parameters<---
self.logger.info("print parameters here")
def teardown_method(self, method):
self.logger.info(color.Blue("Current Test: {}".format(method.__name__)))
self.logger.info(color.Blue("Test Number: {}".format(self.test_number)))
self.logger.info(color.Blue("END OF TEST"))
(在my_feature.py)
class MyFeature(base.Base):
def setup_method(self, method):
# enable this feature in program
return True
(在test_my_feature.py)
class TestClass(my_feature.MyFeature):
@pytest.mark.parametrize("fragment_length", [1,5,10])
def test_my_first_test(self):
# do stuff that is changed based on fragment_length
assert verify_stuff(fragment_length)
所以我怎样才能获得setup_method的参数,基本父类的测试框架的?
简要的回答:不,你不能做到这一点。是的,你可以解决它。
的时间长一点:这些单元测试样式设置&拆解只为与单元测试风格测试兼容性完成。他们不支持pytest的夹具,这使pytest更好。
由于这个原因,既不pytest也不pytest的单元测试插件提供这些安装/拆卸方法的上下文。如果您有request
,function
或其他上下文对象,您可以通过request.getfuncargvalue('my_fixture_name')
动态获取灯具的值。
但是,您拥有的全部是self
/cls
和method
作为测试方法对象本身(即不是pytest的节点)。
如果你看看_pytest/unittest.py
插件里面,你会发现这个代码:
class TestCaseFunction(Function):
_excinfo = None
def setup(self):
self._testcase = self.parent.obj(self.name)
self._fix_unittest_skip_decorator()
self._obj = getattr(self._testcase, self.name)
if hasattr(self._testcase, 'setup_method'):
self._testcase.setup_method(self._obj)
if hasattr(self, "_request"):
self._request._fillfixtures()
首先,请注意setup_method()
被称为完全从pytest的对象(例如self
作为测试节点)分离。
二,请注意setup_method()
被称为后准备的灯具。所以即使你可以访问它们,它们也不会准备好。
所以,一般来说,你不能这样做,没有一些欺骗。
对于诡计,必须定义一次pytest钩/ hookwrapper,并记住pytest节点正在执行:
conftest.py
或任何其他插件:
import pytest
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_protocol(item, nextitem):
item.cls._item = item
yield
test_me.py
:
import pytest
class Base(object):
def setup_method(self, method):
length = self._item.callspec.getparam('fragment_length')
print(length)
class MyFeature(Base):
def setup_method(self, method):
super().setup_method(method)
class TestClass(MyFeature):
@pytest.mark.parametrize("fragment_length", [1,5,10])
def test_my_first_test(self, fragment_length):
# do stuff that is changed based on fragment_length
assert True # verify_stuff(fragment_length)
还要注意的是MyFeature.setup_method()
亩st由于显而易见的原因,请致电父母的super(...).setup_method()
。
的cls._item
将在每个callspec(即,与每个参数的每个函数调用)来设置。如果您愿意,您也可以将项目或特定参数放入其他全局状态。
另外要小心不要保存在item.instance
领域。该类的实例将在稍后创建,并且您必须使用setup_instance/teardown_instance
方法。否则,保存的实例字段不会保留,并且不可用在setup_method()
中。
下面是执行:
============ test session starts ============
......
collected 3 items
test_me.py::TestClass::test_my_first_test[1] 1
PASSED
test_me.py::TestClass::test_my_first_test[5] 5
PASSED
test_me.py::TestClass::test_my_first_test[10] 10
PASSED
============ 3 passed in 0.04 seconds ============
感谢详细的答复,这真的帮助我理解pytest更好。我会试着去实现这个。我看你明确地使用“fragment_length”得到它的价值,所以如果我想获得的所有参数的测试一定有我需要得到self._item.callspec.params和遍历它的价值观? –
@AvishayCohen我不能肯定地说,但很可能是的。这里的所有字段和方法都是pytest的高级API的一部分。唯一的问题是item/node/callspec没有暴露给unittest的类/方法。我认为,这是为了向后兼容unittest而设计的,并不适用于正常的pytest使用。 –
是的。它工作得很好! –
是否使用'unittest.TestCase'?然后,您可以将'setup'中的值设置为'self'并在测试中检索它。需要更多详细信息才能回答此问题。 – Arunmozhi
@Arunmozhi我已经添加了一些基本的代码,希望它会澄清什么,我试图做 –