From bed3ba91560dbef5a3789ec37df67c3de325aa8c Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Mon, 15 Feb 2016 01:58:34 -0500 Subject: [PATCH 1/7] Remove unused code --- seleniumbase/plugins/screen_shots.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/seleniumbase/plugins/screen_shots.py b/seleniumbase/plugins/screen_shots.py index 7074305ede0..ef8152679dd 100755 --- a/seleniumbase/plugins/screen_shots.py +++ b/seleniumbase/plugins/screen_shots.py @@ -16,8 +16,6 @@ class ScreenShots(Plugin): name = "screen_shots" logfile_name = settings.SCREENSHOT_NAME - # Browser windows aren't always maximized. This may display more details. - logfile_name_2 = "full_screenshot.jpg" def options(self, parser, env): super(ScreenShots, self).options(parser, env=env) @@ -34,21 +32,6 @@ def add_screenshot(self, test, err, capt=None, tbinfo=None): os.makedirs(test_logpath) screenshot_file = "%s/%s" % (test_logpath, self.logfile_name) test.driver.get_screenshot_as_file(screenshot_file) - '''try: - # Let humans see any errors on screen before closing the window - test.driver.maximize_window() - import time - time.sleep(0.2) # Make sure the screen is ready - except Exception: - pass - # Second screenshot at fullscreen might not be necessary - # import base64 - screen_b64 = test.driver.get_screenshot_as_base64() - screen = base64.decodestring(screen_b64) - screenshot_file_2 = "%s/%s" % (test_logpath, self.logfile_name_2) - f1 = open(screenshot_file_2, 'w+') - f1.write(screen) - f1.close()''' def addError(self, test, err, capt=None): self.add_screenshot(test, err, capt=capt) From 70945a04b027bd1acb2e3a4d26f6ed5b69f42e9d Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Mon, 15 Feb 2016 02:01:08 -0500 Subject: [PATCH 2/7] Clean up text --- seleniumbase/plugins/db_reporting_plugin.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/seleniumbase/plugins/db_reporting_plugin.py b/seleniumbase/plugins/db_reporting_plugin.py index b25ecdfb7c6..055c2bc917f 100755 --- a/seleniumbase/plugins/db_reporting_plugin.py +++ b/seleniumbase/plugins/db_reporting_plugin.py @@ -24,7 +24,6 @@ class DBReporting(Plugin): name = 'db_reporting' # Usage: --with-db_reporting def __init__(self): - """initialize some variables""" Plugin.__init__(self) self.execution_guid = str(uuid.uuid4()) self.testcase_guid = None @@ -43,14 +42,13 @@ def options(self, parser, env): help=SUPPRESS_HELP) def configure(self, options, conf): - """get the options""" super(DBReporting, self).configure(options, conf) self.options = options self.testcase_manager = TestcaseManager(self.options.database_env) def begin(self): - """At the start of the run, we want to record the - execution information to the database.""" + """At the start of the run, we want to record the test + execution information in the database.""" exec_payload = ExecutionQueryPayload() exec_payload.execution_start_time = int(time.time() * 1000) self.execution_start_time = exec_payload.execution_start_time @@ -59,7 +57,7 @@ def begin(self): self.testcase_manager.insert_execution_data(exec_payload) def startTest(self, test): - """at the start of the test, set the test case details""" + """At the start of the test, set the testcase details.""" data_payload = TestcaseDataPayload() self.testcase_guid = str(uuid.uuid4()) data_payload.guid = self.testcase_guid @@ -80,26 +78,26 @@ def startTest(self, test): def finalize(self, result): """At the end of the run, we want to - update that row with the execution time.""" + update the DB row with the execution time.""" runtime = int(time.time() * 1000) - self.execution_start_time self.testcase_manager.update_execution_data(self.execution_guid, runtime) def addSuccess(self, test, capt): """ - After sucess of a test, we want to record the testcase run information. + After test completion, we want to record testcase run information. """ self.__insert_test_result(constants.State.PASS, test) def addError(self, test, err, capt=None): """ - After error of a test, we want to record the testcase run information. + After a test error, we want to record testcase run information. """ self.__insert_test_result(constants.State.ERROR, test, err) def handleError(self, test, err, capt=None): """ - After error of a test, we want to record the testcase run information. + After a test error, we want to record testcase run information. "Error" also encompasses any states other than Pass or Fail, so we check for those first. """ @@ -123,7 +121,7 @@ def handleError(self, test, err, capt=None): def addFailure(self, test, err, capt=None, tbinfo=None): """ - After failure of a test, we want to record testcase run information. + After a test failure, we want to record testcase run information. """ self.__insert_test_result(constants.State.FAILURE, test, err) From e751b2d2af14c094870ff8753ff5f33248e82c17 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Mon, 15 Feb 2016 02:02:22 -0500 Subject: [PATCH 3/7] Make S3 entry less confusing --- seleniumbase/config/settings.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/seleniumbase/config/settings.py b/seleniumbase/config/settings.py index c1a9d64ce71..b21e3807246 100755 --- a/seleniumbase/config/settings.py +++ b/seleniumbase/config/settings.py @@ -43,11 +43,10 @@ # Amazon S3 Bucket Credentials # (For saving screenshots and other log files from tests) -S3_LOG_BUCKET = "[ENTER LOG BUCKET FOLDER NAME HERE]" -S3_BUCKET_URL = ("http://[ENTER SUBDOMAIN OF AMAZON BUCKET URL HERE]" - ".s3-[ENTER S3 REGION HERE].amazonaws.com/") -S3_SELENIUM_ACCESS_KEY = "[ENTER YOUR S3 ACCESS KEY FOR SELENIUM HERE]" -S3_SELENIUM_SECRET_KEY = "[ENTER YOUR S3 SECRET KEY FOR SELENIUM HERE]" +S3_LOG_BUCKET = "[[S3 BUCKET NAME]]" +S3_BUCKET_URL = ("https://[[S3 BUCKET_NAME]].s3.amazonaws.com/") +S3_SELENIUM_ACCESS_KEY = "[[S3_ACCESS_KEY]]" +S3_SELENIUM_SECRET_KEY = "[[S3_SECRET_KEY]]" # MySQL DB Credentials # (For saving data from tests) From 069123bd9df112d11931aa62784d443e6c026f75 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Mon, 15 Feb 2016 02:04:31 -0500 Subject: [PATCH 4/7] Make the log index file link more noticeable in test output --- seleniumbase/plugins/s3_logging_plugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seleniumbase/plugins/s3_logging_plugin.py b/seleniumbase/plugins/s3_logging_plugin.py index 8b6022db70b..29058e1a930 100755 --- a/seleniumbase/plugins/s3_logging_plugin.py +++ b/seleniumbase/plugins/s3_logging_plugin.py @@ -36,8 +36,8 @@ def afterTest(self, test): uploaded_files.append(logfile_name) s3_bucket.save_uploaded_file_names(uploaded_files) index_file = s3_bucket.upload_index_file(test.id(), guid) - print "Log files uploaded: %s" % index_file - logging.error("Log files uploaded: %s" % index_file) + print "\n\n*** Log files uploaded: ***\n%s\n" % index_file + logging.error("\n\n*** Log files uploaded: ***\n%s\n" % index_file) # If the database plugin is running, attach a link # to the logs index database row From 06bc213758b100b21c4e4d516bff8f5a0856b957 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Mon, 15 Feb 2016 02:05:34 -0500 Subject: [PATCH 5/7] Add S3 logging options to pytest config --- conftest.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/conftest.py b/conftest.py index 88ee2d4adcd..1ba688d0c56 100755 --- a/conftest.py +++ b/conftest.py @@ -44,6 +44,22 @@ def pytest_addoption(parser): choices=('prod', 'qa', 'test'), default='test', help=SUPPRESS_HELP) + parser.addoption('--with-s3_logging', action="store_true", + dest='with_s3_logging', + default=False, + help="Use to save test log files in Amazon S3.") + parser.addoption('--with-screen_shots', action="store_true", + dest='with_screen_shots', + default=False, + help="Use to save screenshots on test failure.") + parser.addoption('--with-basic_test_info', action="store_true", + dest='with_basic_test_info', + default=False, + help="Use to save basic test info on test failure.") + parser.addoption('--with-page_source', action="store_true", + dest='with_page_source', + default=False, + help="Use to save page source on test failure.") parser.addoption('--headless', action="store_true", dest='headless', default=False, @@ -64,6 +80,10 @@ def pytest_configure(config): with_selenium = config.getoption('with_selenium') with_testing_base = config.getoption('with_testing_base') with_db_reporting = config.getoption('with_db_reporting') + with_s3_logging = config.getoption('with_s3_logging') + with_screen_shots = config.getoption('with_screen_shots') + with_basic_test_info = config.getoption('with_basic_test_info') + with_page_source = config.getoption('with_page_source') database_env = config.getoption('database_env') browser = config.getoption('browser') log_path = config.getoption('log_path') @@ -85,6 +105,10 @@ def pytest_configure(config): config_file.write("data:::%s\n" % data) config_file.write("with_testing_base:::%s\n" % with_testing_base) config_file.write("with_db_reporting:::%s\n" % with_db_reporting) + config_file.write("with_s3_logging:::%s\n" % with_s3_logging) + config_file.write("with_screen_shots:::%s\n" % with_screen_shots) + config_file.write("with_basic_test_info:::%s\n" % with_basic_test_info) + config_file.write("with_page_source:::%s\n" % with_page_source) config_file.write("database_env:::%s\n" % database_env) config_file.write("log_path:::%s\n" % log_path) config_file.write("headless:::%s\n" % headless) From 32d7f4de159a7c75de817f3d3db45adda603e3ef Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Mon, 15 Feb 2016 02:06:24 -0500 Subject: [PATCH 6/7] Add S3 logging code to base_case for pytest --- seleniumbase/fixtures/base_case.py | 55 ++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/seleniumbase/fixtures/base_case.py b/seleniumbase/fixtures/base_case.py index 4f5698c8418..c552e0f742f 100755 --- a/seleniumbase/fixtures/base_case.py +++ b/seleniumbase/fixtures/base_case.py @@ -16,6 +16,7 @@ from pyvirtualdisplay import Display from seleniumbase.config import settings from seleniumbase.core.application_manager import ApplicationManager +from seleniumbase.core.s3_manager import S3LoggingBucket from seleniumbase.core.testcase_manager import ExecutionQueryPayload from seleniumbase.core.testcase_manager import TestcaseDataPayload from seleniumbase.core.testcase_manager import TestcaseManager @@ -340,6 +341,11 @@ def setUp(self): self.headless_active = False self.with_testing_base = pytest.config.option.with_testing_base self.with_db_reporting = pytest.config.option.with_db_reporting + self.with_s3_logging = pytest.config.option.with_s3_logging + self.with_screen_shots = pytest.config.option.with_screen_shots + self.with_basic_test_info = ( + pytest.config.option.with_basic_test_info) + self.with_page_source = pytest.config.option.with_page_source self.database_env = pytest.config.option.database_env self.log_path = pytest.config.option.log_path self.browser = pytest.config.option.browser @@ -416,13 +422,24 @@ def tearDown(self): test_logpath = self.log_path + "/" + test_id if not os.path.exists(test_logpath): os.makedirs(test_logpath) - # Handle screenshot logging - log_helper.log_screenshot(test_logpath, self.driver) - # Handle basic test info logging - log_helper.log_test_failure_data( - test_logpath, self.driver, self.browser) - # Handle page source logging - log_helper.log_page_source(test_logpath, self.driver) + if ((not self.with_screen_shots) and + (not self.with_basic_test_info) and + (not self.with_page_source)): + # Log everything if nothing specified (if testing_base) + log_helper.log_screenshot(test_logpath, self.driver) + log_helper.log_test_failure_data( + test_logpath, self.driver, self.browser) + log_helper.log_page_source(test_logpath, self.driver) + else: + if self.with_screen_shots: + log_helper.log_screenshot( + test_logpath, self.driver) + if self.with_basic_test_info: + log_helper.log_test_failure_data( + test_logpath, self.driver, self.browser) + if self.with_page_source: + log_helper.log_page_source( + test_logpath, self.driver) # Finally close the browser self.driver.quit() if self.headless: @@ -436,3 +453,27 @@ def tearDown(self): runtime = int(time.time() * 1000) - self.execution_start_time self.testcase_manager.update_execution_data( self.execution_guid, runtime) + if self.with_s3_logging and (sys.exc_info()[1] is not None): + """ After each testcase, upload logs to the S3 bucket. """ + s3_bucket = S3LoggingBucket() + guid = str(uuid.uuid4().hex) + path = "%s/%s" % (self.log_path, test_id) + uploaded_files = [] + for logfile in os.listdir(path): + logfile_name = "%s/%s/%s" % (guid, + test_id, + logfile.split(path)[-1]) + s3_bucket.upload_file(logfile_name, + "%s/%s" % (path, logfile)) + uploaded_files.append(logfile_name) + s3_bucket.save_uploaded_file_names(uploaded_files) + index_file = s3_bucket.upload_index_file(test_id, guid) + print "\n\n*** Log files uploaded: ***\n%s\n" % index_file + logging.error( + "\n\n*** Log files uploaded: ***\n%s\n" % index_file) + if self.with_db_reporting: + self.testcase_manager = TestcaseManager(self.database_env) + data_payload = TestcaseDataPayload() + data_payload.guid = guid + data_payload.logURL = index_file + self.testcase_manager.update_testcase_log_url(data_payload) From 807db4955174768e9f5a4cd60c1e5d1a76656d12 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Mon, 15 Feb 2016 02:08:18 -0500 Subject: [PATCH 7/7] Version 1.1.25 --- integrations/docker/docker_setup.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/integrations/docker/docker_setup.py b/integrations/docker/docker_setup.py index b2b2c622178..96f200571ae 100755 --- a/integrations/docker/docker_setup.py +++ b/integrations/docker/docker_setup.py @@ -8,7 +8,7 @@ setup( name='seleniumbase', - version='1.1.24', + version='1.1.25', author='Michael Mintz', author_email='@mintzworld', maintainer='Michael Mintz', diff --git a/setup.py b/setup.py index 738d2cb275a..507f1dfa46f 100755 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ setup( name='seleniumbase', - version='1.1.24', + version='1.1.25', url='https://github.com/mdmintz/SeleniumBase', author='Michael Mintz', author_email='@mintzworld',