def __init_fixture_methods(self): """Initialize and populate the lists of fixture methods for this TestCase. Fixture methods are identified by the fixture_decorator_factory when the methods are created. This means in order to figure out all the fixtures this particular TestCase will need, we have to test all of its attributes for 'fixture-ness'. See __fixture_decorator_factory for more info. """ # init our self.(class_setup|setup|teardown|class_teardown)_fixtures lists for fixture_type in FIXTURE_TYPES: setattr(self, "%s_fixtures" % fixture_type, []) # the list of classes in our heirarchy, starting with the highest class # (object), and ending with our class reverse_mro_list = [x for x in reversed(type(self).mro())] # discover which fixures are on this class, including mixed-in ones self._fixture_methods = defaultdict(list) # we want to know everything on this class (including stuff inherited # from bases), but we don't want to trigger any lazily loaded # attributes, so dir() isn't an option; this traverses __bases__/__dict__ # correctly for us. for classified_attr in inspect.classify_class_attrs(type(self)): # have to index here for Python 2.5 compatibility attr_name = classified_attr[0] unbound_method = classified_attr[3] defining_class = classified_attr[2] # skip everything that's not a function/method if not inspect.isroutine(unbound_method): continue # if this is an old setUp/tearDown/etc, tag it as a fixture if attr_name in DEPRECATED_FIXTURE_TYPE_MAP: fixture_type = DEPRECATED_FIXTURE_TYPE_MAP[attr_name] fixture_decorator = globals()[fixture_type] unbound_method = fixture_decorator(unbound_method) # collect all of our fixtures in appropriate buckets if inspection.is_fixture_method(unbound_method): # where in our MRO this fixture was defined defining_class_depth = reverse_mro_list.index(defining_class) inspection.callable_setattr( unbound_method, '_defining_class_depth', defining_class_depth, ) # we grabbed this from the class and need to bind it to us instance_method = instancemethod(unbound_method, self, self.__class__) self._fixture_methods[instance_method._fixture_type].append(instance_method) # arrange our fixture buckets appropriately for fixture_type, fixture_methods in self._fixture_methods.iteritems(): # sort our fixtures in order of oldest (smaller id) to newest, but # also grouped by class to correctly place deprecated fixtures fixture_methods.sort(key=lambda x: (x._defining_class_depth, x._fixture_id)) # for setup methods, we want methods defined further back in the # class hierarchy to execute first. for teardown methods though, # we want the opposite while still maintaining the class-level # definition order, so we reverse only on class depth. if fixture_type in REVERSED_FIXTURE_TYPES: fixture_methods.sort(key=lambda x: x._defining_class_depth, reverse=True) fixture_list_name = "%s_fixtures" % fixture_type setattr(self, fixture_list_name, fixture_methods)
def test_set_method_attr(self): inspection.callable_setattr(DummyTestCase.fixture, 'foo', True) assert DummyTestCase.fixture.foo
def test_set_function_attr(self): function = lambda: None inspection.callable_setattr(function, 'foo', True) assert function.foo
def discover_from(cls, test_case): """Initialize and populate the lists of fixture methods for this TestCase. Fixture methods are identified by the fixture_decorator_factory when the methods are created. This means in order to figure out all the fixtures this particular TestCase will need, we have to test all of its attributes for 'fixture-ness'. See __fixture_decorator_factory for more info. """ all_fixtures = {} for fixture_type in FIXTURE_TYPES: all_fixtures[fixture_type] = [] # the list of classes in our heirarchy, starting with the highest class # (object), and ending with our class reverse_mro_list = [x for x in reversed(type(test_case).mro())] # discover which fixures are on this class, including mixed-in ones # we want to know everything on this class (including stuff inherited # from bases), but we don't want to trigger any lazily loaded # attributes, so dir() isn't an option; this traverses __bases__/__dict__ # correctly for us. for classified_attr in inspect.classify_class_attrs(type(test_case)): # have to index here for Python 2.5 compatibility attr_name = classified_attr[0] unbound_method = classified_attr[3] defining_class = classified_attr[2] # skip everything that's not a function/method if not inspect.isroutine(unbound_method): continue # if this is an old setUp/tearDown/etc, tag it as a fixture if attr_name in DEPRECATED_FIXTURE_TYPE_MAP: fixture_type = DEPRECATED_FIXTURE_TYPE_MAP[attr_name] fixture_decorator = globals()[fixture_type] unbound_method = fixture_decorator(unbound_method) # collect all of our fixtures in appropriate buckets if inspection.is_fixture_method(unbound_method): # where in our MRO this fixture was defined defining_class_depth = reverse_mro_list.index(defining_class) inspection.callable_setattr( unbound_method, '_defining_class_depth', defining_class_depth, ) # we grabbed this from the class and need to bind it to the # test case instance_method = instancemethod(unbound_method, test_case, test_case.__class__) all_fixtures[instance_method._fixture_type].append(instance_method) class_level = ['class_setup', 'class_teardown', 'class_setup_teardown'] inst_level = ['setup', 'teardown', 'setup_teardown'] return cls( class_fixtures=sum([all_fixtures[typ] for typ in class_level], []), instance_fixtures=sum([all_fixtures[typ] for typ in inst_level], []), )
def __init_fixture_methods(self): """Initialize and populate the lists of fixture methods for this TestCase. Fixture methods are identified by the fixture_decorator_factory when the methods are created. This means in order to figure out all the fixtures this particular TestCase will need, we have to test all of its attributes for 'fixture-ness'. See __fixture_decorator_factory for more info. """ # init our self.(class_setup|setup|teardown|class_teardown)_fixtures lists for fixture_type in FIXTURE_TYPES: setattr(self, "%s_fixtures" % fixture_type, []) # the list of classes in our heirarchy, starting with the highest class # (object), and ending with our class reverse_mro_list = [x for x in reversed(type(self).mro())] # discover which fixures are on this class, including mixed-in ones self._fixture_methods = defaultdict(list) # we want to know everything on this class (including stuff inherited # from bases), but we don't want to trigger any lazily loaded # attributes, so dir() isn't an option; this traverses __bases__/__dict__ # correctly for us. for classified_attr in inspect.classify_class_attrs(type(self)): # have to index here for Python 2.5 compatibility attr_name = classified_attr[0] unbound_method = classified_attr[3] defining_class = classified_attr[2] # skip everything that's not a function/method if not inspect.isroutine(unbound_method): continue # if this is an old setUp/tearDown/etc, tag it as a fixture if attr_name in DEPRECATED_FIXTURE_TYPE_MAP: fixture_type = DEPRECATED_FIXTURE_TYPE_MAP[attr_name] fixture_decorator = globals()[fixture_type] unbound_method = fixture_decorator(unbound_method) # collect all of our fixtures in appropriate buckets if inspection.is_fixture_method(unbound_method): # where in our MRO this fixture was defined defining_class_depth = reverse_mro_list.index(defining_class) inspection.callable_setattr( unbound_method, '_defining_class_depth', defining_class_depth, ) # we grabbed this from the class and need to bind it to us instance_method = instancemethod(unbound_method, self, self.__class__) self._fixture_methods[instance_method._fixture_type].append( instance_method) # arrange our fixture buckets appropriately for fixture_type, fixture_methods in self._fixture_methods.iteritems(): # sort our fixtures in order of oldest (smaller id) to newest, but # also grouped by class to correctly place deprecated fixtures fixture_methods.sort( key=lambda x: (x._defining_class_depth, x._fixture_id)) # for setup methods, we want methods defined further back in the # class hierarchy to execute first. for teardown methods though, # we want the opposite while still maintaining the class-level # definition order, so we reverse only on class depth. if fixture_type in REVERSED_FIXTURE_TYPES: fixture_methods.sort(key=lambda x: x._defining_class_depth, reverse=True) fixture_list_name = "%s_fixtures" % fixture_type setattr(self, fixture_list_name, fixture_methods)
def test_set_function_attr(self): def function(): pass inspection.callable_setattr(function, 'foo', True) assert function.foo