Skip to content

Commit 7d8028c

Browse files
author
Brandon Duffany
committed
Improve test fixtures
1 parent 9320a55 commit 7d8028c

File tree

4 files changed

+55
-34
lines changed

4 files changed

+55
-34
lines changed

codebender_testing/utils.py

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import re
2-
import sys
32

43
from selenium import webdriver
54
from selenium.common.exceptions import NoSuchElementException
@@ -12,17 +11,23 @@
1211
from codebender_testing.config import WEBDRIVERS
1312

1413

14+
1515
class SeleniumTestCase(object):
1616
"""Base class for all Selenium tests."""
1717

1818
@classmethod
19-
@pytest.fixture(scope="class", autouse=True, params=WEBDRIVERS.keys())
20-
def setup(self, request):
21-
"""Sets up attributes that should be accessible to all test cases."""
19+
@pytest.fixture(scope="class", autouse=True)
20+
def _testcase_attrs(cls, webdriver):
21+
"""Sets up any class attributes to be used by any SeleniumTestCase.
22+
Here, we just store fixtures as class attributes. This allows us to avoid
23+
the pytest boilerplate of getting a fixture value, and instead just
24+
refer to the fixture as `self.<fixture>`.
25+
"""
26+
cls.driver = webdriver
2227

23-
# Repeat each test for each webdriver configuration
24-
webdriver_cls = WEBDRIVERS[request.param]
25-
self.driver = webdriver_cls()
28+
@pytest.fixture(scope="class")
29+
def tester_login(self):
30+
self.login()
2631

2732
def open(self, url=None):
2833
"""Open the resource specified by `url`.
@@ -49,26 +54,20 @@ def open_project(self, project_name=None):
4954
project_link = self.driver.find_element_by_link_text(project_name)
5055
project_link.send_keys(Keys.ENTER)
5156

52-
53-
def logged_in(func):
54-
"""Decorator to ensure the user is logged in before performing a test.
55-
If not logged in, a login will be performed."""
56-
def inner(*args, **kwargs):
57-
test = args[0]
57+
def login(self):
58+
"""Performs a login."""
5859
try:
59-
test.open()
60-
login_button = test.driver.find_element_by_id('login_btn')
60+
self.open()
61+
login_button = self.driver.find_element_by_id('login_btn')
6162
login_button.send_keys(Keys.ENTER)
6263
# Enter credentials and log in
63-
user_field = test.driver.find_element_by_id('username')
64+
user_field = self.driver.find_element_by_id('username')
6465
user_field.send_keys(TEST_CREDENTIALS['username'])
65-
pass_field = test.driver.find_element_by_id('password')
66+
pass_field = self.driver.find_element_by_id('password')
6667
pass_field.send_keys(TEST_CREDENTIALS['password'])
67-
do_login = test.driver.find_element_by_id('_submit')
68+
do_login = self.driver.find_element_by_id('_submit')
6869
do_login.send_keys(Keys.ENTER)
6970
except NoSuchElementException:
7071
# 'Log In' is not displayed, so we're already logged in.
7172
pass
72-
return func(*args, **kwargs)
73-
return inner
7473

requirements-dev.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
tox
1+
flake8
22
pytest
3+
tox
34
virtualenv
4-

tests/conftest.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import pytest
2+
3+
from codebender_testing.config import WEBDRIVERS
4+
5+
6+
@pytest.fixture(scope="session", params=WEBDRIVERS.keys())
7+
def webdriver(request):
8+
"""Returns a webdriver that persists across the entire test session,
9+
and registers a finalizer to close the browser once the session is
10+
complete. The entire test session is repeated once per driver.
11+
"""
12+
driver = WEBDRIVERS[request.param]()
13+
request.addfinalizer(lambda: driver.quit())
14+
return driver
15+

tests/sketch/test_sketch.py

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
from selenium.webdriver.common.by import By
55
from selenium.webdriver.common.keys import Keys
66
from selenium.webdriver.support import expected_conditions
7+
from selenium.webdriver.support.select import Select
78
from selenium.webdriver.support.ui import WebDriverWait
9+
import pytest
810

9-
from codebender_testing.utils import logged_in
1011
from codebender_testing.utils import SeleniumTestCase
1112

1213

@@ -16,17 +17,24 @@
1617
# How long to wait before we give up on finding an element on the page.
1718
ELEMENT_FIND_TIMEOUT = 5
1819

20+
# Board to test for the dropdown selector.
21+
TEST_BOARD = "Arduino Fio"
22+
1923

2024
class TestSketch(SeleniumTestCase):
25+
"""Tests various functions of the /sketch view."""
2126

22-
@logged_in
23-
def test_verify_code(self):
27+
@pytest.fixture(scope="class", autouse=True)
28+
def open_test_project(self, tester_login):
29+
"""Makes sure we are logged in and have a project open before
30+
performing any of these tests."""
2431
self.open_project()
25-
2632
# I get a StaleElementReferenceException without
2733
# this wait. TODO: figure out how to get around this.
2834
time.sleep(3)
29-
35+
36+
def test_verify_code(self):
37+
"""Ensures that we can compile code and see the success message."""
3038
compile_button = self.driver.find_element_by_id("compile")
3139
compile_button.click()
3240

@@ -35,19 +43,18 @@ def test_verify_code(self):
3543
(By.ID, "operation_output"), "Verification Successful!")
3644
)
3745

38-
@logged_in
3946
def test_boards_dropdown(self):
40-
self.open_project()
41-
47+
"""Tests that the boards dropdown is present, and that we can change
48+
the board successfully."""
4249
WebDriverWait(self.driver, ELEMENT_FIND_TIMEOUT).until(
4350
expected_conditions.presence_of_element_located(
4451
(By.ID, "boards"))
4552
)
4653

47-
boards_dropdown = self.driver.find_element_by_id("boards")
48-
options = boards_dropdown.find_elements_by_tag_name("option")
54+
boards_dropdown = Select(self.driver.find_element_by_id("boards"))
4955

5056
# Click something other than the first option
51-
test_option = options[3]
52-
test_option.click()
57+
boards_dropdown.select_by_visible_text(TEST_BOARD)
58+
59+
assert boards_dropdown.first_selected_option.text == TEST_BOARD
5360

0 commit comments

Comments
 (0)