Define logger as Feature instance attribute
[functest.git] / functest / core / feature.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2016 ZTE Corp 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 parent classes of all Functest Features.
11
12 Feature is considered as TestCase offered by Third-party. It offers
13 helpers to run any python method or any bash command.
14 """
15
16 import logging
17 import time
18
19 import functest.core.testcase as base
20 import functest.utils.functest_utils as ft_utils
21 from functest.utils.constants import CONST
22
23 __author__ = ("Serena Feng <feng.xiaowei@zte.com.cn>, "
24               "Cedric Ollivier <cedric.ollivier@orange.com>")
25
26
27 class Feature(base.TestCase):
28     """Base model for single feature."""
29
30     __logger = logging.getLogger(__name__)
31
32     def __init__(self, **kwargs):
33         super(Feature, self).__init__(**kwargs)
34         self.result_file = "{}/{}.log".format(
35             CONST.__getattribute__('dir_results'), self.case_name)
36         try:
37             module = kwargs['run']['module']
38             self.logger = logging.getLogger(module)
39         except KeyError:
40             self.__logger.warning(
41                 "Cannot get module name %s. Using %s as fallback",
42                 kwargs, self.case_name)
43             self.logger = logging.getLogger(self.case_name)
44         handler = logging.StreamHandler()
45         handler.setLevel(logging.WARN)
46         self.logger.addHandler(handler)
47         handler = logging.FileHandler(self.result_file)
48         handler.setLevel(logging.DEBUG)
49         self.logger.addHandler(handler)
50         formatter = logging.Formatter(
51             '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
52         handler.setFormatter(formatter)
53         self.logger.addHandler(handler)
54
55     def execute(self, **kwargs):
56         """Execute the Python method.
57
58         The subclasses must override the default implementation which
59         is false on purpose.
60
61         The new implementation must return 0 if success or anything
62         else if failure.
63
64         Args:
65             kwargs: Arbitrary keyword arguments.
66
67         Returns:
68             -1.
69         """
70         # pylint: disable=unused-argument,no-self-use
71         return -1
72
73     def run(self, **kwargs):
74         """Run the feature.
75
76         It allows executing any Python method by calling execute().
77
78         It sets the following attributes required to push the results
79         to DB:
80
81             * result,
82             * start_time,
83             * stop_time.
84
85         It doesn't fulfill details when pushing the results to the DB.
86
87         Args:
88             kwargs: Arbitrary keyword arguments.
89
90         Returns:
91             TestCase.EX_OK if execute() returns 0,
92             TestCase.EX_RUN_ERROR otherwise.
93         """
94         self.start_time = time.time()
95         exit_code = base.TestCase.EX_RUN_ERROR
96         self.result = 0
97         try:
98             if self.execute(**kwargs) == 0:
99                 exit_code = base.TestCase.EX_OK
100                 self.result = 100
101             ft_utils.logger_test_results(
102                 self.project_name, self.case_name,
103                 self.result, self.details)
104         except Exception:  # pylint: disable=broad-except
105             self.__logger.exception("%s FAILED", self.project_name)
106         self.__logger.info("Test result is stored in '%s'", self.result_file)
107         self.stop_time = time.time()
108         return exit_code
109
110
111 class BashFeature(Feature):
112     """Class designed to run any bash command."""
113
114     __logger = logging.getLogger(__name__)
115
116     def execute(self, **kwargs):
117         """Execute the cmd passed as arg
118
119         Args:
120             kwargs: Arbitrary keyword arguments.
121
122         Returns:
123             0 if cmd returns 0,
124             -1 otherwise.
125         """
126         ret = -1
127         try:
128             cmd = kwargs["cmd"]
129             ret = ft_utils.execute_command(cmd, output_file=self.result_file)
130         except KeyError:
131             self.__logger.error("Please give cmd as arg. kwargs: %s", kwargs)
132         except Exception:  # pylint: disable=broad-except
133             self.__logger.exception("Execute cmd: %s failed", cmd)
134         return ret