1 | #!/usr/bin/env python
|
---|
2 | # coding:utf-8
|
---|
3 | """
|
---|
4 | This file is part of the Ludd21 proprietary software
|
---|
5 | License
|
---|
6 | =======
|
---|
7 |
|
---|
8 | Copyright (C) <2019> <Odile Troulet-Lambert.tex@orange.fr>
|
---|
9 |
|
---|
10 | this programm is proprietary software
|
---|
11 |
|
---|
12 |
|
---|
13 |
|
---|
14 | Module purpose
|
---|
15 | ==============
|
---|
16 | tests for the module fabric_elements
|
---|
17 | because of the import of app_accounts.models and Fabric Type which inherits from
|
---|
18 | django models this test module requires django to be configured.
|
---|
19 | set environment variable $TEST_MODULE_MODELS to fabric_elements so as not to load all other model modules
|
---|
20 |
|
---|
21 | Implements
|
---|
22 | ==========
|
---|
23 |
|
---|
24 |
|
---|
25 | Documentation
|
---|
26 | =============
|
---|
27 |
|
---|
28 |
|
---|
29 | Usage
|
---|
30 | =====
|
---|
31 |
|
---|
32 |
|
---|
33 | @author: Odile Troulet-Lambert
|
---|
34 | @copyright: Odile Troulet-Lambert
|
---|
35 |
|
---|
36 | """
|
---|
37 | import unittest
|
---|
38 | import os
|
---|
39 | from unittest.mock import patch
|
---|
40 | from abc import abstractmethod, ABCMeta
|
---|
41 |
|
---|
42 | from django.db.models.base import ModelBase
|
---|
43 | import django.db.models as models
|
---|
44 | from django.apps.registry import Apps
|
---|
45 |
|
---|
46 |
|
---|
47 | class AbstractModelMeta(ABCMeta, type(models.Model)):
|
---|
48 | """ a Django model and python abstract class"""
|
---|
49 |
|
---|
50 | def __new__(cls, name, bases, attrs, **kwargs):
|
---|
51 |
|
---|
52 | clas = super().__new__(cls, name, bases, attrs, **kwargs)
|
---|
53 | return clas
|
---|
54 |
|
---|
55 |
|
---|
56 | class Test_AbstractImplementation (unittest.TestCase):
|
---|
57 |
|
---|
58 | @classmethod
|
---|
59 | def setUpClass(cls):
|
---|
60 | os.environ['DJANGO_SETTINGS_MODULE'] = 'djangoLudd21.settings'
|
---|
61 | cls.patcher = patch.object(Apps, 'check_apps_ready')
|
---|
62 | cls.patcher.start()
|
---|
63 |
|
---|
64 | class AbsImplementation (models.Model,
|
---|
65 | metaclass=AbstractModelMeta):
|
---|
66 | class Meta:
|
---|
67 | app_label = 'fakeapp'
|
---|
68 | abstract = True
|
---|
69 |
|
---|
70 | field1 = models.CharField(
|
---|
71 | max_length=20)
|
---|
72 | field2 = models.IntegerField(
|
---|
73 | default=5)
|
---|
74 |
|
---|
75 | @staticmethod
|
---|
76 | def change_field():
|
---|
77 | return 10
|
---|
78 |
|
---|
79 | @abstractmethod
|
---|
80 | def absmethod(self):
|
---|
81 | pass
|
---|
82 |
|
---|
83 | def __init_subclass__(cls, **kwargs):
|
---|
84 | machine = kwargs.pop('machine', None)
|
---|
85 | if not machine:
|
---|
86 | raise ValueError('implementation must have a machine attribute')
|
---|
87 | setattr(cls, 'machine', machine)
|
---|
88 | field1 = models.CharField(
|
---|
89 | max_length=cls.change_field(),
|
---|
90 | )
|
---|
91 | ModelBase.add_to_class(cls, 'field1', field1)
|
---|
92 |
|
---|
93 | cls.absimp = AbsImplementation
|
---|
94 |
|
---|
95 | def test(self):
|
---|
96 | class Imp (self.absimp,
|
---|
97 | machine='machine'):
|
---|
98 |
|
---|
99 | class Meta:
|
---|
100 | app_label = 'fakeapp'
|
---|
101 | abstract = False
|
---|
102 |
|
---|
103 | def absmethod(self):
|
---|
104 | pass
|
---|
105 |
|
---|
106 | self.assertTrue(issubclass(Imp, models.Model))
|
---|
107 | self.assertTrue(issubclass(Imp, self.absimp))
|
---|
108 |
|
---|
109 | self.assertEqual(Imp.machine, 'machine')
|
---|
110 | field1 = Imp._meta.get_field('field1')
|
---|
111 | field2 = Imp._meta.get_field('field2')
|
---|
112 | self.assertEqual(field1.max_length, 10)
|
---|
113 | self.assertEqual(field2.default, 5)
|
---|
114 |
|
---|
115 | @classmethod
|
---|
116 | def tearDownClass(cls):
|
---|
117 | cls.patcher.stop()
|
---|
118 |
|
---|
119 |
|
---|
120 | class Test_ConcreteImplementation (unittest.TestCase):
|
---|
121 |
|
---|
122 | @classmethod
|
---|
123 | def setUpClass(cls):
|
---|
124 | os.environ['DJANGO_SETTINGS_MODULE'] = 'djangoLudd21.settings'
|
---|
125 | cls.patcher = patch.object(Apps, 'check_apps_ready')
|
---|
126 | cls.patcher.start()
|
---|
127 |
|
---|
128 | class Implementation (models.Model,
|
---|
129 | metaclass=AbstractModelMeta):
|
---|
130 | class Meta:
|
---|
131 | app_label = 'fakeapp'
|
---|
132 | abstract = False
|
---|
133 |
|
---|
134 | field1 = models.CharField(
|
---|
135 | max_length=20)
|
---|
136 | field2 = models.IntegerField(
|
---|
137 | default=5)
|
---|
138 |
|
---|
139 | @staticmethod
|
---|
140 | def change_field():
|
---|
141 | return 10
|
---|
142 |
|
---|
143 | @abstractmethod
|
---|
144 | def absmethod(self):
|
---|
145 | pass
|
---|
146 |
|
---|
147 | def __init_subclass__(cls, **kwargs):
|
---|
148 | machine = kwargs.pop('machine', None)
|
---|
149 | if not machine:
|
---|
150 | raise ValueError('implementation must have a machine attribute')
|
---|
151 | setattr(cls, 'machine', machine)
|
---|
152 | field1 = models.CharField(
|
---|
153 | max_length=cls.change_field(),
|
---|
154 | )
|
---|
155 | ModelBase.add_to_class(cls, 'field1', field1)
|
---|
156 |
|
---|
157 | cls.imp = Implementation
|
---|
158 |
|
---|
159 | def test(self):
|
---|
160 | class Imp3 (self.imp,
|
---|
161 | machine='machine'):
|
---|
162 |
|
---|
163 | class Meta:
|
---|
164 | app_label = 'fakeapp'
|
---|
165 |
|
---|
166 | def absmethod(self):
|
---|
167 | pass
|
---|
168 |
|
---|
169 | self.assertTrue(issubclass(Imp3, models.Model))
|
---|
170 | self.assertTrue(issubclass(Imp3, self.imp))
|
---|
171 | self.assertEqual(Imp3.machine, 'machine')
|
---|
172 | field1 = Imp3._meta.get_field('field1')
|
---|
173 | field2 = Imp3._meta.get_field('field2')
|
---|
174 | self.assertEqual(field1.max_length, 10)
|
---|
175 | self.assertEqual(field2.default, 5)
|
---|
176 |
|
---|
177 | @classmethod
|
---|
178 | def tearDownClass(cls):
|
---|
179 | cls.patcher.stop()
|
---|
180 |
|
---|
181 |
|
---|
182 | if __name__ == '__main__':
|
---|
183 | unittest.main()
|
---|
184 |
|
---|
185 |
|
---|
186 |
|
---|
187 |
|
---|
188 |
|
---|
189 |
|
---|
190 |
|
---|
191 |
|
---|
192 |
|
---|
193 |
|
---|
194 |
|
---|
195 |
|
---|
196 |
|
---|
197 |
|
---|
198 |
|
---|
199 |
|
---|
200 |
|
---|
201 |
|
---|
202 |
|
---|
203 |
|
---|
204 |
|
---|
205 |
|
---|
206 |
|
---|