Skip to content

Commit b96361a

Browse files
committed
Merge pull request #14 from mdmintz/s3-plugin-for-pytest
S3 plugin for pytest
2 parents e4346c0 + 807db49 commit b96361a

File tree

8 files changed

+88
-43
lines changed

8 files changed

+88
-43
lines changed

conftest.py

+24
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,22 @@ def pytest_addoption(parser):
4444
choices=('prod', 'qa', 'test'),
4545
default='test',
4646
help=SUPPRESS_HELP)
47+
parser.addoption('--with-s3_logging', action="store_true",
48+
dest='with_s3_logging',
49+
default=False,
50+
help="Use to save test log files in Amazon S3.")
51+
parser.addoption('--with-screen_shots', action="store_true",
52+
dest='with_screen_shots',
53+
default=False,
54+
help="Use to save screenshots on test failure.")
55+
parser.addoption('--with-basic_test_info', action="store_true",
56+
dest='with_basic_test_info',
57+
default=False,
58+
help="Use to save basic test info on test failure.")
59+
parser.addoption('--with-page_source', action="store_true",
60+
dest='with_page_source',
61+
default=False,
62+
help="Use to save page source on test failure.")
4763
parser.addoption('--headless', action="store_true",
4864
dest='headless',
4965
default=False,
@@ -64,6 +80,10 @@ def pytest_configure(config):
6480
with_selenium = config.getoption('with_selenium')
6581
with_testing_base = config.getoption('with_testing_base')
6682
with_db_reporting = config.getoption('with_db_reporting')
83+
with_s3_logging = config.getoption('with_s3_logging')
84+
with_screen_shots = config.getoption('with_screen_shots')
85+
with_basic_test_info = config.getoption('with_basic_test_info')
86+
with_page_source = config.getoption('with_page_source')
6787
database_env = config.getoption('database_env')
6888
browser = config.getoption('browser')
6989
log_path = config.getoption('log_path')
@@ -85,6 +105,10 @@ def pytest_configure(config):
85105
config_file.write("data:::%s\n" % data)
86106
config_file.write("with_testing_base:::%s\n" % with_testing_base)
87107
config_file.write("with_db_reporting:::%s\n" % with_db_reporting)
108+
config_file.write("with_s3_logging:::%s\n" % with_s3_logging)
109+
config_file.write("with_screen_shots:::%s\n" % with_screen_shots)
110+
config_file.write("with_basic_test_info:::%s\n" % with_basic_test_info)
111+
config_file.write("with_page_source:::%s\n" % with_page_source)
88112
config_file.write("database_env:::%s\n" % database_env)
89113
config_file.write("log_path:::%s\n" % log_path)
90114
config_file.write("headless:::%s\n" % headless)

integrations/docker/docker_setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
setup(
1010
name='seleniumbase',
11-
version='1.1.24',
11+
version='1.1.25',
1212
author='Michael Mintz',
1313
author_email='@mintzworld',
1414
maintainer='Michael Mintz',

seleniumbase/config/settings.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,10 @@
4343

4444
# Amazon S3 Bucket Credentials
4545
# (For saving screenshots and other log files from tests)
46-
S3_LOG_BUCKET = "[ENTER LOG BUCKET FOLDER NAME HERE]"
47-
S3_BUCKET_URL = ("http://[ENTER SUBDOMAIN OF AMAZON BUCKET URL HERE]"
48-
".s3-[ENTER S3 REGION HERE].amazonaws.com/")
49-
S3_SELENIUM_ACCESS_KEY = "[ENTER YOUR S3 ACCESS KEY FOR SELENIUM HERE]"
50-
S3_SELENIUM_SECRET_KEY = "[ENTER YOUR S3 SECRET KEY FOR SELENIUM HERE]"
46+
S3_LOG_BUCKET = "[[S3 BUCKET NAME]]"
47+
S3_BUCKET_URL = ("https://[[S3 BUCKET_NAME]].s3.amazonaws.com/")
48+
S3_SELENIUM_ACCESS_KEY = "[[S3_ACCESS_KEY]]"
49+
S3_SELENIUM_SECRET_KEY = "[[S3_SECRET_KEY]]"
5150

5251
# MySQL DB Credentials
5352
# (For saving data from tests)

seleniumbase/fixtures/base_case.py

+48-7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from pyvirtualdisplay import Display
1717
from seleniumbase.config import settings
1818
from seleniumbase.core.application_manager import ApplicationManager
19+
from seleniumbase.core.s3_manager import S3LoggingBucket
1920
from seleniumbase.core.testcase_manager import ExecutionQueryPayload
2021
from seleniumbase.core.testcase_manager import TestcaseDataPayload
2122
from seleniumbase.core.testcase_manager import TestcaseManager
@@ -340,6 +341,11 @@ def setUp(self):
340341
self.headless_active = False
341342
self.with_testing_base = pytest.config.option.with_testing_base
342343
self.with_db_reporting = pytest.config.option.with_db_reporting
344+
self.with_s3_logging = pytest.config.option.with_s3_logging
345+
self.with_screen_shots = pytest.config.option.with_screen_shots
346+
self.with_basic_test_info = (
347+
pytest.config.option.with_basic_test_info)
348+
self.with_page_source = pytest.config.option.with_page_source
343349
self.database_env = pytest.config.option.database_env
344350
self.log_path = pytest.config.option.log_path
345351
self.browser = pytest.config.option.browser
@@ -416,13 +422,24 @@ def tearDown(self):
416422
test_logpath = self.log_path + "/" + test_id
417423
if not os.path.exists(test_logpath):
418424
os.makedirs(test_logpath)
419-
# Handle screenshot logging
420-
log_helper.log_screenshot(test_logpath, self.driver)
421-
# Handle basic test info logging
422-
log_helper.log_test_failure_data(
423-
test_logpath, self.driver, self.browser)
424-
# Handle page source logging
425-
log_helper.log_page_source(test_logpath, self.driver)
425+
if ((not self.with_screen_shots) and
426+
(not self.with_basic_test_info) and
427+
(not self.with_page_source)):
428+
# Log everything if nothing specified (if testing_base)
429+
log_helper.log_screenshot(test_logpath, self.driver)
430+
log_helper.log_test_failure_data(
431+
test_logpath, self.driver, self.browser)
432+
log_helper.log_page_source(test_logpath, self.driver)
433+
else:
434+
if self.with_screen_shots:
435+
log_helper.log_screenshot(
436+
test_logpath, self.driver)
437+
if self.with_basic_test_info:
438+
log_helper.log_test_failure_data(
439+
test_logpath, self.driver, self.browser)
440+
if self.with_page_source:
441+
log_helper.log_page_source(
442+
test_logpath, self.driver)
426443
# Finally close the browser
427444
self.driver.quit()
428445
if self.headless:
@@ -436,3 +453,27 @@ def tearDown(self):
436453
runtime = int(time.time() * 1000) - self.execution_start_time
437454
self.testcase_manager.update_execution_data(
438455
self.execution_guid, runtime)
456+
if self.with_s3_logging and (sys.exc_info()[1] is not None):
457+
""" After each testcase, upload logs to the S3 bucket. """
458+
s3_bucket = S3LoggingBucket()
459+
guid = str(uuid.uuid4().hex)
460+
path = "%s/%s" % (self.log_path, test_id)
461+
uploaded_files = []
462+
for logfile in os.listdir(path):
463+
logfile_name = "%s/%s/%s" % (guid,
464+
test_id,
465+
logfile.split(path)[-1])
466+
s3_bucket.upload_file(logfile_name,
467+
"%s/%s" % (path, logfile))
468+
uploaded_files.append(logfile_name)
469+
s3_bucket.save_uploaded_file_names(uploaded_files)
470+
index_file = s3_bucket.upload_index_file(test_id, guid)
471+
print "\n\n*** Log files uploaded: ***\n%s\n" % index_file
472+
logging.error(
473+
"\n\n*** Log files uploaded: ***\n%s\n" % index_file)
474+
if self.with_db_reporting:
475+
self.testcase_manager = TestcaseManager(self.database_env)
476+
data_payload = TestcaseDataPayload()
477+
data_payload.guid = guid
478+
data_payload.logURL = index_file
479+
self.testcase_manager.update_testcase_log_url(data_payload)

seleniumbase/plugins/db_reporting_plugin.py

+8-10
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ class DBReporting(Plugin):
2424
name = 'db_reporting' # Usage: --with-db_reporting
2525

2626
def __init__(self):
27-
"""initialize some variables"""
2827
Plugin.__init__(self)
2928
self.execution_guid = str(uuid.uuid4())
3029
self.testcase_guid = None
@@ -43,14 +42,13 @@ def options(self, parser, env):
4342
help=SUPPRESS_HELP)
4443

4544
def configure(self, options, conf):
46-
"""get the options"""
4745
super(DBReporting, self).configure(options, conf)
4846
self.options = options
4947
self.testcase_manager = TestcaseManager(self.options.database_env)
5048

5149
def begin(self):
52-
"""At the start of the run, we want to record the
53-
execution information to the database."""
50+
"""At the start of the run, we want to record the test
51+
execution information in the database."""
5452
exec_payload = ExecutionQueryPayload()
5553
exec_payload.execution_start_time = int(time.time() * 1000)
5654
self.execution_start_time = exec_payload.execution_start_time
@@ -59,7 +57,7 @@ def begin(self):
5957
self.testcase_manager.insert_execution_data(exec_payload)
6058

6159
def startTest(self, test):
62-
"""at the start of the test, set the test case details"""
60+
"""At the start of the test, set the testcase details."""
6361
data_payload = TestcaseDataPayload()
6462
self.testcase_guid = str(uuid.uuid4())
6563
data_payload.guid = self.testcase_guid
@@ -80,26 +78,26 @@ def startTest(self, test):
8078

8179
def finalize(self, result):
8280
"""At the end of the run, we want to
83-
update that row with the execution time."""
81+
update the DB row with the execution time."""
8482
runtime = int(time.time() * 1000) - self.execution_start_time
8583
self.testcase_manager.update_execution_data(self.execution_guid,
8684
runtime)
8785

8886
def addSuccess(self, test, capt):
8987
"""
90-
After sucess of a test, we want to record the testcase run information.
88+
After test completion, we want to record testcase run information.
9189
"""
9290
self.__insert_test_result(constants.State.PASS, test)
9391

9492
def addError(self, test, err, capt=None):
9593
"""
96-
After error of a test, we want to record the testcase run information.
94+
After a test error, we want to record testcase run information.
9795
"""
9896
self.__insert_test_result(constants.State.ERROR, test, err)
9997

10098
def handleError(self, test, err, capt=None):
10199
"""
102-
After error of a test, we want to record the testcase run information.
100+
After a test error, we want to record testcase run information.
103101
"Error" also encompasses any states other than Pass or Fail, so we
104102
check for those first.
105103
"""
@@ -123,7 +121,7 @@ def handleError(self, test, err, capt=None):
123121

124122
def addFailure(self, test, err, capt=None, tbinfo=None):
125123
"""
126-
After failure of a test, we want to record testcase run information.
124+
After a test failure, we want to record testcase run information.
127125
"""
128126
self.__insert_test_result(constants.State.FAILURE, test, err)
129127

seleniumbase/plugins/s3_logging_plugin.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ def afterTest(self, test):
3636
uploaded_files.append(logfile_name)
3737
s3_bucket.save_uploaded_file_names(uploaded_files)
3838
index_file = s3_bucket.upload_index_file(test.id(), guid)
39-
print "Log files uploaded: %s" % index_file
40-
logging.error("Log files uploaded: %s" % index_file)
39+
print "\n\n*** Log files uploaded: ***\n%s\n" % index_file
40+
logging.error("\n\n*** Log files uploaded: ***\n%s\n" % index_file)
4141

4242
# If the database plugin is running, attach a link
4343
# to the logs index database row

seleniumbase/plugins/screen_shots.py

-17
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ class ScreenShots(Plugin):
1616

1717
name = "screen_shots"
1818
logfile_name = settings.SCREENSHOT_NAME
19-
# Browser windows aren't always maximized. This may display more details.
20-
logfile_name_2 = "full_screenshot.jpg"
2119

2220
def options(self, parser, env):
2321
super(ScreenShots, self).options(parser, env=env)
@@ -34,21 +32,6 @@ def add_screenshot(self, test, err, capt=None, tbinfo=None):
3432
os.makedirs(test_logpath)
3533
screenshot_file = "%s/%s" % (test_logpath, self.logfile_name)
3634
test.driver.get_screenshot_as_file(screenshot_file)
37-
'''try:
38-
# Let humans see any errors on screen before closing the window
39-
test.driver.maximize_window()
40-
import time
41-
time.sleep(0.2) # Make sure the screen is ready
42-
except Exception:
43-
pass
44-
# Second screenshot at fullscreen might not be necessary
45-
# import base64
46-
screen_b64 = test.driver.get_screenshot_as_base64()
47-
screen = base64.decodestring(screen_b64)
48-
screenshot_file_2 = "%s/%s" % (test_logpath, self.logfile_name_2)
49-
f1 = open(screenshot_file_2, 'w+')
50-
f1.write(screen)
51-
f1.close()'''
5235

5336
def addError(self, test, err, capt=None):
5437
self.add_screenshot(test, err, capt=capt)

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
setup(
88
name='seleniumbase',
9-
version='1.1.24',
9+
version='1.1.25',
1010
url='https://github.com/mdmintz/SeleniumBase',
1111
author='Michael Mintz',
1212
author_email='@mintzworld',

0 commit comments

Comments
 (0)