如何逐行停止执行功能?

时间:2014-10-05 13:28:19

标签: python testing

我很难总结这个问题,所以我会描述我想要做的事情:

我正在为某种产品编写测试解决方案,比方说微波炉。目的是在使用微波炉的同时测量各种资源。为此,我写了一个名为measure()的上下文管理器。

使用微波API我编写了一个模拟微波基本用例的函数,并用一个完成所有测量的函数进行装饰:

def test_function(fn):
    def wrapper(*args, **kwargs):
        with measure():
            fn(*args, **kwargs)

    return wrapper

@test_function
def prepare_food():
    microwave = Microwave()
    microwave.open_door()
    microwave.insert_food()
    microwave.close_door()
    microwave.turn_on(seconds = 60)

prepare_food()

当然,微波炉只是一个例子,我有很多这样的微波炉"。

经过几天的测试和测量后,我的团队决定分别测量每个动作,这意味着我的测试功能现在看起来像这样:

def test_prepare_food():
    microwave = Microwave()
    actions = {
            microwave.open_door : [],
            microwave.insert_food : [],
            microwave.close_door() : [],
            microwave.turn_on : [60]
            }
    for (action, args) in actions.items():
            with measure():
                action(*args)

test_prepare_food的问题是,现在每个prepare_food函数,我需要添加另一个test_*函数(我有很多)。

我正在寻找一种优雅的方式来保持我的prepare_food功能相同,并用另一个功能包装它,这样我仍然可以获得与test_prepare_food中相同的功能。

修改 目标是建立一个不依赖于prepare_food()实施的解决方案,以便prepare_food()中的更改不需要进行其他更改。此外,解决方案不应影响prepare_food未使用的方法。

换句话说,我希望能够进入" prepare_food并且能够在每行之前和之后执行代码。这类似于调试时所做的事情,但我找不到任何相似的东西。

有什么想法吗?

谢谢!

1 个答案:

答案 0 :(得分:2)

您可以使用measure方法修饰Microwave类的每个实例方法。这可以通过Microwave类上的类装饰器来完成。对于这个例子,我只是通过一种方法修改Microwave类。完成工作的方法是wrapwrap_method

import inspect

class measure(object):
    def __enter__(self):
        print "Enter measure."
    def __exit__(self, *args):
        print "Exit measure."

class Microwave(object):
    def f(self, x):
        print "f: %s" % x
    def g(self, x):
        print "g: %s" % x

def wrap_method(method):
    def wrapper(*args, **kwargs):
        with measure():
            method(*args, **kwargs)
    return wrapper

def wrap(cls):
    for name, method in inspect.getmembers(cls, predicate=inspect.ismethod):
        setattr(cls, name, wrap_method(method))

wrap(Microwave)
m = Microwave()
m.f(1)
m.g(2)

输出是:

Enter measure.
f: 1
Exit measure.
Enter measure.
g: 2
Exit measure.