Attach test logs individually for each test

Reports-Example: Ic35c95e720211bce8659baeb0cd4470308e25ea4

Change-Id: Ie5d972d2a560d4f59666c49dc3bf22fdb48071e8
Depends-On: I124973d9adbaaacf5d3429e6f6684f15de27dc7f
Closes-Bug: #1572999
This commit is contained in:
Sergei Chipiga 2016-04-19 18:31:08 +03:00
parent 4ec8b211f6
commit 4619696ec4
2 changed files with 62 additions and 46 deletions

View File

@ -11,8 +11,9 @@
# under the License.
import contextlib
import datetime
import logging
import os
from six import StringIO
import socket
import tempfile
import time
@ -30,6 +31,8 @@ from openstack_dashboard.test.integration_tests import config
from openstack_dashboard.test.integration_tests.pages import loginpage
from openstack_dashboard.test.integration_tests.regions import messages
LOGGER = logging.getLogger()
LOGGER.setLevel(logging.DEBUG)
ROOT_PATH = os.path.dirname(os.path.abspath(config.__file__))
@ -80,6 +83,8 @@ class BaseTestCase(testtools.TestCase):
CONFIG = config.get_config()
def setUp(self):
self._configure_log()
if not os.environ.get('INTEGRATION_TESTS', False):
msg = "The INTEGRATION_TESTS env variable is not set."
raise self.skipException(msg)
@ -118,22 +123,65 @@ class BaseTestCase(testtools.TestCase):
self.driver.implicitly_wait(self.CONFIG.selenium.implicit_wait)
self.driver.set_page_load_timeout(
self.CONFIG.selenium.page_timeout)
self.addOnException(self._dump_page_html_source)
self.addOnException(self._dump_browser_log)
self.addOnException(self._save_screenshot)
self.addOnException(self._attach_page_source)
self.addOnException(self._attach_screenshot)
self.addOnException(self._attach_browser_log)
self.addOnException(self._attach_test_log)
super(BaseTestCase, self).setUp()
def _configure_log(self):
"""Configure log to capture test logs include selenium logs in order
to attach them if test will be broken.
"""
LOGGER.handlers[:] = [] # clear other handlers to set target handler
self._log_buffer = StringIO()
stream_handler = logging.StreamHandler(stream=self._log_buffer)
stream_handler.setLevel(logging.DEBUG)
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s')
stream_handler.setFormatter(formatter)
LOGGER.addHandler(stream_handler)
@property
def _test_report_dir(self):
report_dir = os.path.join(ROOT_PATH, 'test_reports',
self._testMethodName)
if not os.path.isdir(report_dir):
os.makedirs(report_dir)
return report_dir
def _attach_page_source(self, exc_info):
source_path = os.path.join(self._test_report_dir, 'page.html')
with self.log_exception("Attach page source"):
with open(source_path, 'w') as f:
f.write(self._get_page_html_source())
def _attach_screenshot(self, exc_info):
screen_path = os.path.join(self._test_report_dir, 'screenshot.png')
with self.log_exception("Attach screenshot"):
self.driver.get_screenshot_as_file(screen_path)
def _attach_browser_log(self, exc_info):
browser_log_path = os.path.join(self._test_report_dir, 'browser.log')
with self.log_exception("Attach browser log"):
with open(browser_log_path, 'w') as f:
f.write(
self._unwrap_browser_log(self.driver.get_log('browser')))
def _attach_test_log(self, exc_info):
test_log_path = os.path.join(self._test_report_dir, 'test.log')
with self.log_exception("Attach test log"):
with open(test_log_path, 'w') as f:
f.write(self._log_buffer.getvalue().encode('utf-8'))
@contextlib.contextmanager
def exceptions_captured(self, label):
contents = []
def log_exception(self, label):
try:
yield contents
yield
except Exception:
exc_traceback = traceback.format_exc()
contents.append(testtools.content.text_content(exc_traceback))
finally:
self.addDetail(label, contents[0])
self.addDetail(
label, testtools.content.text_content(traceback.format_exc()))
@staticmethod
def _unwrap_browser_log(_log):
@ -146,20 +194,6 @@ class BaseTestCase(testtools.TestCase):
return log.encode('utf-8')
return rec(_log)
def _dump_browser_log(self, exc_info):
with self.exceptions_captured("BrowserLog.text") as contents:
log = self.driver.get_log('browser')
contents.append(testtools.content.Content(
testtools.content_type.UTF8_TEXT,
lambda: self._unwrap_browser_log(log)))
def _dump_page_html_source(self, exc_info):
with self.exceptions_captured("PageHTMLSource.html") as contents:
pg_source = self._get_page_html_source()
contents.append(testtools.content.Content(
testtools.content_type.ContentType('text', 'html'),
lambda: pg_source))
def zoom_out(self, times=3):
"""Zooming out prevents different elements being driven out of xvfb
viewport (which in Selenium>=2.50.1 prevents interaction with them.
@ -171,24 +205,6 @@ class BaseTestCase(testtools.TestCase):
keys.Keys.CONTROL).send_keys(*zoom_out_keys).key_up(
keys.Keys.CONTROL).perform()
def _save_screenshot(self, exc_info):
with self.exceptions_captured("Screenshot") as contents:
filename = self._get_screenshot_filename()
self.driver.get_screenshot_as_file(filename)
contents.append(testtools.content.text_content(filename))
def _get_screenshot_filename(self):
screenshot_dir = os.path.join(
ROOT_PATH,
self.CONFIG.selenium.screenshots_directory)
if not os.path.exists(screenshot_dir):
os.makedirs(screenshot_dir)
date_string = datetime.datetime.now().strftime(
'%Y.%m.%d-%H%M%S')
test_name = self._testMethodName
name = '%s_%s.png' % (test_name, date_string)
return os.path.join(screenshot_dir, name)
def _get_page_html_source(self):
"""Gets html page source.
@ -196,7 +212,7 @@ class BaseTestCase(testtools.TestCase):
display html code generated/changed by javascript.
"""
html_elem = self.driver.find_element_by_tag_name("html")
return html_elem.get_attribute("innerHTML").encode("UTF-8")
return html_elem.get_attribute("innerHTML").encode("utf-8")
def tearDown(self):
if os.environ.get('INTEGRATION_TESTS', False):

View File

@ -8,8 +8,8 @@ cd /opt/stack/new/horizon
sudo -H -u stack tox -e py27integration
retval=$?
if [ -d openstack_dashboard/test/integration_tests/integration_tests_screenshots/ ]; then
cp -r openstack_dashboard/test/integration_tests/integration_tests_screenshots/ /home/jenkins/workspace/gate-horizon-dsvm-integration/
if [ -d openstack_dashboard/test/integration_tests/test_reports/ ]; then
cp -r openstack_dashboard/test/integration_tests/test_reports/ /home/jenkins/workspace/gate-horizon-dsvm-integration/
fi
exit $retval