Revision 16d7b9ff docs/developers/extending-clients-api.rst
b/docs/developers/extending-clients-api.rst | ||
---|---|---|
1 | 1 |
Extending kamaki.clients |
2 | 2 |
======================== |
3 | 3 |
|
4 |
By default, kamaki clients are REST clients (they manage HTTP requests and
|
|
5 |
responses to communicate with services).
|
|
4 |
By default, kamaki clients implement REST APIs, therefore they manage HTTP
|
|
5 |
requests and responses to communicate with services.
|
|
6 | 6 |
|
7 | 7 |
How to build a client |
8 | 8 |
--------------------- |
... | ... | |
17 | 17 |
|
18 | 18 |
from kamaki.clients import Client, ClientError |
19 | 19 |
|
20 |
|
|
20 | 21 |
class MyNewClient(Client): |
21 | 22 |
"""MyNewClient Description Here""" |
22 | 23 |
|
... | ... | |
100 | 101 |
----------- |
101 | 102 |
|
102 | 103 |
The kamaki.clients package contains a set of fine-grained unit-tests for all |
103 |
its packages.
|
|
104 |
APIs.
|
|
104 | 105 |
|
105 | 106 |
.. note:: unit tests require the optional python-mock package, version 1.X or |
106 | 107 |
better |
... | ... | |
123 | 124 |
|
124 | 125 |
$ python test.py |
125 | 126 |
|
126 |
To test a specific class, add the class name as an argument. E.g. for the
|
|
127 |
To test a specific class, add the class name as an argument. e.g., for the
|
|
127 | 128 |
Client class: |
128 | 129 |
|
129 | 130 |
.. code-block:: console |
130 | 131 |
|
131 | 132 |
$ python test.py Client |
132 | 133 |
|
133 |
To test a specific method in a class, apply an extra argument, e.g. for the |
|
134 |
To test a specific method in a class, apply an extra argument, e.g., for the
|
|
134 | 135 |
request method in the Client class: |
135 | 136 |
|
136 | 137 |
.. code-block:: console |
... | ... | |
138 | 139 |
$ python test.py Client request |
139 | 140 |
|
140 | 141 |
Each package contains a test module (test.py) which is also runnable from the |
141 |
command line. E.g. in the pithos package there is a test module which
|
|
142 |
command line. e.g., in the pithos package there is a test module which
|
|
142 | 143 |
contains, among others, the **download** sub-test: |
143 | 144 |
|
144 | 145 |
.. code-block:: console |
... | ... | |
154 | 155 |
# Test kamaki.clients.pithos.PithosClient.download |
155 | 156 |
$ python test.py Pithos download |
156 | 157 |
|
157 |
To fully test a specific package, run test.py from the package location. E.g.
|
|
158 |
To fully test a specific package, run test.py from the package location. e.g.,
|
|
158 | 159 |
to test everything in kamaki.clients.pithos package: |
159 | 160 |
|
160 | 161 |
.. code-block:: console |
... | ... | |
169 | 170 |
of this package. All test modules contain a set of classes that extent the |
170 | 171 |
TestCase class. They also contain a main method to run the tests. |
171 | 172 |
|
172 |
By convention, testing classes are named as <Tested Class> where <Test Class>
|
|
173 |
is the name of the tested class or module. Methods not grouped in classes are
|
|
174 |
tested by classes named after their respective module.
|
|
173 |
By convention, testing classes have the same name as the class they test.
|
|
174 |
Methods not grouped in classes are tested by classes named after their
|
|
175 |
respective module. |
|
175 | 176 |
|
176 |
For example, the kamaki.clients.pithos.PithosClient class is tested by the |
|
177 |
kamaki.clients.pithos.test.PithosClient class, while the methods in |
|
178 |
kamaki.clients.utils module are tested by the kamaki.clients.utils.test.Utils |
|
179 |
testing class. |
|
177 |
For example, the *kamaki.clients.pithos.PithosClient* class is tested by the |
|
178 |
*kamaki.clients.pithos.test.PithosClient* class, while the methods in |
|
179 |
*kamaki.clients.utils* module are tested by *kamaki.clients.utils.test.Utils*. |
|
180 | 180 |
|
181 | 181 |
Adding unit tests |
182 | 182 |
^^^^^^^^^^^^^^^^^ |
183 | 183 |
|
184 |
After modifying or extending kamaki.clients method, classes, modules or
|
|
184 |
After modifying or extending *kamaki.clients* method, classes, modules or
|
|
185 | 185 |
packages, it is a good practice to also modify or extend the corresponding |
186 | 186 |
unit tests. What's more, it is recommended to modify or implement the testing |
187 |
of new behavior before implementing the behavior itself. The aim for
|
|
188 |
kamaki.clients package is an 1 to 1 mapping between methods and their tests.
|
|
187 |
of new behavior before implementing the behavior itself. The goal is to
|
|
188 |
preserve an 1 to 1 mapping between methods and their tests.
|
|
189 | 189 |
|
190 | 190 |
Modifying an existing method |
191 | 191 |
"""""""""""""""""""""""""""" |
... | ... | |
195 | 195 |
test module under the same package, in a TestCase subclass that is named with a |
196 | 196 |
name similar to the package or class that contains the tested method. |
197 | 197 |
|
198 |
Example 1: to modify the kamaki.clients.utils.filter_in method, the programmer |
|
199 |
has to also adjust the kamaki.clients.utils.test.Utils.test_filter_in method. |
|
200 |
|
|
201 |
Example 2: to modify the kamaki.clients.pithos.PithosRestClient.object_get, the |
|
198 |
Example: to modify *kamaki.clients.pithos.PithosRestClient.object_get*, the |
|
202 | 199 |
programmer has to also adjust the |
203 |
kamaki.clients.pithos.test.PithosRestClient.test_object_get method.
|
|
200 |
*kamaki.clients.pithos.test.PithosRestClient.test.object_get* method.
|
|
204 | 201 |
|
205 | 202 |
Adding a new method |
206 | 203 |
""""""""""""""""""" |
207 | 204 |
|
208 |
Programmers who want to implement a new method in an existing class, are |
|
209 |
encouraged to implement the corresponding unit test first. In order to do that, |
|
210 |
they should find the testing class that is mapped to the class or module they |
|
211 |
need to extend. |
|
205 |
To implement a new method in an existing class, developers are encouraged to |
|
206 |
implement the corresponding unit test first. In order to do that, they should |
|
207 |
find the testing class that is mapped to the class or module they working on. |
|
212 | 208 |
|
213 |
Example 1: To add a **list_special** method to
|
|
214 |
kamaki.clients.astakos.AstakosClient, extend the
|
|
215 |
kamaki.clients.astakos.test.AstakosClient class, as shown bellow:
|
|
209 |
Example: Adding **list_special** to *kamaki.clients.astakos.AstakosClient*,
|
|
210 |
requires changes to *kamaki.clients.astakos.test.AstakosClient* too, as shown
|
|
211 |
bellow: |
|
216 | 212 |
|
217 | 213 |
.. code-block:: python |
218 | 214 |
|
... | ... | |
224 | 220 |
"""Test the list_special method""" |
225 | 221 |
... |
226 | 222 |
|
227 |
Example 2: To add a **get_random_int** method in kamaki.clients.utils module, |
|
228 |
extend the kamaki.clients.utils.test.Utils test class, as shown bellow: |
|
229 |
|
|
230 |
.. code-block:: python |
|
231 |
|
|
232 |
# file: ${kamaki}/kamaki/clients/utils/__init__.py |
|
233 |
|
|
234 |
class Utils(TestCase): |
|
235 |
... |
|
236 |
def test_get_random_int(self): |
|
237 |
"""Test the get_random_int method""" |
|
238 |
... |
|
239 |
|
|
240 | 223 |
Implementing a new class or module |
241 | 224 |
"""""""""""""""""""""""""""""""""" |
242 | 225 |
|
243 | 226 |
Each class or module needs a seperate test sub-module. By convention, each |
244 |
class or module under the kamaki.clients should be located in a separate
|
|
227 |
class or module under *kamaki.clients*, should be located in a separate
|
|
245 | 228 |
directory. |
246 | 229 |
|
247 |
Example 1: To add a NewService class that implements the kamaki.clients.Client |
|
248 |
interface: |
|
230 |
Example 1: To add a NewService class that implements *kamaki.clients.Client*: |
|
249 | 231 |
|
250 |
* create a new_service package and implement the unit tests in the kamaki.clients.new_service.test module: |
|
232 |
* create a new_service package and implement the unit tests in |
|
233 |
*kamaki.clients.new_service.test*: |
|
251 | 234 |
|
252 | 235 |
.. code-block:: console |
253 | 236 |
|
254 | 237 |
$ mkdir new_service && touch new_service/test.py |
255 | 238 |
|
256 |
* create the file that will hold the package code and implement the module there:
|
|
239 |
* create the file to code the package implementation:
|
|
257 | 240 |
|
258 | 241 |
.. code-block:: console |
259 | 242 |
|
260 | 243 |
$ touch new_service/__init__.py |
261 | 244 |
|
262 |
* Create the test class and methods in kamaki.clients.new_service.test
|
|
245 |
* Create the test class and methods in *kamaki.clients.new_service.test*
|
|
263 | 246 |
|
264 | 247 |
.. code-block:: python |
265 | 248 |
|
... | ... | |
283 | 266 |
def method1(self, ...): |
284 | 267 |
... |
285 | 268 |
|
286 |
* Expose the new tests to top test module, by importing the test class to kamaki.clients.test
|
|
269 |
* Import the test class to *kamaki.clients.test*:
|
|
287 | 270 |
|
288 |
..code-block:: python |
|
271 |
.. code-block:: python
|
|
289 | 272 |
|
290 | 273 |
# file: ${kamaki}/kamaki/clients/test.py |
291 |
|
|
292 | 274 |
from kamaki.clients.new_service.test import NewService |
293 | 275 |
|
294 | 276 |
.. note:: If the new class or module is part of an existing sub-package, it is |
Also available in: Unified diff