Merge "Make tempest user_password more complicated"
[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 | create_snapshot() | save the testing environment |
69 | clean()           | clean the resources          |
70
71
72 ### run(**kwargs)
73
74 - the subclasses must override the default implementation which is false on purpose
75 - the new implementation must set the following attributes to push the results to DB:
76     - result
77     - start_time
78     - stop_time
79
80
81 ### class attributes
82
83 | Status code        | Returned when       |
84 |--------------------|---------------------|
85 | EX_OK              | everything is OK    |
86 | EX_RUN_ERROR       | run() failed        |
87 | EX_TESTCASE_FAILED | results are false   |
88 | EX_PUSH_TO_DB_ERROR| push_to_db() failed |
89
90
91 ### run_tests.py
92
93 ```python
94 module = importlib.import_module(run_dict['module'])
95 cls = getattr(module, run_dict['class'])
96 test_dict = ft_utils.get_dict_by_test(test_name)
97 test_case = cls(**test_dict)
98 try:
99     kwargs = run_dict['args']
100     result = test_case.run(**kwargs)
101 except KeyError:
102     result = test_case.run()
103 if result == testcase.TestCase.EX_OK:
104     if GlobalVariables.REPORT_FLAG:
105         test_case.push_to_db()
106     result = test_case.is_successful()
107 ```
108
109
110
111 ## Your first test case
112
113
114 ### first.py
115
116 ```python
117 #!/usr/bin/env python
118
119 import time
120
121 from functest.core import testcase
122
123 class Test(testcase.TestCase):
124
125     def run(self, **kwargs):
126         self.start_time = time.time()
127         print "Hello World"
128         self.result = 100
129         self.stop_time = time.time()
130         return testcase.TestCase.EX_OK
131 ```
132
133
134 ### functest/ci/testcases.yaml
135
136 ```yaml
137 case_name: first
138 project_name: functest
139 criteria: 100
140 blocking: true
141 description: ''
142 dependencies:
143     installer: ''
144     scenario: ''
145 run:
146     module: 'first'
147     class: 'Test'
148 ```
149
150
151
152 ## class Feature
153 bases: TestCase
154
155 base model for single feature
156
157
158 ### methods
159
160 | Method            | Purpose                   |
161 |-------------------|---------------------------|
162 | run(**kwargs)     | run the feature           |
163 | execute(**kwargs) | execute the Python method |
164
165
166 ### run(**kwargs)
167
168 - allows executing any Python method by calling execute()
169 - sets the following attributes required to push the results to DB:
170     - result
171     - start_time
172     - stop_time
173 - doesn't fulfill details when pushing the results to the DB.
174
175
176 ### execute(**kwargs)
177
178 - the subclasses must override the default implementation which is false on purpose
179 - the new implementation must return 0 if success or anything else if failure.
180
181
182
183 ## Your second test case
184
185
186 ### second.py
187
188 ```python
189 #!/usr/bin/env python
190
191 from functest.core import feature
192
193 class Test(feature.Feature):
194
195     def execute(self, **kwargs):
196         print "Hello World"
197         return 0
198 ```
199
200
201 ### functest/ci/testcases.yaml
202
203 ```yaml
204 case_name: second
205 project_name: functest
206 criteria: 100
207 blocking: true
208 description: ''
209 dependencies:
210     installer: ''
211     scenario: ''
212 run:
213     module: 'second'
214     class: 'Test'
215 ```
216
217
218
219 ## class BashFeature
220 bases: Feature
221
222 class designed to run any bash command
223
224
225 ### execute(**kwargs)
226
227 execute the cmd passed as arg.
228
229
230
231 ## Your third test case
232
233
234 ### functest/ci/testcases.yaml
235
236 ```
237 case_name: third
238 project_name: functest
239 criteria: 100
240 blocking: true
241 description: ''
242 dependencies:
243     installer: ''
244     scenario: ''
245 run:
246     module: 'functest.core.feature'
247     class: 'BashFeature'
248     args:
249         cmd: 'echo Hello World; exit 0'
250 ```
251
252
253
254 ## class Suite
255 bases: TestCase
256
257 base model for running unittest.TestSuite
258
259
260 ### run(**kwargs)
261
262 - allows running any unittest.TestSuite
263 - sets the following attributes required to push the results to DB:
264     - result
265     - start_time
266     - stop_time
267     - details
268
269
270
271 ## Your fourth test case
272
273
274 ### fourth.py
275
276 ```python
277 #!/usr/bin/env python
278
279 import unittest
280
281 class TestStringMethods(unittest.TestCase):
282
283     def test_upper(self):
284         self.assertEqual('Hello World'.upper(),
285                          'HELLO WORLD')
286 ```
287
288
289 ### functest/ci/testcases.yaml
290
291 ```
292 case_name: fourth
293 project_name: functest
294 criteria: 100
295 blocking: true
296 description: ''
297 dependencies:
298     installer: ''
299     scenario: ''
300 run:
301     module: 'functest.core.unit'
302     class: 'Suite'
303     args:
304         name: 'fourth'
305 ```
306
307
308
309 ## Euphrates
310
311
312 ### Next actions
313
314 - __to finish VNF abstraction (coverage + pylint)__
315 - to publish doc API
316
317 Please see [Functest Euphrates page](https://wiki.opnfv.org/display/functest/Functest+Euphrates+page) for more details
318
319
320
321 ## Thank You!