0

私は、nose のジェネレーターから生成されたテストを取得して、テスト対象の特定の反復用にカスタマイズされた記述を作成する方法に取り組んできました。selfジェネレーター ターゲット メソッドがジェネレーター クラスからアクセスしようとしない限り、機能するものがあります。すべてのジェネレーター ターゲット インスタンスに共通のテスト クラス インスタンスがあることがわかりますが、ノーズはジェネレーターからのテスト実行ごとにテスト クラスの 1 回限りのインスタンスを生成しています。これにより、setUpノーズが作成する各テストインスタンスで実行されますが、ジェネレーターターゲットがバインドされているインスタンスでは実行されません (もちろん、本当の問題は、ノーズで作成されたインスタンスをジェネレーターターゲットにバインドする方法がわからないことです)。これをすべて理解するために私が使用しているコードは次のとおりです(はい、デコレーターはおそらく呼び出し可能なクラスとして優れていることを知っていますが、鼻、少なくとも私が持っているバージョン1.2.1は、テストがどちらかの関数であることを明示的にチェックしますまたはメソッドなので、呼び出し可能なクラスはまったく実行されません):

import inspect

def labelable_yielded_case(case):

    argspec = inspect.getargspec(case)
    if argspec.defaults is not None:
        defaults_list = [''] * (len(argspec.args) - len(argspec.defaults)) + argspec.defaults
    else:
        defaults_list = [''] * len(argspec.args)
    argument_defaults_list = zip(argspec.args, defaults_list)
    case_wrappers = []

    def add_description(wrapper_id, argument_dict):

        case_wrappers[wrapper_id].description = case.__doc__.format(**argument_dict)

    def case_factory(*factory_args, **factory_kwargs):

        def case_wrapper_wrapper():

            wrapper_id = len(case_wrappers)

            def case_wrapper(*args, **kwargs):

                args = factory_args + args
                argument_list = []
                for argument in argument_defaults_list:
                    argument_list.append(list(argument))
                for index, value in enumerate(args):
                    argument_list[index][1] = value
                argument_dict = dict(argument_list)
                argument_dict.update(factory_kwargs)
                argument_dict.update(kwargs)
                add_description(wrapper_id, argument_dict)
                return case(*args, **kwargs)

            case_wrappers.append(case_wrapper)
            case_wrapper.__name__ = case.__name__
            return case_wrapper

        return case_wrapper_wrapper()

    return case_factory


class TestTest(object):

    def __init__(self):

        self.data = None

    def setUp(self):

        print 'setup', self
        self.data = (1,2,3)

    def test_all(self):

        for index, value in enumerate((1,2,3)):
            yield self.validate_equality(), index, value

    def test_all_again(self):

        for index, value in enumerate((1,2,3)):
            yield self.validate_equality_again, index, value

    @labelable_yielded_case
    def validate_equality(self, index, value):
        '''element {index} equals {value}'''

        print 'test', self
        assert self.data[index] == value, 'expected %d got %d' % (value, self.data[index])

    def validate_equality_again(self, index, value):

        print 'test', self
        assert self.data[index] == value, 'expected %d got %d' % (value, self.data[index])

    validate_equality_again.description = 'again'

ノーズを実行すると、againテストは正常に機能しますが、デコレートされたジェネレーター ターゲットを使用する一連のテストはすべて失敗しますself.data is None(クロージャーに格納されている のインスタンスがノーズによって実行されるインスタンスではないため、 が実行されないため)。デコレータを の基本クラスのインスタンス メンバーにしようとしましたが、 unbound に渡される引数が少なすぎる (no ) というエラーがノーズからスローされました。これを機能させる方法はありますか (鼻をハックする方法はありません)、または、yield ターゲットをインスタンス メンバーにすることができないか、または生成された各テストのテストごとのラベル付けを持たないかのどちらかを選択するのに行き詰まっていますか?setUpTestTestTestTestselflabelable_yielded_case

4

1 に答える 1

0

それを修正しました(少なくともここのケースでは、すべてのケースでそれを取得したと思いますが)。私はいじってcase_wrapper_wrappercase_wrapperファクトリが正しいクラスに添付されたラップされたケースを返すようにする必要がありましたが、特定のインスタンスには決してバインドされていませんでした。ラッパーラッパーで引数 dict を作成していたが、それをケースに渡していなかったため、別のコードの問題もありました。作業コード:

import inspect

def labelable_yielded_case(case):

    argspec = inspect.getargspec(case)
    if argspec.defaults is not None:
        defaults_list = [''] * (len(argspec.args) - len(argspec.defaults)) + argspec.defaults
    else:
        defaults_list = [''] * len(argspec.args)
    argument_defaults_list = zip(argspec.args, defaults_list)
    case_wrappers = []

    def add_description(wrapper_id, argument_dict):

        case_wrappers[wrapper_id].description = case.__doc__.format(**argument_dict)

    def case_factory(*factory_args, **factory_kwargs):

        def case_wrapper_wrapper():

            wrapper_id = len(case_wrappers)

            def case_wrapper(*args, **kwargs):

                argument_list = []
                for argument in argument_defaults_list:
                    argument_list.append(list(argument))
                for index, value in enumerate(args):
                    argument_list[index][1] = value
                argument_dict = dict(argument_list)
                argument_dict.update(kwargs)
                add_description(wrapper_id, argument_dict)
                return case(**argument_dict)

            case_wrappers.append(case_wrapper)
            case_name = case.__name__ + str(wrapper_id)
            case_wrapper.__name__ = case_name
            if factory_args:
                setattr(factory_args[0].__class__, case_name, case_wrapper)
                return getattr(factory_args[0].__class__, case_name)
            else:
                return case_wrapper

        return case_wrapper_wrapper()

    return case_factory


class TestTest(object):

    def __init__(self):

        self.data = None

    def setUp(self):

        self.data = (1,2,3)

    def test_all(self):

        for index, value in enumerate((1,2,3)):
            yield self.validate_equality(), index, value

    @labelable_yielded_case
    def validate_equality(self, index, value):
        '''element {index} equals {value}'''

        assert self.data[index] == value, 'expected %d got %d' % (value, self.data[index])
于 2012-09-14T16:16:39.563 に答える