NFVBENCH-205 - Add behave tests for characterization and non-regression
[nfvbench.git] / xtesting / behaveframework.py
1 #!/usr/bin/env python
2 # Copyright 2021 Orange
3 #
4 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
5 #    not use this file except in compliance with the License. You may obtain
6 #    a copy of the License at
7 #
8 #         http://www.apache.org/licenses/LICENSE-2.0
9 #
10 #    Unless required by applicable law or agreed to in writing, software
11 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 #    License for the specific language governing permissions and limitations
14 #    under the License.
15 #
16
17 """Define classes required to run any Behave test suites."""
18
19 from __future__ import division
20
21 import logging
22 import os
23 import time
24
25 import json
26 import six
27
28 from behave.__main__ import main as behave_main
29
30 from xtesting.core import testcase
31
32 __author__ = "Deepak Chandella <deepak.chandella@orange.com>"
33
34
35 class BehaveFramework(testcase.TestCase):
36     """BehaveFramework runner."""
37     # pylint: disable=too-many-instance-attributes
38
39     __logger = logging.getLogger(__name__)
40     dir_results = "/var/lib/xtesting/results"
41
42     def __init__(self, **kwargs):
43         super().__init__(**kwargs)
44         self.json_file = os.path.join(self.res_dir, 'output.json')
45         self.total_tests = 0
46         self.pass_tests = 0
47         self.fail_tests = 0
48         self.skip_tests = 0
49         self.response = None
50
51     def parse_results(self):
52         """Parse output.json and get the details in it."""
53         with open(self.json_file) as stream_:
54             self.response = json.load(stream_)
55             if self.response:
56                 self.total_tests = len(self.response)
57             for item in self.response:
58                 if item['status'] == 'passed':
59                     self.pass_tests += 1
60                 elif item['status'] == 'failed':
61                     self.fail_tests += 1
62                 elif item['status'] == 'skipped':
63                     self.skip_tests += 1
64             self.result = 100 * (
65                 self.pass_tests / self.total_tests)
66             self.details = {}
67             self.details['total_tests'] = self.total_tests
68             self.details['pass_tests'] = self.pass_tests
69             self.details['fail_tests'] = self.fail_tests
70             self.details['skip_tests'] = self.skip_tests
71             self.details['tests'] = self.response
72
73     def run(self, **kwargs):
74         """Run the BehaveFramework feature files
75
76         Here are the steps:
77            * create the output directories if required,
78            * run behave features with parameters
79            * get the results in output.json,
80
81         Args:
82             kwargs: Arbitrary keyword arguments.
83
84         Returns:
85             EX_OK if all suites ran well.
86             EX_RUN_ERROR otherwise.
87         """
88         try:
89             suites = kwargs["suites"]
90             tags = kwargs.get("tags", [])
91             console = kwargs["console"] if "console" in kwargs else False
92         except KeyError:
93             self.__logger.exception("Mandatory args were not passed")
94             return self.EX_RUN_ERROR
95         if not os.path.exists(self.res_dir):
96             try:
97                 os.makedirs(self.res_dir)
98             except Exception:  # pylint: disable=broad-except
99                 self.__logger.exception("Cannot create %s", self.res_dir)
100                 return self.EX_RUN_ERROR
101         config = ['--tags=' + ','.join(tags),
102                   '--junit', '--junit-directory={}'.format(self.res_dir),
103                   '--format=json', '--outfile={}'.format(self.json_file)]
104         if six.PY3:
105             html_file = os.path.join(self.res_dir, 'output.html')
106             config += ['--format=behave_html_formatter:HTMLFormatter',
107                        '--outfile={}'.format(html_file)]
108         if console:
109             config += ['--format=pretty',
110                        '--outfile=-']
111         for feature in suites:
112             config.append(feature)
113         self.start_time = time.time()
114         behave_main(config)
115         self.stop_time = time.time()
116
117         try:
118             self.parse_results()
119             self.__logger.info("Results were successfully parsed")
120         except Exception:  # pylint: disable=broad-except
121             self.__logger.exception("Cannot parse results")
122             return self.EX_RUN_ERROR
123         return self.EX_OK