Skip to content

Commit 8ca1165

Browse files
authored
Merge pull request #163 from seleniumbase/mysql-deploy
MySQL Deploy
2 parents 6af020b + 32289fc commit 8ca1165

15 files changed

+153
-325
lines changed

.travis.yml

+14-5
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,33 @@ language: python
22
sudo: false
33
python:
44
- "2.7"
5+
- "3.6"
56
addons:
67
firefox: latest
78
chrome: stable
9+
before_install:
10+
- "sudo mysql -e 'CREATE DATABASE IF NOT EXISTS test_db;'"
11+
- "sudo mysql -h 127.0.0.1 -u root test_db < seleniumbase/core/create_db_tables.sql"
12+
- "mysqladmin -u root password test"
13+
# - "mysqladmin -u root -p'old_password' password new_password"
14+
- "sudo service mysql restart"
815
install:
916
- "pip install --upgrade pip"
1017
- "pip install -r requirements.txt --upgrade"
1118
- "python setup.py develop"
1219
- "sudo rm -f /etc/boto.cfg"
1320
before_script:
1421
- "flake8 seleniumbase/*.py && flake8 seleniumbase/*/*.py && flake8 seleniumbase/*/*/*.py && flake8 seleniumbase/*/*/*/*.py"
15-
# - "export DISPLAY=:99.0 && sh -e /etc/init.d/xvfb start"
1622
- "wget https://chromedriver.storage.googleapis.com/2.37/chromedriver_linux64.zip && unzip chromedriver_linux64.zip && sudo cp chromedriver /usr/local/bin/ && sudo chmod +x /usr/local/bin/chromedriver"
1723
- "wget https://github.com/mozilla/geckodriver/releases/download/v0.20.0/geckodriver-v0.20.0-linux64.tar.gz -O /tmp/geckodriver.tar.gz && tar -C /opt -xzf /tmp/geckodriver.tar.gz && sudo chmod 755 /opt/geckodriver && sudo ln -fs /opt/geckodriver /usr/bin/geckodriver && sudo ln -fs /opt/geckodriver /usr/local/bin/geckodriver"
1824
# - "wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2 && tar -xvf ./phantomjs-2.1.1-linux-x86_64.tar.bz2 && export PATH=$PWD/phantomjs-2.1.1-linux-x86_64/bin:$PATH"
1925
script:
20-
- "pytest examples/my_first_test.py --browser=chrome -s --headless"
21-
- "nosetests examples/boilerplates/boilerplate_test.py --headless"
22-
- "pytest examples/my_first_test.py --browser=firefox -s --headless"
23-
- "pytest examples/github_test.py --browser=chrome -s --headless"
26+
- "pytest examples/my_first_test.py --browser=chrome -s --headless --with-db_reporting"
27+
- "nosetests examples/boilerplates/boilerplate_test.py --browser=chrome --headless"
28+
- "pytest examples/my_first_test.py --browser=firefox -s --headless --with-db_reporting"
29+
- "pytest examples/github_test.py --browser=firefox -s --headless --with-db_reporting --demo_mode --demo_sleep=0.2"
30+
- "sudo mysql --password=test -e 'select test_address,browser,state,start_time,runtime from test_db.test_run_data'"
31+
after_script:
32+
- "sudo mysql -e 'DROP DATABASE test_db;'"
2433
notifications:
2534
email: false

README.md

+2-46
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
2-
## Automated Web-UI testing reimagined.
1+
## Automated testing made fast, easy, and reliable.
32

43
<img src="https://cdn2.hubspot.net/hubfs/100006/images/laptop_logo.png" title="SeleniumBase" height="160">
54

@@ -610,7 +609,7 @@ Let's say you have a test that sends an email, and now you want to check that th
610609
from seleniumbase.fixtures.email_manager import EmailManager, EmailException
611610
num_email_results = 0
612611
email_subject = "This is the subject to search for (maybe include a timestamp)"
613-
email_manager = EmailManager("[YOUR SELENIUM GMAIL EMAIL ADDRESS]") # the password for this is elsewhere (in the library) because this is a default email account
612+
email_manager = EmailManager("{YOUR SELENIUM GMAIL ACCOUNT EMAIL ADDRESS}") # the password for this would be stored in seleniumbase/config/settings.py
614613
try:
615614
html_text = email_manager.search(SUBJECT="%s" % email_subject, timeout=300)
616615
num_email_results = len(html_text)
@@ -622,49 +621,6 @@ self.assertTrue(num_email_results) # true if not zero
622621
Now you can parse through the email if you're looking for specific text or want to navigate to a link listed there.
623622

624623

625-
#### Database Powers:
626-
Let's say you have a test that needs to access the database. First make sure you already have a table ready. Then try this example:
627-
628-
```python
629-
from seleniumbase.core.mysql import DatabaseManager
630-
def write_data_to_db(self, theId, theValue, theUrl):
631-
db = DatabaseManager()
632-
query = """INSERT INTO myTable(theId,theValue,theUrl)
633-
VALUES (%(theId)s,%(theValue)s,%(theUrl)s)"""
634-
db.execute_query_and_close(query, {"theId":theId,
635-
"theValue":theValue,
636-
"theUrl":theUrl})
637-
```
638-
639-
Access credentials are stored in [settings.py](https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/config/settings.py) for your convenience (you have to add them first).
640-
641-
The following example below (taken from the Delayed Data Manager) shows how data can be pulled from the database.
642-
643-
```python
644-
import logging
645-
from seleniumbase.core.mysql import DatabaseManager
646-
647-
def get_delayed_test_data(self, testcase_address, done=0):
648-
""" Returns a list of rows """
649-
db = DatabaseManager()
650-
query = """SELECT guid,testcaseAddress,insertedAt,expectedResult,done
651-
FROM delayedTestData
652-
WHERE testcaseAddress=%(testcase_address)s
653-
AND done=%(done)s"""
654-
data = db.fetchall_query_and_close(query, {"testcase_address":testcase_address, "done":done})
655-
if data:
656-
return data
657-
else:
658-
logging.debug("Could not find any rows in delayedTestData.")
659-
logging.debug("DB Query = " + query % {"testcase_address":testcase_address, "done":done})
660-
return []
661-
```
662-
663-
Now you know how to pull data from your MySQL DB.
664-
665-
Delayed Data usage example: If you scheduled an email to go out 3 hours from now and you wanted to check that the email gets received (but you don't want your test sitting idle for 3 hours) you can store the email credentials as a unique time-stamp for the email subject in the DB (along with a time for when it's safe for the email to be searched for) and then a later-running test can do the checking after the right amount of time has passed.
666-
667-
668624
### ![http://seleniumbase.com](https://cdn2.hubspot.net/hubfs/100006/images/super_logo_tiny.png "SeleniumBase") Wrap-Up
669625

670626
**Congratulations** on learning how to use **SeleniumBase**!

examples/github_test.py

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
11
from seleniumbase import BaseCase
2+
import time
23

34

45
class GitHubTests(BaseCase):
56

7+
# Selenium can trigger GitHub's abuse detection mechanism:
8+
# "You have triggered an abuse detection mechanism."
9+
# "Please wait a few minutes before you try again."
10+
# To avoid this, slow down Selenium actions.
11+
def slow_click(self, css_selector):
12+
time.sleep(1)
13+
self.click(css_selector)
14+
615
def test_github(self):
716
self.open("https://github.com/")
817
self.update_text("input.header-search-input", "SeleniumBase\n")
9-
self.click('a[href="/seleniumbase/SeleniumBase"]')
18+
self.slow_click('a[href="/seleniumbase/SeleniumBase"]')
1019
self.assert_element("div.repository-content")
1120
self.assert_text("SeleniumBase", "h1")
12-
self.click('a[title="seleniumbase"]')
13-
self.click('a[title="fixtures"]')
14-
self.click('a[title="base_case.py"]')
21+
self.slow_click('a[title="seleniumbase"]')
22+
self.slow_click('a[title="fixtures"]')
23+
self.slow_click('a[title="base_case.py"]')
1524
self.assert_text("Code", "nav a.selected")

integrations/google_cloud/ReadMe.md

+3-8
Original file line numberDiff line numberDiff line change
@@ -168,18 +168,13 @@ If you have a web application that you want to test, you'll be able to create Se
168168

169169
#### Step 26. Create the necessary tables in your MySQL database/schema
170170

171-
* Run a SQL script in your MySQL database/schema using [testcaserepository.sql](https://raw.githubusercontent.com/seleniumbase/SeleniumBase/master/seleniumbase/core/testcaserepository.sql)
171+
* Run the [create_db_tables.sql](https://raw.githubusercontent.com/seleniumbase/SeleniumBase/master/seleniumbase/core/create_db_tables.sql) script in your MySQL database/schema to create all the required DB tables.
172172

173-
#### Step 27. Have your local clone of SeleniumBase connect to your MySQL Instance
173+
#### Step 27. Have your local clone of SeleniumBase connect to your MySQL DB Instance
174174

175175
* Update the MySQL connection details in your [settings.py](https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/config/settings.py) file to use the credentials that you saved in Step 21.
176-
* If you haven't already installed the MySQL-Python connector, run the following command below:
177176

178-
```bash
179-
pip install MySQL-python==1.2.5
180-
```
181-
182-
#### Step 28. Have your SeleniumBase Jenkins jobs use your MySQL Instance
177+
#### Step 28. Have your SeleniumBase Jenkins jobs use your MySQL DB Instance
183178

184179
* For the "Execute shell", use the following as your updated "Command":
185180

requirements.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ six==1.10.0
1010
flake8==3.5.0
1111
requests==2.18.4
1212
beautifulsoup4==4.6.0
13+
mysqlclient==1.3.12
1314
unittest2==1.1.0
1415
chardet==3.0.4
1516
boto==2.48.0
1617
ipdb==0.11
17-
pyvirtualdisplay==0.2.1
18+
PyVirtualDisplay==0.2.1
1819
-e .
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Creates test_db tables for using SeleniumBase with MySQL
2+
3+
# test_run_data table
4+
# -----------------------------------
5+
CREATE TABLE `test_run_data` (
6+
`guid` varchar(64) NOT NULL DEFAULT '',
7+
`test_address` varchar(255) DEFAULT NULL,
8+
`env` varchar(64) DEFAULT NULL,
9+
`start_time` varchar(64) DEFAULT NULL,
10+
`execution_guid` varchar(64) DEFAULT NULL,
11+
`runtime` int(11),
12+
`state` varchar(64) DEFAULT NULL,
13+
`browser` varchar(64) DEFAULT NULL,
14+
`message` text,
15+
`stack_trace` text,
16+
`retry_count` int(11) DEFAULT '0',
17+
`exception_map_guid` varchar(64) DEFAULT NULL,
18+
`log_url` text,
19+
PRIMARY KEY (`guid`)
20+
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
21+
22+
# test_execution table
23+
# -----------------------------------
24+
CREATE TABLE `test_execution` (
25+
`guid` varchar(64) NOT NULL DEFAULT '',
26+
`total_execution_time` int(11),
27+
`username` varchar(255) DEFAULT NULL,
28+
`execution_start` bigint(20) DEFAULT '0',
29+
PRIMARY KEY (`guid`)
30+
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

seleniumbase/core/mysql.py

+10-12
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,25 @@
11
"""
2-
Wrapper for MySQL functions to make life easier
3-
Due to compatibility issues, might only work for Python 2.7 right now
2+
Wrapper for MySQL DB functions to make life easier.
43
"""
54

65
import time
6+
from seleniumbase.core import mysql_conf as conf
77

88

99
class DatabaseManager():
1010
"""
11-
This class wraps database functions for easy use.
12-
It connects to the testcase database.
11+
This class wraps MySQL database methods for easy use.
1312
"""
1413

1514
def __init__(self, database_env='test', conf_creds=None):
1615
"""
1716
Gets database information from mysql_conf.py and creates a connection.
1817
"""
19-
import mysql_conf as conf # This had problems when using Python 3
2018
import MySQLdb
2119
db_server, db_user, db_pass, db_schema = \
2220
conf.APP_CREDS[conf.Apps.TESTCASE_REPOSITORY][database_env]
2321
retry_count = 3
24-
backoff = 1.2 # Time to wait (in seconds) between retries
22+
backoff = 1.2 # Time to wait (in seconds) between retries.
2523
count = 0
2624
while count < retry_count:
2725
try:
@@ -38,27 +36,27 @@ def __init__(self, database_env='test', conf_creds=None):
3836
if retry_count == 3:
3937
raise Exception("Unable to connect to Database after 3 retries.")
4038

41-
def fetchall_query_and_close(self, query, values):
39+
def query_fetch_all(self, query, values):
4240
"""
43-
Executes a query, gets all the values and then closes up the connection
41+
Executes a db query, gets all the values, and closes the connection.
4442
"""
4543
self.cursor.execute(query, values)
4644
retval = self.cursor.fetchall()
4745
self.__close_db()
4846
return retval
4947

50-
def fetchone_query_and_close(self, query, values):
48+
def query_fetch_one(self, query, values):
5149
"""
52-
Executes a query, gets the first value, and closes up the connection
50+
Executes a db query, gets the first value, and closes the connection.
5351
"""
5452
self.cursor.execute(query, values)
5553
retval = self.cursor.fetchone()
5654
self.__close_db()
5755
return retval
5856

59-
def execute_query_and_close(self, query, values):
57+
def execute_query(self, query, values):
6058
"""
61-
Executes a query and closes the connection
59+
Executes a query to the test_db and closes the connection afterwards.
6260
"""
6361
retval = self.cursor.execute(query, values)
6462
self.__close_db()

seleniumbase/core/mysql_conf.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
"""
2-
This file contains database credentials for the various databases
3-
that the tests need to access
2+
This file organizes connection details to the Testcase Database.
43
"""
54

65
from seleniumbase.config import settings

0 commit comments

Comments
 (0)