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

Commit eeffadc

Browse files
authored
Merge pull request #918 from bjones1/timeout
Fix: Wait for the server to start before running tests.
2 parents 6806d85 + d410111 commit eeffadc

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,17 +1,40 @@
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 pytest
615
import signal
716
import time
817
import subprocess
18+
import sys
19+
import time
20+
import unittest
21+
from urllib.request import urlopen
22+
from urllib.error import URLError
23+
24+
# Third-party imports
25+
# -------------------
926
from selenium import webdriver
1027
from selenium.webdriver.chrome.options import Options
1128
from pyvirtualdisplay import Display
1229

30+
# Local imports
31+
# -------------
32+
# None
33+
1334
# Select an unused port for serving web pages to the test suite.
14-
PORT = '8081'
35+
PORT = "8081"
36+
# Use the localhost for testing.
37+
HOST = "http://127.0.0.1:" + PORT
1538

1639

1740
# Provide access to the currently-active ModuleFixture object.
@@ -20,25 +43,32 @@
2043

2144
# 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.
2245
class ModuleFixture(unittest.TestCase):
23-
def __init__(self,
46+
def __init__(
47+
self,
2448
# 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.
2549
module_path,
2650
# True if the sphinx-build process must exit with status of 0 (success)
27-
exit_status_success=True):
51+
exit_status_success=True,
52+
):
2853

2954
super(ModuleFixture, self).__init__()
3055
self.base_path = os.path.dirname(module_path)
3156
self.exit_status_success = exit_status_success
3257
# Windows Compatability
33-
if platform.system() is 'Windows' and self.base_path is '':
34-
self.base_path = '.'
58+
if platform.system() is "Windows" and self.base_path is "":
59+
self.base_path = "."
3560

3661
def setUpModule(self):
3762
# Change to this directory for running Runestone.
3863
self.old_cwd = os.getcwd()
3964
os.chdir(self.base_path)
4065
# Compile the docs. Save the stdout and stderr for examination.
41-
p = subprocess.Popen(['runestone', 'build', '--all'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
66+
p = subprocess.Popen(
67+
["runestone", "build", "--all"],
68+
stdout=subprocess.PIPE,
69+
stderr=subprocess.PIPE,
70+
universal_newlines=True,
71+
)
4272
self.build_stdout_data, self.build_stderr_data = p.communicate()
4373
print(self.build_stdout_data + self.build_stderr_data)
4474
if self.exit_status_success:
@@ -67,17 +97,19 @@ def setUpModule(self):
6797

6898

6999
# Run the server. Simply calling ``runestone serve`` fails, since the process killed isn't the actual server, but probably a setuptools-created launcher.
70-
self.runestone_server = subprocess.Popen([sys.executable, '-m', 'runestone', 'serve', '--port', PORT])
100+
self.runestone_server = subprocess.Popen(
101+
[sys.executable, "-m", "runestone", "serve", "--port", PORT]
102+
)
71103

72104
# 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.
73105
#
74106
# `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.
75-
if sys.platform.startswith('linux'):
107+
if sys.platform.startswith("linux"):
76108
self.display = Display(visible=0, size=(1280, 1024))
77109
self.display.start()
78110
else:
79111
self.display = None
80-
#self.driver = webdriver.PhantomJS() # use this for Jenkins auto testing
112+
# self.driver = webdriver.PhantomJS() # use this for Jenkins auto testing
81113
options = Options()
82114
options.add_argument("--window-size=1200,800")
83115
options.add_argument("--no-sandbox")
@@ -87,6 +119,17 @@ def setUpModule(self):
87119
global mf
88120
mf = self
89121

122+
# Wait for the webserver to come up.
123+
for tries in range(50):
124+
try:
125+
urlopen(HOST, timeout=5)
126+
except URLError:
127+
# Wait for the server to come up.
128+
time.sleep(0.1)
129+
else:
130+
# The server is up. We're done.
131+
break
132+
90133
def tearDownModule(self):
91134
# Shut down Selenium.
92135
self.driver.quit()
@@ -113,6 +156,7 @@ def tearDownModule(self):
113156
def runTest(self):
114157
pass
115158

159+
116160
# Provide a simple way to instantiante a ModuleFixture in a test module. Typical use:
117161
#
118162
# .. code:: Python
@@ -133,10 +177,10 @@ class RunestoneTestCase(unittest.TestCase):
133177
def setUp(self):
134178
# Use the shared module-wide driver.
135179
self.driver = mf.driver
136-
self.host = 'http://127.0.0.1:' + PORT
180+
self.host = HOST
137181

138182
def tearDown(self):
139183
# 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.)
140-
self.driver.execute_script('window.localStorage.clear();')
141-
self.driver.execute_script('window.sessionStorage.clear();')
184+
self.driver.execute_script("window.localStorage.clear();")
185+
self.driver.execute_script("window.sessionStorage.clear();")
142186
self.driver.delete_all_cookies()

0 commit comments

Comments
 (0)