3 # Copyright (c) 2016 Orange and others.
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
10 """Define the parent class of all Functest TestCases."""
15 import functest.utils.functest_utils as ft_utils
20 __author__ = "Cedric Ollivier <cedric.ollivier@orange.com>"
23 class TestCase(object):
24 """Base model for single test case."""
27 """everything is OK"""
29 EX_RUN_ERROR = os.EX_SOFTWARE
32 EX_PUSH_TO_DB_ERROR = os.EX_SOFTWARE - 1
33 """push_to_db() failed"""
35 EX_TESTCASE_FAILED = os.EX_SOFTWARE - 2
36 """results are false"""
38 __logger = logging.getLogger(__name__)
40 def __init__(self, **kwargs):
42 self.project_name = kwargs.get('project_name', 'functest')
43 self.case_name = kwargs.get('case_name', '')
44 self.criteria = kwargs.get('criteria', 100)
51 assert self.project_name
53 result = 'PASS' if(self.is_successful(
54 ) == TestCase.EX_OK) else 'FAIL'
55 msg = prettytable.PrettyTable(
56 header_style='upper', padding_width=5,
57 field_names=['test case', 'project', 'duration',
59 msg.add_row([self.case_name, self.project_name,
60 self.get_duration(), result])
61 return msg.get_string()
62 except AssertionError:
63 self.__logger.error("We cannot print invalid objects")
64 return super(TestCase, self).__str__()
66 def get_duration(self):
67 """Return the duration of the test case.
70 duration if start_time and stop_time are set
74 assert self.start_time
76 if self.stop_time < self.start_time:
78 return "{0[0]:02.0f}:{0[1]:02.0f}".format(divmod(
79 self.stop_time - self.start_time, 60))
80 except Exception: # pylint: disable=broad-except
81 self.__logger.error("Please run test before getting the duration")
84 def is_successful(self):
85 """Interpret the result of the test case.
87 It allows getting the result of TestCase. It completes run()
88 which only returns the execution status.
90 It can be overriden if checking result is not suitable.
93 TestCase.EX_OK if result is 'PASS'.
94 TestCase.EX_TESTCASE_FAILED otherwise.
98 assert self.result is not None
99 if (not isinstance(self.result, str) and
100 not isinstance(self.criteria, str)):
101 if self.result >= self.criteria:
102 return TestCase.EX_OK
104 # Backward compatibility
105 # It must be removed as soon as TestCase subclasses
106 # stop setting result = 'PASS' or 'FAIL'.
107 # In this case criteria is unread.
108 self.__logger.warning(
109 "Please update result which must be an int!")
110 if self.result == 'PASS':
111 return TestCase.EX_OK
112 except AssertionError:
113 self.__logger.error("Please run test before checking the results")
114 return TestCase.EX_TESTCASE_FAILED
116 def run(self, **kwargs):
117 """Run the test case.
119 It allows running TestCase and getting its execution
122 The subclasses must override the default implementation which
125 The new implementation must set the following attributes to
126 push the results to DB:
133 kwargs: Arbitrary keyword arguments.
136 TestCase.EX_RUN_ERROR.
138 # pylint: disable=unused-argument
139 self.__logger.error("Run must be implemented")
140 return TestCase.EX_RUN_ERROR
142 def push_to_db(self):
143 """Push the results of the test case to the DB.
145 It allows publishing the results and to check the status.
147 It could be overriden if the common implementation is not
148 suitable. The following attributes must be set before pushing
158 TestCase.EX_OK if results were pushed to DB.
159 TestCase.EX_PUSH_TO_DB_ERROR otherwise.
162 assert self.project_name
163 assert self.case_name
164 assert self.start_time
165 assert self.stop_time
166 pub_result = 'PASS' if self.is_successful(
167 ) == TestCase.EX_OK else 'FAIL'
168 if ft_utils.push_results_to_db(
169 self.project_name, self.case_name, self.start_time,
170 self.stop_time, pub_result, self.details):
172 "The results were successfully pushed to DB")
173 return TestCase.EX_OK
175 self.__logger.error("The results cannot be pushed to DB")
176 return TestCase.EX_PUSH_TO_DB_ERROR
177 except Exception: # pylint: disable=broad-except
178 self.__logger.exception("The results cannot be pushed to DB")
179 return TestCase.EX_PUSH_TO_DB_ERROR
181 def create_snapshot(self): # pylint: disable=no-self-use
182 """Save the testing environment before running test.
184 It can be overriden if resources must be listed running the
190 return TestCase.EX_OK
193 """Clean the resources.
195 It can be overriden if resources must be deleted after
196 running the test case.