Allow dynamically skipping testcases
[functest-xtesting.git] / xtesting / tests / unit / core / test_testcase.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2016 Orange and others.
4 #
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
9
10 """Define the class required to fully cover testcase."""
11
12 from datetime import datetime
13 import json
14 import logging
15 import os
16 import unittest
17
18 import mock
19 import requests
20
21 from xtesting.core import testcase
22
23 __author__ = "Cedric Ollivier <cedric.ollivier@orange.com>"
24
25
26 class TestCaseTesting(unittest.TestCase):
27     """The class testing TestCase."""
28
29     # pylint: disable=missing-docstring,too-many-public-methods
30
31     _case_name = "base"
32     _project_name = "xtesting"
33     _published_result = "PASS"
34     _test_db_url = "http://testresults.opnfv.org/test/api/v1/results"
35     _headers = {'Content-Type': 'application/json'}
36
37     def setUp(self):
38         self.test = testcase.TestCase(case_name=self._case_name,
39                                       project_name=self._project_name)
40         self.test.start_time = 1
41         self.test.stop_time = 2
42         self.test.result = 100
43         self.test.details = {"Hello": "World"}
44         os.environ['TEST_DB_URL'] = TestCaseTesting._test_db_url
45         os.environ['INSTALLER_TYPE'] = "installer_type"
46         os.environ['DEPLOY_SCENARIO'] = "scenario"
47         os.environ['NODE_NAME'] = "node_name"
48         os.environ['BUILD_TAG'] = "foo-daily-master-bar"
49
50     def test_run_unimplemented(self):
51         self.assertEqual(self.test.run(),
52                          testcase.TestCase.EX_RUN_ERROR)
53
54     def _test_pushdb_missing_attribute(self):
55         self.assertEqual(self.test.push_to_db(),
56                          testcase.TestCase.EX_PUSH_TO_DB_ERROR)
57
58     def test_pushdb_no_project_name(self):
59         self.test.project_name = None
60         self._test_pushdb_missing_attribute()
61
62     def test_pushdb_no_case_name(self):
63         self.test.case_name = None
64         self._test_pushdb_missing_attribute()
65
66     def test_pushdb_no_start_time(self):
67         self.test.start_time = None
68         self._test_pushdb_missing_attribute()
69
70     def test_pushdb_no_stop_time(self):
71         self.test.stop_time = None
72         self._test_pushdb_missing_attribute()
73
74     def _test_pushdb_missing_env(self, var):
75         del os.environ[var]
76         self.assertEqual(self.test.push_to_db(),
77                          testcase.TestCase.EX_PUSH_TO_DB_ERROR)
78
79     def test_pushdb_no_db_url(self):
80         self._test_pushdb_missing_env('TEST_DB_URL')
81
82     def test_pushdb_no_installer_type(self):
83         self._test_pushdb_missing_env('INSTALLER_TYPE')
84
85     def test_pushdb_no_deploy_scenario(self):
86         self._test_pushdb_missing_env('DEPLOY_SCENARIO')
87
88     def test_pushdb_no_node_name(self):
89         self._test_pushdb_missing_env('NODE_NAME')
90
91     def test_pushdb_no_build_tag(self):
92         self._test_pushdb_missing_env('BUILD_TAG')
93
94     @mock.patch('requests.post')
95     def test_pushdb_bad_start_time(self, mock_function=None):
96         self.test.start_time = "1"
97         self.assertEqual(
98             self.test.push_to_db(),
99             testcase.TestCase.EX_PUSH_TO_DB_ERROR)
100         mock_function.assert_not_called()
101
102     @mock.patch('requests.post')
103     def test_pushdb_bad_end_time(self, mock_function=None):
104         self.test.stop_time = "2"
105         self.assertEqual(
106             self.test.push_to_db(),
107             testcase.TestCase.EX_PUSH_TO_DB_ERROR)
108         mock_function.assert_not_called()
109
110     @mock.patch('requests.post')
111     def test_pushdb_skipped_test(self, mock_function=None):
112         self.test.is_skipped = True
113         self.assertEqual(
114             self.test.push_to_db(),
115             testcase.TestCase.EX_PUSH_TO_DB_ERROR)
116         mock_function.assert_not_called()
117
118     def _get_data(self):
119         return {
120             "build_tag": os.environ['BUILD_TAG'],
121             "case_name": self._case_name,
122             "criteria": 'PASS' if self.test.is_successful(
123                 ) == self.test.EX_OK else 'FAIL',
124             "details": self.test.details,
125             "installer": os.environ['INSTALLER_TYPE'],
126             "pod_name": os.environ['NODE_NAME'],
127             "project_name": self.test.project_name,
128             "scenario": os.environ['DEPLOY_SCENARIO'],
129             "start_date": datetime.fromtimestamp(
130                 self.test.start_time).strftime('%Y-%m-%d %H:%M:%S'),
131             "stop_date": datetime.fromtimestamp(
132                 self.test.stop_time).strftime('%Y-%m-%d %H:%M:%S'),
133             "version": "master"}
134
135     @mock.patch('requests.post')
136     def _test_pushdb_version(self, mock_function=None, **kwargs):
137         payload = self._get_data()
138         payload["version"] = kwargs.get("version", "unknown")
139         self.assertEqual(self.test.push_to_db(), testcase.TestCase.EX_OK)
140         mock_function.assert_called_once_with(
141             os.environ['TEST_DB_URL'],
142             data=json.dumps(payload, sort_keys=True),
143             headers=self._headers)
144
145     def test_pushdb_daily_job(self):
146         self._test_pushdb_version(version="master")
147
148     def test_pushdb_weekly_job(self):
149         os.environ['BUILD_TAG'] = 'foo-weekly-master-bar'
150         self._test_pushdb_version(version="master")
151
152     def test_pushdb_random_build_tag(self):
153         os.environ['BUILD_TAG'] = 'whatever'
154         self._test_pushdb_version(version="unknown")
155
156     @mock.patch('requests.post', return_value=mock.Mock(
157         raise_for_status=mock.Mock(
158             side_effect=requests.exceptions.HTTPError)))
159     def test_pushdb_http_errors(self, mock_function=None):
160         self.assertEqual(
161             self.test.push_to_db(),
162             testcase.TestCase.EX_PUSH_TO_DB_ERROR)
163         mock_function.assert_called_once_with(
164             os.environ['TEST_DB_URL'],
165             data=json.dumps(self._get_data(), sort_keys=True),
166             headers=self._headers)
167
168     def test_check_requirements(self):
169         self.test.check_requirements()
170         self.assertEqual(self.test.is_skipped, False)
171
172     def test_check_criteria_missing(self):
173         self.test.criteria = None
174         self.assertEqual(self.test.is_successful(),
175                          testcase.TestCase.EX_TESTCASE_FAILED)
176
177     def test_check_result_missing(self):
178         self.test.result = None
179         self.assertEqual(self.test.is_successful(),
180                          testcase.TestCase.EX_TESTCASE_FAILED)
181
182     def test_check_result_failed(self):
183         # Backward compatibility
184         # It must be removed as soon as TestCase subclasses
185         # stop setting result = 'PASS' or 'FAIL'.
186         self.test.result = 'FAIL'
187         self.assertEqual(self.test.is_successful(),
188                          testcase.TestCase.EX_TESTCASE_FAILED)
189
190     def test_check_result_pass(self):
191         # Backward compatibility
192         # It must be removed as soon as TestCase subclasses
193         # stop setting result = 'PASS' or 'FAIL'.
194         self.test.result = 'PASS'
195         self.assertEqual(self.test.is_successful(),
196                          testcase.TestCase.EX_OK)
197
198     def test_check_result_skip(self):
199         self.test.is_skipped = True
200         self.assertEqual(self.test.is_successful(),
201                          testcase.TestCase.EX_TESTCASE_SKIPPED)
202
203     def test_check_result_lt(self):
204         self.test.result = 50
205         self.assertEqual(self.test.is_successful(),
206                          testcase.TestCase.EX_TESTCASE_FAILED)
207
208     def test_check_result_eq(self):
209         self.test.result = 100
210         self.assertEqual(self.test.is_successful(),
211                          testcase.TestCase.EX_OK)
212
213     def test_check_result_gt(self):
214         self.test.criteria = 50
215         self.test.result = 100
216         self.assertEqual(self.test.is_successful(),
217                          testcase.TestCase.EX_OK)
218
219     def test_check_result_zero(self):
220         self.test.criteria = 0
221         self.test.result = 0
222         self.assertEqual(self.test.is_successful(),
223                          testcase.TestCase.EX_TESTCASE_FAILED)
224
225     def test_get_duration_start_ko(self):
226         self.test.start_time = None
227         self.assertEqual(self.test.get_duration(), "XX:XX")
228         self.test.start_time = 0
229         self.assertEqual(self.test.get_duration(), "XX:XX")
230
231     def test_get_duration_end_ko(self):
232         self.test.stop_time = None
233         self.assertEqual(self.test.get_duration(), "XX:XX")
234         self.test.stop_time = 0
235         self.assertEqual(self.test.get_duration(), "XX:XX")
236
237     def test_get_invalid_duration(self):
238         self.test.start_time = 2
239         self.test.stop_time = 1
240         self.assertEqual(self.test.get_duration(), "XX:XX")
241
242     def test_get_zero_duration(self):
243         self.test.start_time = 2
244         self.test.stop_time = 2
245         self.assertEqual(self.test.get_duration(), "00:00")
246
247     def test_get_duration(self):
248         self.test.start_time = 1
249         self.test.stop_time = 180
250         self.assertEqual(self.test.get_duration(), "02:59")
251
252     def test_get_duration_skipped_test(self):
253         self.test.is_skipped = True
254         self.assertEqual(self.test.get_duration(), "00:00")
255
256     def test_str_project_name_ko(self):
257         self.test.project_name = None
258         self.assertIn("<xtesting.core.testcase.TestCase object at",
259                       str(self.test))
260
261     def test_str_case_name_ko(self):
262         self.test.case_name = None
263         self.assertIn("<xtesting.core.testcase.TestCase object at",
264                       str(self.test))
265
266     def test_str_pass(self):
267         duration = '01:01'
268         with mock.patch.object(self.test, 'get_duration',
269                                return_value=duration), \
270                 mock.patch.object(self.test, 'is_successful',
271                                   return_value=testcase.TestCase.EX_OK):
272             message = str(self.test)
273         self.assertIn(self._project_name, message)
274         self.assertIn(self._case_name, message)
275         self.assertIn(duration, message)
276         self.assertIn('PASS', message)
277
278     def test_str_fail(self):
279         duration = '00:59'
280         with mock.patch.object(self.test, 'get_duration',
281                                return_value=duration), \
282                 mock.patch.object(
283                     self.test, 'is_successful',
284                     return_value=testcase.TestCase.EX_TESTCASE_FAILED):
285             message = str(self.test)
286         self.assertIn(self._project_name, message)
287         self.assertIn(self._case_name, message)
288         self.assertIn(duration, message)
289         self.assertIn('FAIL', message)
290
291     def test_str_skip(self):
292         self.test.is_skipped = True
293         message = str(self.test)
294         self.assertIn(self._project_name, message)
295         self.assertIn(self._case_name, message)
296         self.assertIn("00:00", message)
297         self.assertIn('SKIP', message)
298
299     def test_clean(self):
300         self.assertEqual(self.test.clean(), None)
301
302
303 if __name__ == "__main__":
304     logging.disable(logging.CRITICAL)
305     unittest.main(verbosity=2)