Pour tout problème contactez-nous par mail : support@froggit.fr | La FAQ :grey_question: | Rejoignez-nous sur le Chat :speech_balloon:

Skip to content
Snippets Groups Projects
Commit 81e97d61 authored by Dorian Turba's avatar Dorian Turba
Browse files

tests: description to tests, more fixtures, renaming

parent ceed46bf
No related branches found
No related tags found
No related merge requests found
...@@ -4,25 +4,42 @@ import collections ...@@ -4,25 +4,42 @@ import collections
import functools import functools
import typing import typing
import weakref
class Hook: class Hook:
instances: weakref.WeakSet = weakref.WeakSet()
function: typing.Callable function: typing.Callable
registered_level: int = 0 registered_level: int = 0
l10n_flags: int = 0 l10n_flags: int = 0
name: str
def __new__(cls, *_: typing.Any, **__: typing.Any) -> Hook:
new_instance = super().__new__(cls)
cls.instances.add(new_instance)
return new_instance
def __init__(self, function: typing.Callable): def __init__(self, function: typing.Callable):
functools.wraps(function)(self) functools.wraps(function)(self)
self.function = function self.function = function
def __get__(self, instance: typing.Callable, owner: typing.Type) -> typing.Callable: def __get__(self, instance: typing.Callable, owner: typing.Type) -> functools.partial:
partial = functools.partial(self.function, instance) partial = functools.partial(self.function, instance)
partial.add = self.add # type: ignore partial.add = self.add # type: ignore
return partial return partial
def __call__(self, *args: typing.Any, **kwargs: typing.Any) -> None: def __call__(self, *args: typing.Any, **kwargs: typing.Any) -> typing.Any:
"""TODO: dispatch on function to add hooks""" """TODO: dispatch on function to add hooks"""
return self.function(*args, **kwargs) return self.function(*args, **kwargs)
@property
def __name__(self) -> str:
return self.name
@__name__.setter
def __name__(self, name: str) -> None:
self.name = name
def match_level(self, flags: int) -> int: def match_level(self, flags: int) -> int:
""" """
For match, flags must be For match, flags must be
...@@ -52,5 +69,5 @@ class Hook: ...@@ -52,5 +69,5 @@ class Hook:
dispatch_add: collections.defaultdict = collections.defaultdict(lambda: Hook.add_flags) dispatch_add: collections.defaultdict = collections.defaultdict(lambda: Hook.add_flags)
dispatch_add[type(add_function)] = add_function dispatch_add[type(add_function)] = add_function
def add(self, function_or_flags: typing.Callable) -> typing.Callable: def add(self, function_or_flags: typing.Union[typing.Callable, int]) -> typing.Callable:
return self.dispatch_add[type(function_or_flags)](self, function_or_flags) return self.dispatch_add[type(function_or_flags)](self, function_or_flags)
...@@ -7,10 +7,15 @@ import fasthook ...@@ -7,10 +7,15 @@ import fasthook
class Flags(enum.IntFlag): class Flags(enum.IntFlag):
country_one = enum.auto() country_A = enum.auto()
country_two = enum.auto() country_B = enum.auto()
brand_one = enum.auto() brand_A = enum.auto()
brand_two = enum.auto() brand_B = enum.auto()
@pytest.fixture
def import_fasthook():
return fasthook
@pytest.fixture @pytest.fixture
...@@ -20,25 +25,45 @@ def setting_reset(): ...@@ -20,25 +25,45 @@ def setting_reset():
@pytest.fixture @pytest.fixture
def hook_setting_country_one(setting_reset): def config_country(setting_reset):
fasthook.Hook.l10n_flags = Flags.country_one fasthook.Hook.l10n_flags = Flags.country_A
@pytest.fixture @pytest.fixture
def hook_setting_country_one_brand_one(setting_reset): def config_country_brand(setting_reset):
fasthook.Hook.l10n_flags = Flags.country_one | Flags.brand_one """configure flags to a simple combination of country and brand, i.e. a market"""
fasthook.Hook.l10n_flags = Flags.country_A | Flags.brand_A
@pytest.fixture @pytest.fixture
def flags() -> typing.Type[Flags]: def flags() -> typing.Type[Flags]:
"""return configuration integer enum flags used by hook to dispatch hook implementations"""
return Flags return Flags
@pytest.fixture @pytest.fixture
def return_default() -> fasthook.Hook: def default_hook(import_fasthook) -> fasthook.Hook:
@fasthook.Hook @import_fasthook.Hook
def return_default_(): def return_default_():
"""default hook""" """default hook"""
return "default" return default_hook.__name__
return return_default_ return return_default_
@pytest.fixture
def inject_country(default_hook, flags) -> typing.Callable:
@default_hook.add(flags.country_A)
def country():
return inject_country.__name__
return country
@pytest.fixture
def inject_country_brand(default_hook, flags) -> typing.Callable:
@default_hook.add(flags.country_A | flags.brand_A)
def country_brand():
return inject_country_brand.__name__
return country_brand
...@@ -4,69 +4,122 @@ import pytest ...@@ -4,69 +4,122 @@ import pytest
@pytest.mark.regression @pytest.mark.regression
def test_hook(): def test_hook(import_fasthook):
import fasthook """
given
- imported fasthook package
- and a function that return the name of the default hook
@fasthook.Hook when apply the hook decorator to the function
then assert that the hook return its name
"""
@import_fasthook.Hook
def return_default(): def return_default():
"""default hook""" return return_default.__name__
return "default"
assert return_default() == "default" assert return_default() == "return_default"
@pytest.mark.regression @pytest.mark.regression
def test_hook_better_match(return_default, hook_setting_country_one_brand_one, flags): def test_hook_implementation_injection(default_hook, config_country_brand, flags):
@return_default.add(flags.country_one) """
def return_first_registered(): given
- a default hook that returns its name
- a configuration for a specific country and a specific brand
- the flags enum used to specify a configuration
- and a function that return its name
when add the function to the hook matching the country
then assert that the hook return the name of the added function
"""
@default_hook.add(flags.country_A)
def inject_country():
"""First registered hook, replace default one""" """First registered hook, replace default one"""
return "first registered" return inject_country.__name__
assert default_hook() == "inject_country"
assert return_default() == "first registered"
@return_default.add(flags.country_one | flags.brand_one) @pytest.mark.regression
def return_second_registered(): def test_hook_better_match(default_hook, config_country_brand, flags, inject_country):
"""
given
- a default hook that returns its name
- a configuration for a specific country and a specific brand
- the flags enum used to specify a configuration
- an injected function that return its name matching country
- and a function that return its name
when add the function to the hook matching the country and the brand of the configuration
then assert that the hook return the name of the function that match the country and the brand
"""
@default_hook.add(flags.country_A | flags.brand_A)
def inject_country_brand():
"""second registered hook, replace first one""" """second registered hook, replace first one"""
return "second registered" return inject_country_brand.__name__
assert return_default() == "second registered" assert default_hook() == "inject_country_brand"
@pytest.mark.regression @pytest.mark.regression
def test_hook_lesser_match(return_default, hook_setting_country_one_brand_one, flags): def test_hook_fewer_match(default_hook, config_country_brand, flags, inject_country_brand):
@return_default.add(flags.country_one | flags.brand_one) """
def return_first_registered(): given
"""First registered hook, replace default one""" - a default hook that returns its name
return "first registered" - a configuration for a specific country and a specific brand
- the flags enum used to specify a configuration
- an injected function that return its name matching country and brand
- and a function that return its name
when add the function to the hook matching just country
assert return_default() == "first registered" then assert that the hook return the name of the function that match the country and the brand
"""
@return_default.add(flags.country_one) @default_hook.add(flags.country_A)
def return_second_registered(): def inject_country():
"""lesser match than first hook, not registered""" """fewer match than first hook, not registered"""
return "second registered" return inject_country.__name__
assert return_default() == "first registered" assert default_hook() == "inject_country_brand"
@pytest.mark.regression @pytest.mark.regression
def test_hook_too_specific_use_default(return_default, hook_setting_country_one, flags): def test_hook_too_specific_use_default(default_hook, config_country, flags):
@return_default.add(flags.country_one | flags.brand_one) """
given
- a default hook that returns its name
- a configuration for a specific country
- the flags enum used to specify a configuration
- and a function that return its name
when add the function to the hook matching country but with brand that is not in config
then assert that the hook return its name
"""
@default_hook.add(flags.country_A | flags.brand_A)
def return_registered(): def return_registered():
"""hook not registered because config match only one registration flag""" """hook not registered because config match only one registration flag"""
return "registered" return return_registered.__name__
assert return_default() == "default" assert default_hook() == "default_hook"
@pytest.mark.regression @pytest.mark.regression
def test_hook_no_match_use_default(return_default, hook_setting_country_one, flags): def test_hook_no_match_use_default(default_hook, config_country, flags):
@return_default.add(flags.country_two) @default_hook.add(flags.country_B)
def return_registered(): def return_registered():
"""Not registered hook""" """Not registered hook"""
return "registered" return "registered"
assert return_default() == "default" assert default_hook() == "default_hook"
class Flags(enum.IntFlag): class Flags(enum.IntFlag):
...@@ -83,20 +136,18 @@ class Flags(enum.IntFlag): ...@@ -83,20 +136,18 @@ class Flags(enum.IntFlag):
(Flags.country_one, "registered"), (Flags.country_one, "registered"),
(Flags.brand_one, "registered"), (Flags.brand_one, "registered"),
(Flags.country_one | Flags.brand_one, "registered"), (Flags.country_one | Flags.brand_one, "registered"),
(Flags.country_two | Flags.brand_two, "default"), (Flags.country_two | Flags.brand_two, "default_hook"),
], ],
) )
def test_hook_multiple_add(return_default, flags_int, expected): def test_hook_multiple_add(import_fasthook, default_hook, flags_int, expected):
import fasthook import_fasthook.Hook.l10n_flags = flags_int
fasthook.Hook.l10n_flags = flags_int @default_hook.add(Flags.country_one)
@default_hook.add(Flags.brand_one)
@return_default.add(Flags.country_one)
@return_default.add(Flags.brand_one)
def return_registered(): def return_registered():
return "registered" return "registered"
assert return_default() == expected assert default_hook() == expected
def test_replace_default(): def test_replace_default():
...@@ -117,14 +168,14 @@ def test_replace_default(): ...@@ -117,14 +168,14 @@ def test_replace_default():
@pytest.mark.regression @pytest.mark.regression
def test_hook_setup_teardown(hook_setting_country_one, flags): def test_hook_setup_teardown(config_country, flags):
import fasthook import fasthook
@fasthook.Hook @fasthook.Hook
def setup(x): def setup(x):
return x return x
@setup.add(flags.country_one) @setup.add(flags.country_A)
def setup_1(x): def setup_1(x):
return x + 1 return x + 1
...@@ -132,7 +183,7 @@ def test_hook_setup_teardown(hook_setting_country_one, flags): ...@@ -132,7 +183,7 @@ def test_hook_setup_teardown(hook_setting_country_one, flags):
def teardown(resutl, y): def teardown(resutl, y):
return resutl return resutl
@teardown.add(flags.country_one) @teardown.add(flags.country_A)
def teardown_1(resutl, y): def teardown_1(resutl, y):
return resutl + y return resutl + y
...@@ -142,3 +193,35 @@ def test_hook_setup_teardown(hook_setting_country_one, flags): ...@@ -142,3 +193,35 @@ def test_hook_setup_teardown(hook_setting_country_one, flags):
return teardown(result, x) return teardown(result, x)
assert component(5) == 13 # (5+1 + 1) + 6 assert component(5) == 13 # (5+1 + 1) + 6
@pytest.mark.regression
def test_hook_instances_set():
import fasthook
@fasthook.Hook
def return_default_1():
"""default hook"""
return "default_1"
assert len(fasthook.Hook.instances) == 1
assert len(return_default_1.instances) == 1
@pytest.mark.regression
def test_hook_instances_garbage_collector():
import fasthook
@fasthook.Hook
def return_default_1():
"""default hook"""
return "default_1"
@fasthook.Hook
def return_default_2():
"""default hook"""
return "default_2"
assert len(fasthook.Hook.instances) == 2
del return_default_1
assert len(fasthook.Hook.instances) == 1
...@@ -17,7 +17,7 @@ def test_hook_method(): ...@@ -17,7 +17,7 @@ def test_hook_method():
@pytest.mark.regression @pytest.mark.regression
def test_hook_another_method_register(hook_setting_country_one, flags): def test_hook_another_method_register(config_country, flags):
import fasthook import fasthook
class Foobar: class Foobar:
...@@ -28,7 +28,7 @@ def test_hook_another_method_register(hook_setting_country_one, flags): ...@@ -28,7 +28,7 @@ def test_hook_another_method_register(hook_setting_country_one, flags):
self.spam += 1 self.spam += 1
return self return self
@change_value.add(flags.country_one) @change_value.add(flags.country_A)
def min_1_method_registered(self): def min_1_method_registered(self):
self.spam -= 1 self.spam -= 1
return self return self
...@@ -37,7 +37,7 @@ def test_hook_another_method_register(hook_setting_country_one, flags): ...@@ -37,7 +37,7 @@ def test_hook_another_method_register(hook_setting_country_one, flags):
@pytest.mark.regression @pytest.mark.regression
def test_hook_method_register_fct(hook_setting_country_one, flags): def test_hook_method_register_fct(config_country, flags):
import fasthook import fasthook
class Foobar: class Foobar:
...@@ -48,7 +48,7 @@ def test_hook_method_register_fct(hook_setting_country_one, flags): ...@@ -48,7 +48,7 @@ def test_hook_method_register_fct(hook_setting_country_one, flags):
self.spam += 1 self.spam += 1
return self return self
@Foobar.change_value.add(flags.country_one) @Foobar.change_value.add(flags.country_A)
def fct_registered(self): def fct_registered(self):
self.spam -= 1 self.spam -= 1
return self return self
...@@ -57,7 +57,7 @@ def test_hook_method_register_fct(hook_setting_country_one, flags): ...@@ -57,7 +57,7 @@ def test_hook_method_register_fct(hook_setting_country_one, flags):
@pytest.mark.regression @pytest.mark.regression
def test_method_too_specific_use_default(hook_setting_country_one, flags): def test_method_too_specific_use_default(config_country, flags):
import fasthook import fasthook
class Foobar: class Foobar:
...@@ -68,7 +68,7 @@ def test_method_too_specific_use_default(hook_setting_country_one, flags): ...@@ -68,7 +68,7 @@ def test_method_too_specific_use_default(hook_setting_country_one, flags):
self.spam += 1 self.spam += 1
return self return self
@change_value.add(flags.country_one | flags.brand_one) @change_value.add(flags.country_A | flags.brand_A)
def too_specific_not_registered(self): def too_specific_not_registered(self):
self.spam -= 1 self.spam -= 1
return self return self
...@@ -77,7 +77,7 @@ def test_method_too_specific_use_default(hook_setting_country_one, flags): ...@@ -77,7 +77,7 @@ def test_method_too_specific_use_default(hook_setting_country_one, flags):
@pytest.mark.regression @pytest.mark.regression
def test_method_lesser_match(hook_setting_country_one_brand_one, flags): def test_method_lesser_match(config_country_brand, flags):
import fasthook import fasthook
class Foobar: class Foobar:
...@@ -88,12 +88,12 @@ def test_method_lesser_match(hook_setting_country_one_brand_one, flags): ...@@ -88,12 +88,12 @@ def test_method_lesser_match(hook_setting_country_one_brand_one, flags):
self.spam += 1 self.spam += 1
return self return self
@change_value.add(flags.country_one | flags.brand_one) @change_value.add(flags.country_A | flags.brand_A)
def better_match_registered(self): def better_match_registered(self):
self.spam -= 1 self.spam -= 1
return self return self
@change_value.add(flags.country_one) @change_value.add(flags.country_A)
def lesser_match_not_registered(self): def lesser_match_not_registered(self):
self.spam += 10 self.spam += 10
return self return self
......
...@@ -8,12 +8,12 @@ def test_hook_default_testing(flags): ...@@ -8,12 +8,12 @@ def test_hook_default_testing(flags):
assert return_default.function() == "default" assert return_default.function() == "default"
def test_hook_variance_testing(return_default, flags): def test_hook_variance_testing(default_hook, flags):
@return_default.add(flags.country_one) @default_hook.add(flags.country_A)
def return_first_registered(): def return_first_registered():
return "first_registered" return "first_registered"
@return_default.add(flags.brand_one) @default_hook.add(flags.brand_A)
def return_second_registered(): def return_second_registered():
return "second_registered" return "second_registered"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment