Browse Source

Writing some tests for LodelHook

Yann Weber 9 years ago
parent
commit
be675bc723
4 changed files with 128 additions and 3 deletions
  1. 8
    2
      Lodel/hooks.py
  2. 0
    0
      Lodel/test/__init__.py
  3. 112
    0
      Lodel/test/tests_hooks.py
  4. 8
    1
      leapi/letype.py

+ 8
- 2
Lodel/hooks.py View File

43
     # @param priority int : the hook priority
43
     # @param priority int : the hook priority
44
     def __init__(self, hook_name, priority = None):
44
     def __init__(self, hook_name, priority = None):
45
         self._hook_name = hook_name
45
         self._hook_name = hook_name
46
-        self._priority = 0xFFF if priority is None else priority
46
+        self._priority = 0xFFFF if priority is None else priority
47
     
47
     
48
     ## @brief called just after __init__
48
     ## @brief called just after __init__
49
     # @param hook function : the decorated function
49
     # @param hook function : the decorated function
78
         else:
78
         else:
79
             res = copy.copy(cls._hooks)
79
             res = copy.copy(cls._hooks)
80
         return { name: [(hook._hook, hook._priority) for hook in hooks] for name, hooks in res.items() }
80
         return { name: [(hook._hook, hook._priority) for hook in hooks] for name, hooks in res.items() }
81
-
81
+    
82
+    ## @brief Unregister all hooks
83
+    # @warning REALLY NOT a good idea !
84
+    # @note implemented for testing purpose
85
+    @classmethod
86
+    def __reset_hooks__(cls):
87
+        cls._hooks = dict()

+ 0
- 0
Lodel/test/__init__.py View File


+ 112
- 0
Lodel/test/tests_hooks.py View File

1
+#-*- coding: utf-8 -*-
2
+
3
+import copy
4
+import unittest
5
+from unittest import mock
6
+from unittest.mock import patch, call, Mock
7
+
8
+import leapi.test.utils
9
+from Lodel.hooks import LodelHook
10
+
11
+class LodelHookTestCase(unittest.TestCase):
12
+
13
+    #Dynamic code generation & import
14
+    @classmethod
15
+    def setUpClass(cls):
16
+        """ Write the generated code in a temporary directory and import it """
17
+        cls.tmpdir = leapi.test.utils.tmp_load_factory_code()
18
+
19
+    @classmethod
20
+    def tearDownClass(cls):
21
+        """ Remove the temporary directory created at class setup """
22
+        leapi.test.utils.cleanup(cls.tmpdir)
23
+
24
+    def test_hook_registration(self):
25
+        """ Testing hooks registration """
26
+        self.assertEqual(LodelHook.hook_list('test_hook'), dict())
27
+        @LodelHook('test_hook', 42)
28
+        def test_hook(hook_name, caller, payload):
29
+            pass
30
+        @LodelHook('test_hook', 1)
31
+        def test2_hook(hook_name, caller, payload):
32
+            pass
33
+        @LodelHook('test_hook')
34
+        def test3_hook(hook_name, caller, payload):
35
+            pass
36
+
37
+        self.assertEqual(   LodelHook.hook_list('test_hook'),
38
+                            {
39
+                                'test_hook':[
40
+                                    (test2_hook, 1),
41
+                                    (test_hook, 42),
42
+                                    (test3_hook, 0xFFFF),
43
+                                ]
44
+                            }
45
+        )
46
+
47
+    def test_hook_call(self):
48
+        """ Testing hooks call """
49
+        # Registering a mock as hook
50
+        mockhook = Mock()
51
+        decorator = LodelHook('test_hook_call')
52
+        decorator(mockhook)
53
+        
54
+        LodelHook.call_hook('test_hook_call', leapi, [1,2,3,42])
55
+        mockhook.assert_called_once_with('test_hook_call', leapi, [1,2,3,42])
56
+        mockhook.reset_mock()
57
+        LodelHook.call_hook('test_hook_call', None, 'datas')
58
+        mockhook.assert_called_once_with('test_hook_call', None, 'datas')
59
+
60
+    def test_leapi_get_hook_leobject(self):
61
+        """ Testing that leapi_get_* hooks get called when calling get on LeObject """
62
+        from dyncode import Numero, Article, Publication, Textes, LeRelation, LeObject, LeRelation
63
+        call_args = {
64
+                        'query_filters': [],
65
+                        'offset': 0,
66
+                        'limit': None,
67
+                        'order': None,
68
+                        'group': None,
69
+                        'field_list': None
70
+        }
71
+        for leo in [Numero, Article, Publication, Textes, LeObject]:
72
+            call_args_full = copy.copy(call_args)
73
+            if 'instanciate' not in call_args_full:
74
+                call_args_full['instanciate'] = True
75
+            if leo.implements_letype():
76
+                call_args_full['query_filters'].append( ('type_id', '=', leo._type_id) )
77
+            if leo.implements_leclass():
78
+                call_args_full['query_filters'].append( ('class_id', '=', leo._class_id) )
79
+
80
+            with patch.object(LodelHook, 'call_hook', return_value=call_args_full) as callhook_mock:
81
+                foo = leo.get(**call_args)
82
+                expected_calls = [
83
+                    call('leapi_get_pre', leo, call_args_full),
84
+                    call('leapi_get_post', leo, None)
85
+                ]
86
+                callhook_mock.assert_has_calls(expected_calls, any_order = False)
87
+
88
+    def test_leapi_get_hook_lerelation(self):
89
+        """ Testing that leapi_get_* hooks get called when calling get on LeRelation """
90
+        from dyncode import LeRelation, LeRel2Type, LeHierarch, RelTextesPersonneAuteur
91
+        call_args = {
92
+                        'query_filters': [],
93
+                        'offset': 0,
94
+                        'limit': None,
95
+                        'order': None,
96
+                        'group': None,
97
+                        'field_list': None
98
+        }
99
+        for lerel in [LeRelation, LeRel2Type, LeHierarch, RelTextesPersonneAuteur]:
100
+            call_args_full = copy.copy(call_args)
101
+            if 'instanciate' not in call_args_full:
102
+                call_args_full['instanciate'] = True
103
+
104
+            with patch.object(LodelHook, 'call_hook', return_value=call_args_full) as callhook_mock:
105
+                foo = lerel.get(**call_args)
106
+                expected_calls = [
107
+                    call('leapi_get_pre', lerel, call_args_full),
108
+                    call('leapi_get_post', lerel, None),
109
+                ]
110
+                callhook_mock.assert_has_calls(expected_calls, any_order = False)
111
+
112
+    ## @todo Write tests for update, delete and insert hooks

+ 8
- 1
leapi/letype.py View File

54
     @classmethod
54
     @classmethod
55
     def get(cls, query_filters, field_list = None, order = None, group = None, limit = None, offset = 0):
55
     def get(cls, query_filters, field_list = None, order = None, group = None, limit = None, offset = 0):
56
         query_filters.append(('type_id', '=', cls._type_id))
56
         query_filters.append(('type_id', '=', cls._type_id))
57
-        return super().get(query_filters, field_list, order, group, limit, offset)
57
+        return super().get(
58
+                            query_filters = query_filters,
59
+                            field_list = field_list,
60
+                            order = order,
61
+                            group = group,
62
+                            limit = limit,
63
+                            offset = offset
64
+        )
58
 
65
 
59
     @classmethod
66
     @classmethod
60
     def fieldtypes(cls, complete=True):
67
     def fieldtypes(cls, complete=True):

Loading…
Cancel
Save