是否可以使用python装饰器将特定的单元测试指向所测试内容的不同实例?

是否可以使用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

我有一个包含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 """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

As
get_model1
get_model2
是采用
self
(在您的示例中),在
model_contents
I pass
ContainerForStringXMLs
类为
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 from
object

我真的很难理解您为什么要这样做。为什么测试定义之前的
@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")