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