Skip to content
This repository was archived by the owner on Jun 7, 2023. It is now read-only.

Commit d410111

Browse files
committed
Fix: Wait for the server to start before running tests.
Clean: Black, imports.
1 parent 9643156 commit d410111

1 file changed

Lines changed: 58 additions & 14 deletions

File tree

runestone/unittest_base.py

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,37 @@
1-
import unittest
1+
# *************************************************************************
2+
# ``unittest_base.py`` - Base classes for RunestoneComponents test fixtures
3+
# *************************************************************************
4+
#
5+
# Imports
6+
# =======
7+
# These are listed in the order prescribed by `PEP 8
8+
# <http://www.python.org/dev/peps/pep-0008/#imports>`_.
9+
#
10+
# Standard library
11+
# ----------------
212
import os
3-
import sys
413
import platform
514
import subprocess
15+
import sys
16+
import time
17+
import unittest
18+
from urllib.request import urlopen
19+
from urllib.error import URLError
20+
21+
# Third-party imports
22+
# -------------------
623
from selenium import webdriver
724
from selenium.webdriver.chrome.options import Options
825
from pyvirtualdisplay import Display
926

27+
# Local imports
28+
# -------------
29+
# None
30+
1031
# Select an unused port for serving web pages to the test suite.
11-
PORT = '8081'
32+
PORT = "8081"
33+
# Use the localhost for testing.
34+
HOST = "http://127.0.0.1:" + PORT
1235

1336

1437
# Provide access to the currently-active ModuleFixture object.
@@ -17,41 +40,50 @@
1740

1841
# Define `module fixtures <https://docs.python.org/2/library/unittest.html#setupmodule-and-teardownmodule>`_ to build the test Runestone project, run the server, then shut it down when the tests complete.
1942
class ModuleFixture(unittest.TestCase):
20-
def __init__(self,
43+
def __init__(
44+
self,
2145
# The path to the Python module in which the test resides. This provides a simple way to determine the path in which to run runestone build/serve.
2246
module_path,
2347
# True if the sphinx-build process must exit with status of 0 (success)
24-
exit_status_success=True):
48+
exit_status_success=True,
49+
):
2550

2651
super(ModuleFixture, self).__init__()
2752
self.base_path = os.path.dirname(module_path)
2853
self.exit_status_success = exit_status_success
2954
# Windows Compatability
30-
if platform.system() is 'Windows' and self.base_path is '':
31-
self.base_path = '.'
55+
if platform.system() is "Windows" and self.base_path is "":
56+
self.base_path = "."
3257

3358
def setUpModule(self):
3459
# Change to this directory for running Runestone.
3560
self.old_cwd = os.getcwd()
3661
os.chdir(self.base_path)
3762
# Compile the docs. Save the stdout and stderr for examination.
38-
p = subprocess.Popen(['runestone', 'build', '--all'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
63+
p = subprocess.Popen(
64+
["runestone", "build", "--all"],
65+
stdout=subprocess.PIPE,
66+
stderr=subprocess.PIPE,
67+
universal_newlines=True,
68+
)
3969
self.build_stdout_data, self.build_stderr_data = p.communicate()
4070
print(self.build_stdout_data + self.build_stderr_data)
4171
if self.exit_status_success:
4272
self.assertFalse(p.returncode)
4373
# Run the server. Simply calling ``runestone serve`` fails, since the process killed isn't the actual server, but probably a setuptools-created launcher.
44-
self.runestone_server = subprocess.Popen([sys.executable, '-m', 'runestone', 'serve', '--port', PORT])
74+
self.runestone_server = subprocess.Popen(
75+
[sys.executable, "-m", "runestone", "serve", "--port", PORT]
76+
)
4577

4678
# Testing time in dominated by browser startup/shutdown. So, simply run all tests in a module in a single browser instance to speed things up. See ``RunestoneTestCase.setUp`` for additional code to (mostly) clear the browser between tests.
4779
#
4880
# `PyVirtualDisplay <http://pyvirtualdisplay.readthedocs.io/en/latest/>`_ only runs on X-windows, meaning Linux. Mac seems to have `some support <https://support.apple.com/en-us/HT201341>`_. Windows is out of the question.
49-
if sys.platform.startswith('linux'):
81+
if sys.platform.startswith("linux"):
5082
self.display = Display(visible=0, size=(1280, 1024))
5183
self.display.start()
5284
else:
5385
self.display = None
54-
#self.driver = webdriver.PhantomJS() # use this for Jenkins auto testing
86+
# self.driver = webdriver.PhantomJS() # use this for Jenkins auto testing
5587
options = Options()
5688
options.add_argument("--window-size=1200,800")
5789
self.driver = webdriver.Chrome(chrome_options=options) # good for development.
@@ -60,6 +92,17 @@ def setUpModule(self):
6092
global mf
6193
mf = self
6294

95+
# Wait for the webserver to come up.
96+
for tries in range(50):
97+
try:
98+
urlopen(HOST, timeout=5)
99+
except URLError:
100+
# Wait for the server to come up.
101+
time.sleep(0.1)
102+
else:
103+
# The server is up. We're done.
104+
break
105+
63106
def tearDownModule(self):
64107
# Shut down Selenium.
65108
self.driver.quit()
@@ -86,6 +129,7 @@ def tearDownModule(self):
86129
def runTest(self):
87130
pass
88131

132+
89133
# Provide a simple way to instantiante a ModuleFixture in a test module. Typical use:
90134
#
91135
# .. code:: Python
@@ -106,10 +150,10 @@ class RunestoneTestCase(unittest.TestCase):
106150
def setUp(self):
107151
# Use the shared module-wide driver.
108152
self.driver = mf.driver
109-
self.host = 'http://127.0.0.1:' + PORT
153+
self.host = HOST
110154

111155
def tearDown(self):
112156
# Clear as much as possible, to present an almost-fresh instance of a browser for the next test. (Shutting down then starting up a browswer is very slow.)
113-
self.driver.execute_script('window.localStorage.clear();')
114-
self.driver.execute_script('window.sessionStorage.clear();')
157+
self.driver.execute_script("window.localStorage.clear();")
158+
self.driver.execute_script("window.sessionStorage.clear();")
115159
self.driver.delete_all_cookies()

0 commit comments

Comments
 (0)