Correct documented return values
[functest-xtesting.git] / xtesting / core / behaveframework.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2019 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 classes required to run any Behave test suites."""
11
12 from __future__ import division
13
14 import logging
15 import os
16 import time
17
18 import json
19
20 from behave.__main__ import main as behave_main
21
22 from xtesting.core import testcase
23
24 __author__ = "Deepak Chandella <deepak.chandella@orange.com>"
25
26
27 class BehaveFramework(testcase.TestCase):
28     """BehaveFramework runner."""
29     # pylint: disable=too-many-instance-attributes
30
31     __logger = logging.getLogger(__name__)
32
33     def __init__(self, **kwargs):
34         super().__init__(**kwargs)
35         self.json_file = os.path.join(self.res_dir, 'output.json')
36         self.total_tests = 0
37         self.pass_tests = 0
38         self.fail_tests = 0
39         self.skip_tests = 0
40         self.response = None
41
42     def parse_results(self):
43         """Parse output.json and get the details in it."""
44         with open(self.json_file) as stream_:
45             self.response = json.load(stream_)
46             if self.response:
47                 self.total_tests = len(self.response)
48             for item in self.response:
49                 if item['status'] == 'passed':
50                     self.pass_tests += 1
51                 elif item['status'] == 'failed':
52                     self.fail_tests += 1
53                 elif item['status'] == 'skipped':
54                     self.skip_tests += 1
55             self.result = 100 * (
56                 self.pass_tests / self.total_tests)
57             self.details = {}
58             self.details['total_tests'] = self.total_tests
59             self.details['pass_tests'] = self.pass_tests
60             self.details['fail_tests'] = self.fail_tests
61             self.details['skip_tests'] = self.skip_tests
62             self.details['tests'] = self.response
63
64     def run(self, **kwargs):
65         """Run the BehaveFramework feature files
66
67         Here are the steps:
68            * create the output directories if required,
69            * run behave features with parameters
70            * get the results in output.json,
71
72         Args:
73             kwargs: Arbitrary keyword arguments.
74
75         Returns:
76             EX_OK if all suites ran well.
77             EX_RUN_ERROR otherwise.
78         """
79         try:
80             suites = kwargs["suites"]
81         except KeyError:
82             self.__logger.exception("Mandatory args were not passed")
83             return self.EX_RUN_ERROR
84         if not os.path.exists(self.res_dir):
85             try:
86                 os.makedirs(self.res_dir)
87             except Exception:  # pylint: disable=broad-except
88                 self.__logger.exception("Cannot create %s", self.res_dir)
89                 return self.EX_RUN_ERROR
90         config = ['--junit', '--junit-directory={}'.format(self.res_dir),
91                   '--format=json', '--outfile={}'.format(self.json_file)]
92         html_file = os.path.join(self.res_dir, 'output.html')
93         config += ['--format=behave_html_formatter:HTMLFormatter',
94                    '--outfile={}'.format(html_file)]
95         if kwargs.get("tags", False):
96             config += ['--tags='+','.join(kwargs.get("tags", []))]
97         if kwargs.get("console", False):
98             config += ['--format=pretty', '--outfile=-']
99         for feature in suites:
100             config.append(feature)
101         self.start_time = time.time()
102         behave_main(config)
103         self.stop_time = time.time()
104
105         try:
106             self.parse_results()
107             self.__logger.info("Results were successfully parsed")
108         except Exception:  # pylint: disable=broad-except
109             self.__logger.exception("Cannot parse results")
110             return self.EX_RUN_ERROR
111         return self.EX_OK