2 # Copyright 2021 Orange
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
8 # http://www.apache.org/licenses/LICENSE-2.0
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
17 """Define classes required to run any Behave test suites."""
19 from __future__ import division
28 from behave.__main__ import main as behave_main
30 from xtesting.core import testcase
32 __author__ = "Deepak Chandella <deepak.chandella@orange.com>"
35 class BehaveFramework(testcase.TestCase):
36 """BehaveFramework runner."""
37 # pylint: disable=too-many-instance-attributes
39 __logger = logging.getLogger(__name__)
40 dir_results = "/var/lib/xtesting/results"
42 def __init__(self, **kwargs):
43 super().__init__(**kwargs)
44 self.json_file = os.path.join(self.res_dir, 'output.json')
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_)
56 self.total_tests = len(self.response)
57 for item in self.response:
58 if item['status'] == 'passed':
60 elif item['status'] == 'failed':
62 elif item['status'] == 'skipped':
65 self.pass_tests / self.total_tests)
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
73 def run(self, **kwargs):
74 """Run the BehaveFramework feature files
77 * create the output directories if required,
78 * run behave features with parameters
79 * get the results in output.json,
82 kwargs: Arbitrary keyword arguments.
85 EX_OK if all suites ran well.
86 EX_RUN_ERROR otherwise.
89 suites = kwargs["suites"]
90 tags = kwargs.get("tags", [])
91 console = kwargs["console"] if "console" in kwargs else False
93 self.__logger.exception("Mandatory args were not passed")
94 return self.EX_RUN_ERROR
95 if not os.path.exists(self.res_dir):
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)]
105 html_file = os.path.join(self.res_dir, 'output.html')
106 config += ['--format=behave_html_formatter:HTMLFormatter',
107 '--outfile={}'.format(html_file)]
109 config += ['--format=pretty',
111 for feature in suites:
112 config.append(feature)
113 self.start_time = time.time()
115 self.stop_time = time.time()
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