Merge "Get auth token when checking deployment"
[functest-xtesting.git] / docs / com / pres / framework / framework.md
1 # Functest Framework
2
3 created by [Cédric Ollivier](mailto:cedric.ollivier@orange.com)
4
5 2017/06/05
6
7 Note:
8
9 - Functest integrates lots of heterogeneous testcases:
10     - python vs bash
11     - internal vs external
12 - it aims to benefit from object programming
13     - to define common operations
14     - to avoid conditional instructions regarding the testcases
15     - to avoid duplicating code
16     - to ease the integration of third-party testcases (written in Bash or Python)
17
18
19
20 ## Quick overview
21
22
23 ### Functest function calls
24
25 - **CI** calls *run_tests.py* (please see [jenkins jobs](https://gerrit.opnfv.org/gerrit/gitweb?p=releng.git;a=tree;f=jjb/functest))
26 - *run_tests.py* parses *functest/ci/testcases.yaml* to:
27     - check which testcase(s) must be run
28     - execute the common operations on every testcase (run, push its results to db...)
29 <!-- .element: class="fragment highlight-red"-->
30     - return the right status code to **CI**
31
32
33 ### Our target
34
35 - limit run_tests.py instructions by defining:
36     - the basic testcase attributes
37     - all common operations
38     - the status codes expected
39 - avoid duplicating codes between testcases
40 - ease the development of third-party testcases (aka features)
41
42
43
44 ## class TestCase
45
46 base model for single test case
47
48
49 ### instance attributes
50
51 - project_name (default: 'functest')
52 - case_name
53 - criteria
54 - result
55 - start_time
56 - stop_time
57 - details
58
59
60 ### methods
61
62 | Method            | Purpose                      |
63 |-------------------|------------------------------|
64 | run(**kwargs)     | run the test case            |
65 | is_successful()   | interpret the results        |
66 | get_duration()    | return the duration          |
67 | push_to_db()      | push the results to the DB   |
68 | clean()           | clean the resources          |
69
70
71 ### run(**kwargs)
72
73 - the subclasses must override the default implementation which is false on purpose
74 - the new implementation must set the following attributes to push the results to DB:
75     - result
76     - start_time
77     - stop_time
78
79
80 ### class attributes
81
82 | Status code        | Returned when       |
83 |--------------------|---------------------|
84 | EX_OK              | everything is OK    |
85 | EX_RUN_ERROR       | run() failed        |
86 | EX_TESTCASE_FAILED | results are false   |
87 | EX_PUSH_TO_DB_ERROR| push_to_db() failed |
88
89
90 ### run_tests.py
91
92 ```python
93 module = importlib.import_module(run_dict['module'])
94 cls = getattr(module, run_dict['class'])
95 test_dict = ft_utils.get_dict_by_test(test_name)
96 test_case = cls(**test_dict)
97 try:
98     kwargs = run_dict['args']
99     result = test_case.run(**kwargs)
100 except KeyError:
101     result = test_case.run()
102 if result == testcase.TestCase.EX_OK:
103     if GlobalVariables.REPORT_FLAG:
104         test_case.push_to_db()
105     result = test_case.is_successful()
106 ```
107
108
109
110 ## Your first test case
111
112
113 ### first.py
114
115 ```python
116 #!/usr/bin/env python
117
118 import time
119
120 from functest.core import testcase
121
122 class Test(testcase.TestCase):
123
124     def run(self, **kwargs):
125         self.start_time = time.time()
126         print "Hello World"
127         self.result = 100
128         self.stop_time = time.time()
129         return testcase.TestCase.EX_OK
130 ```
131
132
133 ### functest/ci/testcases.yaml
134
135 ```yaml
136 case_name: first
137 project_name: functest
138 criteria: 100
139 blocking: true
140 description: ''
141 dependencies:
142     installer: ''
143     scenario: ''
144 run:
145     module: 'first'
146     class: 'Test'
147 ```
148
149
150
151 ## class Feature
152 bases: TestCase
153
154 base model for single feature
155
156
157 ### methods
158
159 | Method            | Purpose                   |
160 |-------------------|---------------------------|
161 | run(**kwargs)     | run the feature           |
162 | execute(**kwargs) | execute the Python method |
163
164
165 ### run(**kwargs)
166
167 - allows executing any Python method by calling execute()
168 - sets the following attributes required to push the results to DB:
169     - result
170     - start_time
171     - stop_time
172 - doesn't fulfill details when pushing the results to the DB.
173
174
175 ### execute(**kwargs)
176
177 - the subclasses must override the default implementation which is false on purpose
178 - the new implementation must return 0 if success or anything else if failure.
179
180
181
182 ## Your second test case
183
184
185 ### second.py
186
187 ```python
188 #!/usr/bin/env python
189
190 from functest.core import feature
191
192 class Test(feature.Feature):
193
194     def execute(self, **kwargs):
195         print "Hello World"
196         return 0
197 ```
198
199
200 ### functest/ci/testcases.yaml
201
202 ```yaml
203 case_name: second
204 project_name: functest
205 criteria: 100
206 blocking: true
207 description: ''
208 dependencies:
209     installer: ''
210     scenario: ''
211 run:
212     module: 'second'
213     class: 'Test'
214 ```
215
216
217
218 ## class BashFeature
219 bases: Feature
220
221 class designed to run any bash command
222
223
224 ### execute(**kwargs)
225
226 execute the cmd passed as arg.
227
228
229
230 ## Your third test case
231
232
233 ### functest/ci/testcases.yaml
234
235 ```
236 case_name: third
237 project_name: functest
238 criteria: 100
239 blocking: true
240 description: ''
241 dependencies:
242     installer: ''
243     scenario: ''
244 run:
245     module: 'functest.core.feature'
246     class: 'BashFeature'
247     args:
248         cmd: 'echo Hello World; exit 0'
249 ```
250
251
252
253 ## class Suite
254 bases: TestCase
255
256 base model for running unittest.TestSuite
257
258
259 ### run(**kwargs)
260
261 - allows running any unittest.TestSuite
262 - sets the following attributes required to push the results to DB:
263     - result
264     - start_time
265     - stop_time
266     - details
267
268
269
270 ## Your fourth test case
271
272
273 ### fourth.py
274
275 ```python
276 #!/usr/bin/env python
277
278 import unittest
279
280 class TestStringMethods(unittest.TestCase):
281
282     def test_upper(self):
283         self.assertEqual('Hello World'.upper(),
284                          'HELLO WORLD')
285 ```
286
287
288 ### functest/ci/testcases.yaml
289
290 ```
291 case_name: fourth
292 project_name: functest
293 criteria: 100
294 blocking: true
295 description: ''
296 dependencies:
297     installer: ''
298     scenario: ''
299 run:
300     module: 'functest.core.unit'
301     class: 'Suite'
302     args:
303         name: 'fourth'
304 ```
305
306
307
308 ## class VNF
309 bases: TestCase
310
311 base model for VNF onboarding testing
312
313
314 ### methods
315
316 | Method                | Purpose                                           |
317 |-----------------------|---------------------------------------------------|
318 | prepare()             | prepare VNF env (user, tenant, security group,..) |
319 | run(**kwargs)         | run VNF test case                                 |
320 | deploy_orchestrator() | deploy cloudify, ONAP, OpenBaton,... (optional)   |
321 | deploy_vnf()          | deploy the VNF                                    |
322 | test_vnf()            | run tests on the VNF                              |
323
324
325 ### run(**kwargs)
326
327 - deploys an orchestrator if needed (e.g. heat, OpenBaton, Cloudify, ONAP, Juju)
328 - deploys the VNF
329 - performs tests on the VNF
330
331
332 ### prepare()
333
334 - creates a user
335 - creates a Tenant/Project
336 - allocates admin role to the user on this tenant
337
338
339 ### deploy_orchestrator()
340
341 - deploys an orchestrator (optional)
342 - if this function is overridden then raise orchestratorDeploymentException if error during orchestrator deployment
343
344
345 ### deploy_vnf()
346
347 - **MUST be implemented** by vnf test cases. The details section MAY be updated in the vnf test cases.
348 - The deployment can be executed via a specific orchestrator or using build-in orchestrators such as heat, openbaton, cloudify, juju, ONAP, ...
349 - returns:
350   True if the VNF is properly deployed
351   False if the VNF is not deployed
352 - raises VnfDeploymentException if error during VNF deployment
353
354
355 ### test_vnf()
356
357 - **MUST be implemented** by vnf test cases. The details section MAY be updated in the vnf test cases.
358 - Once a VNF is deployed, it is assumed that specific test suite can be run to validate the VNF.
359 - returns:
360   True if VNF tests are PASS
361   False if test suite is FAIL
362 - raises VnfTestException if error during VNF tests
363
364
365
366 ## Your fifth test case
367
368
369 ### fifth.py
370
371 ```python
372 #!/usr/bin/env python
373
374 from functest.core import vnf
375
376 class Vnf(vnf.VnfOnBoarding):
377
378     def deploy_vnf(self):
379         print "Deploy your VNF here"
380         print "Feed orchestrator with VNF descriptor"
381         return 0
382
383     def test_vnf(self):
384         print "Test your VNF here"
385         return 0
386 ```
387
388
389 ### functest/ci/testcases.yaml
390
391 ```yaml
392 case_name: fifth
393 project_name: functest
394 criteria: 100
395 blocking: true
396 description: ''
397 dependencies:
398     installer: ''
399     scenario: ''
400 run:
401     module: 'fifth'
402     class: 'Vnf'
403 ```
404
405
406
407 ## Thank You!