是否可以使用python装饰器将特定的单元测试指向所测试内容的不同实例?
我有一个包含XML字符串的类。这些是我的模型是否可以使用python装饰器将特定的单元测试指向所测试内容的不同实例?,python,inheritance,decorator,python-unittest,Python,Inheritance,Decorator,Python Unittest,我有一个包含XML字符串的类。这些是我的模型 class ContainerForStringXMLs(): def __init__(self): pass @staticmethod def get_model1(self): return """I'm a long string called model1""" @staticmethod def get_model2(self): return
class ContainerForStringXMLs():
def __init__(self):
pass
@staticmethod
def get_model1(self):
return """I'm a long string called model1"""
@staticmethod
def get_model2(self):
return """I'm a long string called model2"""
我有一个基本的测试类,它允许我访问其他测试中的模型(以及一些其他在这里不重要的东西)
我的实际测试类如下所示:
class TestClass(BaseTest):
def __init__(self):
pass
def test_on_model1(self):
"""
I want to perform this test on model1
"""
print self.test_model ##would return model 1
def test_on_model2(self):
"""
I want to perform this test on model 2
"""
print self.testmodel2
我想要执行的测试是完全相同的测试,但是模型是不同的,因此我从xml中提取的值在每种情况下都是不同的。我的问题是:有没有一种很好的pythonic方法可以在TestClass的模型之间切换?我在想也许是个装饰师还是什么的
如果我能够使用以下类似的方法来选择我将测试指向的模型,那就太好了:
class TestClass(BaseTest):
def __init__(self):
pass
@testmodel1
def test_on_model1(self):
"""
I want to perform this test on model1
"""
print self.test_model ##would return model 1
@testmodel2
def test_on_model2(self):
"""
I want to perform this test on model 2
"""
print self.testmodel2
这种行为可能吗?“XML字符串”类按原样在
models.py中。
测试助手(基类和装饰器)位于testutils.py
:
import unittest
import functools
import models
class BaseTestCase(unittest.TestCase):
def setUp(self, model='model1'):
self.model_loader = models.ContainerForStringXMLs
self.model = model
@property
def model_contents(self):
return getattr(
self.model_loader, 'get_' + self.model)(self.model_loader)
def use_model(model):
"""Make BaseTestCase-aware test use particular model."""
def _wrapper(func):
@functools.wraps(func)
def _inner(self):
orig = self.model
self.model = model
func(self)
self.model = orig
return _inner
return _wrapper
use\u model
是一个采用模型名称(model
)的装饰器,并且
暂时设置测试方法的self.model
<代码>型号内容
是从ContainerForStringXMLs
对于当前的self.model
Asget_model1
和get_model2
是采用self
(在您的示例中),在model_contents
I passContainerForStringXMLs
类为self
(这不是特别好)。如果那不是什么
您可以将(self.model\u loader)
更改为其他内容(当然
当然,将ContainerForStringXMLs
中的get.*
方法更改为匹配
你叫他们的方式)。考虑到这是一个小问题,我只是假设
只能修改测试和BaseTest
在test\u models.py
中有两个测试用例:
from testutils import BaseTestCase, use_model
class TwoModelsWithDefaultModelTest(BaseTestCase):
def setUp(self):
BaseTestCase.setUp(self, model='model2')
@use_model('model1')
def test_first_model(self):
self.assertEqual(self.model, 'model1')
self.assertEqual(
self.model_contents,
"I'm a long string called model1")
def test_second_model(self):
self.assertEqual(self.model, 'model2')
self.assertEqual(
self.model_contents,
"I'm a long string called model2")
@use_model('model1')
def test_first_model_again(self):
self.assertEqual(self.model, 'model1')
self.assertEqual(
self.model_contents,
"I'm a long string called model1")
def test_second_model_again(self):
self.assertEqual(self.model, 'model2')
self.assertEqual(
self.model_contents,
"I'm a long string called model2")
class TwoModelsTestWithoutExplicitSetUp(BaseTestCase):
@use_model('model1')
def test_first_model(self):
self.assertEqual(self.model, 'model1')
self.assertEqual(
self.model_contents,
"I'm a long string called model1")
@use_model('model2')
def test_second_model(self):
self.assertEqual(self.model, 'model2')
self.assertEqual(
self.model_contents,
"I'm a long string called model2")
def test_first_model_again(self):
self.assertEqual(self.model, 'model1')
self.assertEqual(
self.model_contents,
"I'm a long string called model1")
@use_model('model2')
def test_second_model_again(self):
self.assertEqual(self.model, 'model2')
self.assertEqual(
self.model_contents,
"I'm a long string called model2")
TwoModelsWithDefaultModelTest
调用BaseTestCase.setUp
对于不使用的测试,将self.model
设置为'model2'
使用_model
装饰器TwoModelsTestWithoutExplicitSetUp
使用
BaseTestCase.setUp的默认实现
model
参数默认值,因此默认值self.model
是'model1'
根据print
语句判断,您使用的是Python 2。你
制作
ContainerForStringXMLs
inherit fromobject
我真的很难理解您为什么要这样做。为什么测试定义之前的@testmodel1
比测试定义内部的self.test\u model=ContainerForStringXMLs.model1()
更可取?或者更好的方法是,将单独模型的测试拉到单独的测试用例中,然后覆盖setUp
以使用适当的模型。
from testutils import BaseTestCase, use_model
class TwoModelsWithDefaultModelTest(BaseTestCase):
def setUp(self):
BaseTestCase.setUp(self, model='model2')
@use_model('model1')
def test_first_model(self):
self.assertEqual(self.model, 'model1')
self.assertEqual(
self.model_contents,
"I'm a long string called model1")
def test_second_model(self):
self.assertEqual(self.model, 'model2')
self.assertEqual(
self.model_contents,
"I'm a long string called model2")
@use_model('model1')
def test_first_model_again(self):
self.assertEqual(self.model, 'model1')
self.assertEqual(
self.model_contents,
"I'm a long string called model1")
def test_second_model_again(self):
self.assertEqual(self.model, 'model2')
self.assertEqual(
self.model_contents,
"I'm a long string called model2")
class TwoModelsTestWithoutExplicitSetUp(BaseTestCase):
@use_model('model1')
def test_first_model(self):
self.assertEqual(self.model, 'model1')
self.assertEqual(
self.model_contents,
"I'm a long string called model1")
@use_model('model2')
def test_second_model(self):
self.assertEqual(self.model, 'model2')
self.assertEqual(
self.model_contents,
"I'm a long string called model2")
def test_first_model_again(self):
self.assertEqual(self.model, 'model1')
self.assertEqual(
self.model_contents,
"I'm a long string called model1")
@use_model('model2')
def test_second_model_again(self):
self.assertEqual(self.model, 'model2')
self.assertEqual(
self.model_contents,
"I'm a long string called model2")