Merge "Attach test logs individually for each test"
This commit is contained in:
commit
64bbb52261
@ -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):
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user