def test_activate_contextmanager(self): @injector(self.map) def test(foo=Key('foo')): return foo self.map['foo'] = 'ROOT' test() | should.eql('ROOT') with self.map.activate('A'): self.map['foo'] = 'A' test() | should.eql('A') test() | should.eql('ROOT') with self.map.activate('B'): self.map['foo'] = 'B' test() | should.eq('B') # Force a context self.map.context('A') test() | should.eq('A') test() | should.eql('ROOT') with self.map.activate('A'): with self.map.activate('B'): test() | should.eq('B') test() | should.eq('A') test() | should.eql('ROOT')
def test_add_a_functionality_with_variants(self): fn = "FOO" _variants = ["foo", "bar", "bazz"] self.backend.add_functionality(Feature(fn, variants=_variants)) f = self.backend._get_functionality(fn) f.name | should.eql(fn) f.percentage | should.eql(100) all_of(["foo", "bar", "bazz"]) | should.be_in(f.variants)
def test_add_a_functionality_with_percentage(self): fn = "FOO" self.backend.add_functionality(Feature(fn, None, 50)) self.backend.get_functionalities() | should.have_len(1) f, users = self.backend._get_functionality(fn) f.name | should.eql(fn) f.percentage | should.eql(50) users | should.be_empty().and_array()
def test_retrieve_a_variant(self): fn = "FOO" _variants = ["foo", "bar", "bazz"] self.backend.add_functionality(Feature(fn, variants=_variants)) f = self.backend.get_functionality(fn) f.name | should.eql(fn) f.percentage | should.eql(100) self.backend.variant(fn, 'juan') | should.be_in(f.variants) self.backend.variant(fn, 'juan2') | should.be_in(f.variants)
def test_add_a_disabled_functionality_with_percentage(self): fn = "FOO" func = Feature(fn, None, 50) func.enabled = False self.backend.add_functionality(func) f = self.backend._get_functionality(fn) f.name | should.eql(fn) f.percentage | should.eql(50) f.enabled | should.be_falsy() self.backend._redis.smembers("rollout:users:FOO") | should.be_empty()
def test_add_a_disabled_functionality_with_percentage(self): fn = "FOO" func = Feature(fn, None, 50) func.enabled = False self.backend.add_functionality(func) self.backend.get_functionalities() | should.have_len(1) f, users = self.backend._get_functionality(fn) f.name | should.eql(fn) f.percentage | should.eql(50) f.enabled | should.be_falsy() users | should.be_empty().and_array()
def test_context_manager(self): self.map[Ham] = 10 self.map[Spam] = 20 @injector(self.map) def func(ham=Ham, spam=Spam): return ham + spam func() | should.eql(30) with self.map: self.map[Ham] = 1 func() | should.eql(21) func() | should.eql(30)
def test_context_manager(self): self.map[Ham] = 10 self.map[Spam] = 20 @injector(self.map) def func(ham=Ham, spam=Spam): return ham + spam func() | should.eql( 30 ) with self.map: self.map[Ham] = 1 func() | should.eql( 21 ) func() | should.eql( 30 )
def test_py3_kwonlydefaults(): inject = injector({KeyA: 'A', KeyB: 'B', KeyC: 'C'}) @inject def foo(a, b=KeyB, *, c=KeyC): return (b, c) foo(10) | should.eql(('B', 'C')) @inject def bar(a, *, b=KeyB): return b bar(10) | should.eql('B')
def test_patch_multiple(self): @self.inject def test(foo=InjectorPatchTests): return foo self.inject.patch({InjectorPatchTests: 1}) self.inject.patch({InjectorPatchTests: 2}) self.inject.patch({InjectorPatchTests: 3}) test() | should.eql(3) self.inject.unpatch() test() | should.eql(2) self.inject.unpatch() test() | should.eql(1) self.inject.unpatch() test() | should.eql(self)
def test_decorator_check_with_argument(self): @self.rollout.check(self.FN, 1) def foo(name): return name.id self.rollout.set_current_id('foo') self.rollout.register(self.FN, 'bar') foo(Foo('bar')) | should.eql('bar')
def test_decorator_check_with_current_id(self): @self.rollout.check(self.FN) def foo(name): return name self.rollout.set_current_id(Foo('bar')) self.rollout.register(self.FN, Foo('bar')) foo('bazz') | should.eql('bazz')
def test_get_item_id_calls_the_field_if_callable(self): f = Feature('foo', 'bar') class Foo(object): def bar(self): return 'bazz' f.get_item_id(Foo()) | should.eql('bazz')
def test_retrieve_a_variant_is_none_if_disabled(self): fn = "FOO" _variants = ["foo", "bar", "bazz"] self.backend.add_functionality(Feature(fn, percentage=0, variants=_variants)) f = self.backend._get_functionality(fn) f.name | should.eql(fn) self.backend.variant(fn, 'juan') | should.be_none() self.backend.variant(fn, 'juan2') | should.be_none()
def test_get_item_id_casts_to_string(self): f = Feature('foo') class Foo(object): def __str__(self): return 'bar' f.get_item_id(Foo()) | should.eql('bar')
def test_retrieve_a_variant_is_none_if_disabled(self): fn = "FOO" _variants = ["foo", "bar", "bazz"] self.backend.add_functionality( Feature(fn, percentage=0, variants=_variants)) f = self.backend._get_functionality(fn) f.name | should.eql(fn) self.backend.variant(fn, 'juan') | should.be_none() self.backend.variant(fn, 'juan2') | should.be_none()
def test_add_existing_an_user(self): fn = "FOO" self.backend.add_functionality(Feature(fn)) self.backend.get_functionalities() | should.have_len(1) f, users = self.backend._get_functionality(fn) users | should.be_empty().and_array() self.backend.add(fn, "bar") self.backend.add(fn, "bar") f, users = self.backend._get_functionality(fn) users | should.eql(['bar'])
def test_deprecated_property(self): @self.inject def test(foo=InjectorPatchTests): return foo self.inject.dependencies = {InjectorPatchTests: 'foo'} with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") test() | should.eql('foo') w | should.have_len(1) w[0].category | should.be(UserWarning)
def test_inject_metaclass_keeps_other_decorators(self): def upper(fn): def inner(*args, **kwargs): value = fn(*args, **kwargs) return value.upper() return inner class Foo(object): __metaclass__ = MetaInject(self.inject) @upper def echo(self, test=unittest.TestCase): return test Foo().echo(test="bar") | should.eql("BAR")
def test_py3_annotations(): class Foo: pass class Bar: pass class Baz: pass class Qux: pass inject = injector({Foo: Foo(), Bar: Bar(), Baz: Baz(), Qux: Qux()}) @inject def foo(a: Foo = Key, b: Any = Bar, c: Baz = Baz, d=Qux): return (a, b, c, d) foo() | should.eql(( should.be_a(Foo), should.be_a(Bar), should.be_a(Baz), should.be_a(Qux) ))
def test_add_a_functionality_with_percentage(self): fn = "FOO" self.backend.add_functionality(Feature(fn, None, 50)) f = self.backend._get_functionality(fn) f.name | should.eql(fn) f.percentage | should.eql(50)
def test_field_can_be_none(self): f = Feature('foo') f.get_item_id('bar') | should.eql('bar')
def test_overrides_a_functionality_with_same_name(self): self.rollout.add_func(self.FN, 'id2') fn = self.rollout.backend.get_functionality(self.FN) fn.field | should.eql('id2')
def test_inject_metaclass_override_from_calling_site(self): self.foo.echo(test="bar") | should.eql("bar")
def test_percentage_is_casted_to_integer_if_valid_number_as_string(self): f = Feature('foo', lambda x: True, '100') f.percentage | should.eql(100)
def test_name_is_valid_as_unicode(self): f = Feature(u'üéê', lambda x: True, '100') f.name | should.eql(u'üéê')
def test_name_is_valid_as_a_string(self): f = Feature('foo', lambda x: True, '100') f.name | should.eql('foo')
def test_coroutine_moves_to_first_yield_upon_initialized(self): start = 100 t = self.fn(start) self.handler.flush() self.stream.getvalue() | should.eql(str(start) + os.linesep)
def test_coroutine_keeps_function_name(self): self.fn.__name__ | should.eql("add")
def test_coroutine_keeps_function_doc(self): self.fn.__doc__ | should.eql("Sums two integers")
def test_coroutine_returns_a_generator_type(self): start = 100 t = self.fn(start) type(t) | should.eql(GeneratorType)
def test_add_a_functionality(self): fn = "FOO" self.backend.add_functionality(Feature(fn)) f = self.backend._get_functionality(fn) f.name | should.eql(fn) f.percentage | should.eql(100)
def test_decorator_enabled_decorator_when_feature_enabled(self): @self.rollout.enabled(self.FN) def foo(name): return name foo('bazz') | should.eql('bazz')