aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCédric Ollivier <cedric.ollivier@orange.com>2019-11-09 12:28:24 +0100
committerCédric Ollivier <cedric.ollivier@orange.com>2021-02-09 19:22:35 +0100
commitf772dee4da63faddd34fcaf8a9c97b1c67d9dfe9 (patch)
treedfde600527ea50653e978df65e283cf9e792cf5c
parent115092d35fdf9b449ff91e36cc2d668d39a8b257 (diff)
Generate Html and Xunit Behave reports
Change-Id: I7d5f31502ba61b61a0b1c885fe8828211bc0bc0a Signed-off-by: Cédric Ollivier <cedric.ollivier@orange.com> (cherry picked from commit 728f5c95df4d3edbe6b3f814a270cdf3b532aef9)
-rw-r--r--requirements.txt1
-rw-r--r--upper-constraints.txt2
-rw-r--r--xtesting/core/behaveframework.py40
-rw-r--r--xtesting/tests/unit/core/test_behaveframework.py76
4 files changed, 64 insertions, 55 deletions
diff --git a/requirements.txt b/requirements.txt
index 5ea71168..ea776baf 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,6 +8,7 @@ enum34;python_version=='2.7' or python_version=='2.6' or python_version=='3.3' #
requests!=2.20.0 # Apache-2.0
robotframework>=3.0
behave>=1.2.6
+behave-html-formatter>=0.9.4;python_version>='3.5'
mock # BSD
PrettyTable<0.8 # BSD
six # MIT
diff --git a/upper-constraints.txt b/upper-constraints.txt
index b7c0086f..1867de9f 100644
--- a/upper-constraints.txt
+++ b/upper-constraints.txt
@@ -1,5 +1,7 @@
robotframework===3.0.2
bandit===1.1.0
+behave===1.2.6
+behave-html-formatter===0.9.4;python_version>='3.5'
pylint===1.9.5;python_version=='2.7'
pylint===2.3.1;python_version=='3.6'
boto3===1.7.62
diff --git a/xtesting/core/behaveframework.py b/xtesting/core/behaveframework.py
index d8a61ef3..2b41614c 100644
--- a/xtesting/core/behaveframework.py
+++ b/xtesting/core/behaveframework.py
@@ -14,7 +14,9 @@ from __future__ import division
import logging
import os
import time
+
import json
+import six
from behave.__main__ import main as behave_main
@@ -32,7 +34,6 @@ class BehaveFramework(testcase.TestCase):
def __init__(self, **kwargs):
super(BehaveFramework, self).__init__(**kwargs)
- self.res_dir = os.path.join(self.dir_results, self.case_name)
self.json_file = os.path.join(self.res_dir, 'output.json')
self.total_tests = 0
self.pass_tests = 0
@@ -42,14 +43,8 @@ class BehaveFramework(testcase.TestCase):
def parse_results(self):
"""Parse output.json and get the details in it."""
-
- try:
- with open(self.json_file) as stream_:
- self.response = json.load(stream_)
- except IOError:
- self.__logger.error("Error reading the file %s", self.json_file)
-
- try:
+ with open(self.json_file) as stream_:
+ self.response = json.load(stream_)
if self.response:
self.total_tests = len(self.response)
for item in self.response:
@@ -59,21 +54,14 @@ class BehaveFramework(testcase.TestCase):
self.fail_tests += 1
elif item['status'] == 'skipped':
self.skip_tests += 1
- except KeyError:
- self.__logger.error("Error in json - %s", self.response)
-
- try:
self.result = 100 * (
self.pass_tests / self.total_tests)
- except ZeroDivisionError:
- self.__logger.error("No test has been run")
-
- self.details = {}
- self.details['total_tests'] = self.total_tests
- self.details['pass_tests'] = self.pass_tests
- self.details['fail_tests'] = self.fail_tests
- self.details['skip_tests'] = self.skip_tests
- self.details['tests'] = self.response
+ self.details = {}
+ self.details['total_tests'] = self.total_tests
+ self.details['pass_tests'] = self.pass_tests
+ self.details['fail_tests'] = self.fail_tests
+ self.details['skip_tests'] = self.skip_tests
+ self.details['tests'] = self.response
def run(self, **kwargs):
"""Run the BehaveFramework feature files
@@ -103,8 +91,12 @@ class BehaveFramework(testcase.TestCase):
self.__logger.exception("Cannot create %s", self.res_dir)
return self.EX_RUN_ERROR
config = ['--tags='+','.join(tags),
- '--format=json',
- '--outfile='+self.json_file]
+ '--junit', '--junit-directory={}'.format(self.res_dir),
+ '--format=json', '--outfile={}'.format(self.json_file)]
+ if six.PY3:
+ html_file = os.path.join(self.res_dir, 'output.html')
+ config += ['--format=behave_html_formatter:HTMLFormatter',
+ '--outfile={}'.format(html_file)]
for feature in suites:
config.append(feature)
self.start_time = time.time()
diff --git a/xtesting/tests/unit/core/test_behaveframework.py b/xtesting/tests/unit/core/test_behaveframework.py
index f18cac03..414d96b5 100644
--- a/xtesting/tests/unit/core/test_behaveframework.py
+++ b/xtesting/tests/unit/core/test_behaveframework.py
@@ -10,9 +10,12 @@
"""Define the classes required to fully cover behave."""
import logging
+import os
import unittest
import mock
+import six
+
from xtesting.core import behaveframework
__author__ = "Deepak Chandella <deepak.chandella@orange.com>"
@@ -29,28 +32,27 @@ class ParseResultTesting(unittest.TestCase):
self.test = behaveframework.BehaveFramework(
case_name='behave', project_name='xtesting')
- def test_raises_exc_open(self):
- self.test.json_file = 'dummy_file'
- self.test.response = self._response
- with mock.patch('six.moves.builtins.open',
- mock.mock_open()) as mock_file:
- mock_file.side_effect = IOError()
- self.assertRaises(IOError, self.test.parse_results())
- mock_file.assert_called_once_with('dummy_file')
+ @mock.patch('six.moves.builtins.open', side_effect=OSError)
+ def test_raises_exc_open(self, *args): # pylint: disable=unused-argument
+ with self.assertRaises(OSError):
+ self.test.parse_results()
- def test_raises_exc_key(self):
- with mock.patch('six.moves.builtins.open', mock.mock_open()), \
- mock.patch('json.load', return_value=[{'foo': 'bar'}]):
- self.assertRaises(KeyError, self.test.parse_results())
+ @mock.patch('json.load', return_value=[{'foo': 'bar'}])
+ @mock.patch('six.moves.builtins.open', mock.mock_open())
+ def test_raises_exc_key(self, *args): # pylint: disable=unused-argument
+ with self.assertRaises(KeyError):
+ self.test.parse_results()
- def test_raises_exe_zerodivision(self):
- with mock.patch('six.moves.builtins.open', mock.mock_open()), \
- mock.patch('json.load', mock.Mock(return_value=[])):
- self.assertRaises(ZeroDivisionError, self.test.parse_results())
+ @mock.patch('json.load', return_value=[])
+ @mock.patch('six.moves.builtins.open', mock.mock_open())
+ def test_raises_exe_zerodivision(self, *args):
+ # pylint: disable=unused-argument
+ with self.assertRaises(ZeroDivisionError):
+ self.test.parse_results()
def _test_result(self, response, result):
with mock.patch('six.moves.builtins.open', mock.mock_open()), \
- mock.patch('json.load', mock.Mock(return_value=response)):
+ mock.patch('json.load', return_value=response):
self.test.parse_results()
self.assertEqual(self.test.result, result)
@@ -66,11 +68,10 @@ class ParseResultTesting(unittest.TestCase):
data = [{'status': 'passed'}, {'status': 'passed'}]
self._test_result(data, 100)
- def test_count(self):
+ @mock.patch('six.moves.builtins.open', mock.mock_open())
+ def test_count(self, *args): # pylint: disable=unused-argument
self._response.extend([{'status': 'failed'}, {'status': 'skipped'}])
- with mock.patch('six.moves.builtins.open', mock.mock_open()), \
- mock.patch('json.load', mock.Mock(
- return_value=self._response)):
+ with mock.patch('json.load', mock.Mock(return_value=self._response)):
self.test.parse_results()
self.assertEqual(self.test.details['pass_tests'], 1)
self.assertEqual(self.test.details['fail_tests'], 1)
@@ -116,11 +117,17 @@ class RunTesting(unittest.TestCase):
self.assertEqual(
self.test.run(suites=self.suites, tags=self.tags),
self.test.EX_OK)
- args[0].assert_called_once_with(
- ['--tags=',
- '--format=json',
- '--outfile={}'.format(self.test.json_file),
- 'foo'])
+ html_file = os.path.join(self.test.res_dir, 'output.html')
+ args_list = [
+ '--tags=', '--junit',
+ '--junit-directory={}'.format(self.test.res_dir),
+ '--format=json', '--outfile={}'.format(self.test.json_file)]
+ if six.PY3:
+ args_list += [
+ '--format=behave_html_formatter:HTMLFormatter',
+ '--outfile={}'.format(html_file)]
+ args_list.append('foo')
+ args[0].assert_called_once_with(args_list)
mock_method.assert_called_once_with()
@mock.patch('os.makedirs')
@@ -144,11 +151,17 @@ class RunTesting(unittest.TestCase):
self.test.run(
suites=self.suites, tags=self.tags),
status)
- args[0].assert_called_once_with(
- ['--tags=',
- '--format=json',
- '--outfile={}'.format(self.test.json_file),
- 'foo'])
+ html_file = os.path.join(self.test.res_dir, 'output.html')
+ args_list = [
+ '--tags=', '--junit',
+ '--junit-directory={}'.format(self.test.res_dir),
+ '--format=json', '--outfile={}'.format(self.test.json_file)]
+ if six.PY3:
+ args_list += [
+ '--format=behave_html_formatter:HTMLFormatter',
+ '--outfile={}'.format(html_file)]
+ args_list.append('foo')
+ args[0].assert_called_once_with(args_list)
args[1].assert_called_once_with(self.test.res_dir)
def test_parse_results_exc(self):
@@ -157,6 +170,7 @@ class RunTesting(unittest.TestCase):
self._test_parse_results(self.test.EX_RUN_ERROR)
mock_method.assert_called_once_with()
+
if __name__ == "__main__":
logging.disable(logging.CRITICAL)
unittest.main(verbosity=2)