def test_exposeDocAttribute(self): """ Creating an exposer should require a docstring explaining what it's for. """ docstring = "This is my docstring." exposer = Exposer(docstring) self.assertEqual(exposer.__doc__, docstring)
def setUp(self): """ Create two exposers to expose methods in tests. """ self.exposer = Exposer("test exposer") self.otherExposer = Exposer("other exposer")
class ExposeTests: """ This mixin provides tests for expose, based on a parameterized base type for the class which methods are being exposed on. Subclass this before L{TestCase} and set L{superClass} to use this. @ivar superClass: the class to be subclassed by all classes which expose methods. """ superClass = None def setUp(self): """ Create two exposers to expose methods in tests. """ self.exposer = Exposer("test exposer") self.otherExposer = Exposer("other exposer") def test_exposeDocAttribute(self): """ Creating an exposer should require a docstring explaining what it's for. """ docstring = "This is my docstring." exposer = Exposer(docstring) self.assertEqual(exposer.__doc__, docstring) def test_simpleExpose(self): """ Creating an exposer, defining a class and exposing a method of a class with that exposer, then retrieving a method of that class should result in the method of that class. """ class Foo(self.superClass): def __init__(self, num): self.num = num @self.exposer.expose() def bar(self): return self.num + 1 f = Foo(3) method = self.exposer.get(f, 'bar') self.assertEqual(method(), 4) def test_notExposed(self): """ Creating an exposer and then attempting to retrieve a method not exposed with it should result in a L{MethodNotExposed} exception. """ class Foo(self.superClass): def bar(self): return 1 f = Foo() self.assertRaises(MethodNotExposed, self.exposer.get, f, 'bar') def test_differentMethodsDifferentExposers(self): """ Methods should only be able to be retrieved with the exposer that exposed them, not with any other exposer. """ class Foo(self.superClass): @self.exposer.expose() def bar(self): return 1 @self.otherExposer.expose() def baz(self): return 2 f = Foo() self.assertEqual(self.exposer.get(f, 'bar')(), 1) self.assertEqual(self.otherExposer.get(f, 'baz')(), 2) self.assertRaises(MethodNotExposed, self.otherExposer.get, f, 'bar') self.assertRaises(MethodNotExposed, self.exposer.get, f, 'baz') def test_sameMethodExposedByDifferentExposers(self): """ If the same method is exposed by two different exposers, it should be accessible by both of them. """ class Foo(self.superClass): @self.exposer.expose() @self.otherExposer.expose() def bar(self): return 4 f = Foo() self.assertEqual(self.exposer.get(f, 'bar')(), 4) self.assertEqual(self.otherExposer.get(f, 'bar')(), 4) def test_exposeWithDifferentKey(self): """ The 'key' argument to {Exposer.expose} should change the argument to 'get'. """ class Foo(self.superClass): @self.exposer.expose(key='hello') def bar(self): return 7 f = Foo() self.assertEqual(self.exposer.get(f, 'hello')(), 7) def test_exposeOnDifferentClass(self): """ An exposer should only be able to retrieve a method from instances of types which it has explicitly exposed methods on. Instances of different types with the same method name should raise L{MethodNotExposed}. """ class Foo(self.superClass): @self.exposer.expose() def bar(self): return 7 class Baz(self.superClass): def bar(self): return 8 f = Foo() b = Baz() self.assertEqual(self.exposer.get(f, 'bar')(), 7) self.assertRaises(MethodNotExposed, self.otherExposer.get, b, 'bar') def test_exposeUnnamedNoKey(self): """ L{Exposer.expose} raises L{NameRequired} when called without a value for the C{key} parameter if it is used to decorate a non-function object. """ def f(): class Foo(self.superClass): @self.exposer.expose() @classmethod def foo(self): pass self.assertRaises(NameRequired, f) def test_exposeNonMethod(self): """ L{Exposer.expose} should work on methods which have been decorated by another decorator and will therefore not result in function objects when retrieved with __get__. """ class Getter(record('function')): def __get__(self, oself, type): return self.function class Foo(self.superClass): @self.exposer.expose(key='bar') @Getter def bar(): return 7 f = Foo() # Sanity check self.assertEqual(f.bar(), 7) self.assertEqual(self.exposer.get(f, 'bar')(), 7) def test_descriptorGetsType(self): """ L{Exposer.get} should not interfere with the appropriate type object being passed to the wrapped descriptor's C{__get__}. """ types = [] class Getter(record('function')): def __get__(self, oself, type): types.append(type) return self.function class Foo(self.superClass): @self.exposer.expose(key='bar') @Getter def bar(): return 7 f = Foo() self.exposer.get(f, 'bar') self.assertEqual(types, [Foo]) def test_descriptorGetsSubtype(self): """ When a descriptor is exposed through a superclass, getting it from a subclass results in the subclass being passed to the C{__get__} method. """ types = [] class Getter(record('function')): def __get__(self, oself, type): types.append(type) return self.function class Foo(self.superClass): @self.exposer.expose(key='bar') @Getter def bar(): return 7 class Baz(Foo): pass b = Baz() self.exposer.get(b, 'bar') self.assertEqual(types, [Baz]) def test_implicitSubclassExpose(self): """ L{Exposer.expose} should expose the given object on all subclasses. """ class Foo(self.superClass): @self.exposer.expose() def bar(self): return 7 class Baz(Foo): pass b = Baz() self.assertEqual(self.exposer.get(b, 'bar')(), 7) def test_overrideDontExpose(self): """ L{Exposer.expose} should not expose overridden methods on subclasses. """ class Foo(self.superClass): @self.exposer.expose() def bar(self): return 7 class Baz(Foo): def bar(self): return 8 b = Baz() self.assertRaises(MethodNotExposed, self.otherExposer.get, b, 'bar') def test_sameKeyOnDifferentTypes(self): """ L{Exposer.expose} should work with the same key on different types. """ class Foo(self.superClass): @self.exposer.expose() def bar(self): return 17 class Qux(self.superClass): @self.exposer.expose() def bar(self): return 71 q = Qux() f = Foo() self.assertEqual(self.exposer.get(q, 'bar')(), 71) self.assertEqual(self.exposer.get(f, 'bar')(), 17) def test_overrideReExpose(self): """ L{Exposer.expose} should expose a method on a subclass if that method is overridden. """ class Foo(self.superClass): @self.exposer.expose() def bar(self): return 7 class Baz(Foo): @self.exposer.expose() def bar(self): return 8 f = Foo() b = Baz() self.assertEqual(self.exposer.get(f, 'bar')(), 7) self.assertEqual(self.exposer.get(b, 'bar')(), 8) def test_deleteExposedAttribute(self): """ When an exposed attribute is deleted from a class, it should no longer be exposed; calling L{Exposer.get} should result in L{MethodNotExposed}. """ class Foo(self.superClass): @self.exposer.expose() def bar(self): return 7 f = Foo() del Foo.bar self.assertRaises(MethodNotExposed, self.otherExposer.get, f, 'bar')