##// END OF EJS Templates
Simplify waiting for notebook server to die.
Thomas Kluyver -
Show More
@@ -1,96 +1,92 b''
1 """Base class for notebook tests."""
1 """Base class for notebook tests."""
2
2
3 import sys
3 import sys
4 import time
4 import time
5 import requests
5 import requests
6 from contextlib import contextmanager
6 from contextlib import contextmanager
7 from subprocess import Popen, STDOUT
7 from subprocess import Popen, STDOUT
8 from unittest import TestCase
8 from unittest import TestCase
9
9
10 import nose
10 import nose
11
11
12 from IPython.utils.tempdir import TemporaryDirectory
12 from IPython.utils.tempdir import TemporaryDirectory
13
13
14 class NotebookTestBase(TestCase):
14 class NotebookTestBase(TestCase):
15 """A base class for tests that need a running notebook.
15 """A base class for tests that need a running notebook.
16
16
17 This creates an empty profile in a temp ipython_dir
17 This creates an empty profile in a temp ipython_dir
18 and then starts the notebook server with a separate temp notebook_dir.
18 and then starts the notebook server with a separate temp notebook_dir.
19 """
19 """
20
20
21 port = 12341
21 port = 12341
22
22
23 @classmethod
23 @classmethod
24 def wait_until_alive(cls):
24 def wait_until_alive(cls):
25 """Wait for the server to be alive"""
25 """Wait for the server to be alive"""
26 url = 'http://localhost:%i/api/notebooks' % cls.port
26 url = 'http://localhost:%i/api/notebooks' % cls.port
27 for _ in range(300):
27 for _ in range(300):
28 try:
28 try:
29 requests.get(url)
29 requests.get(url)
30 except requests.exceptions.ConnectionError:
30 except requests.exceptions.ConnectionError:
31 if cls.notebook.poll() is not None:
31 if cls.notebook.poll() is not None:
32 raise RuntimeError("The notebook server exited with status %s" \
32 raise RuntimeError("The notebook server exited with status %s" \
33 % cls.notebook.poll())
33 % cls.notebook.poll())
34 time.sleep(.1)
34 time.sleep(.1)
35 else:
35 else:
36 return
36 return
37
37
38 raise TimeoutError("The notebook server didn't start up correctly.")
38 raise TimeoutError("The notebook server didn't start up correctly.")
39
39
40 @classmethod
40 @classmethod
41 def wait_until_dead(cls):
41 def wait_until_dead(cls):
42 """Wait for the server to stop getting requests after shutdown"""
42 """Wait for the server process to terminate after shutdown"""
43 url = 'http://localhost:%i/api/notebooks' % cls.port
44 for _ in range(300):
43 for _ in range(300):
45 try:
44 if cls.notebook.poll() is not None:
46 requests.get(url)
45 return
47 except requests.exceptions.ConnectionError:
46 time.sleep(.1)
48 break
49 else:
50 time.sleep(.1)
51
47
52 raise TimeoutError("Undead notebook server")
48 raise TimeoutError("Undead notebook server")
53
49
54 @classmethod
50 @classmethod
55 def setup_class(cls):
51 def setup_class(cls):
56 cls.ipython_dir = TemporaryDirectory()
52 cls.ipython_dir = TemporaryDirectory()
57 cls.notebook_dir = TemporaryDirectory()
53 cls.notebook_dir = TemporaryDirectory()
58 notebook_args = [
54 notebook_args = [
59 sys.executable, '-c',
55 sys.executable, '-c',
60 'from IPython.html.notebookapp import launch_new_instance; launch_new_instance()',
56 'from IPython.html.notebookapp import launch_new_instance; launch_new_instance()',
61 '--port=%d' % cls.port,
57 '--port=%d' % cls.port,
62 '--port-retries=0',
58 '--port-retries=0',
63 '--no-browser',
59 '--no-browser',
64 '--ipython-dir=%s' % cls.ipython_dir.name,
60 '--ipython-dir=%s' % cls.ipython_dir.name,
65 '--notebook-dir=%s' % cls.notebook_dir.name,
61 '--notebook-dir=%s' % cls.notebook_dir.name,
66 ]
62 ]
67 cls.notebook = Popen(notebook_args,
63 cls.notebook = Popen(notebook_args,
68 stdout=nose.iptest_stdstreams_fileno(),
64 stdout=nose.iptest_stdstreams_fileno(),
69 stderr=STDOUT,
65 stderr=STDOUT,
70 )
66 )
71 cls.wait_until_alive()
67 cls.wait_until_alive()
72
68
73 @classmethod
69 @classmethod
74 def teardown_class(cls):
70 def teardown_class(cls):
75 cls.notebook.terminate()
71 cls.notebook.terminate()
76 cls.ipython_dir.cleanup()
72 cls.ipython_dir.cleanup()
77 cls.notebook_dir.cleanup()
73 cls.notebook_dir.cleanup()
78 cls.wait_until_dead()
74 cls.wait_until_dead()
79
75
80 @classmethod
76 @classmethod
81 def base_url(cls):
77 def base_url(cls):
82 return 'http://localhost:%i/' % cls.port
78 return 'http://localhost:%i/' % cls.port
83
79
84
80
85 @contextmanager
81 @contextmanager
86 def assert_http_error(status, msg=None):
82 def assert_http_error(status, msg=None):
87 try:
83 try:
88 yield
84 yield
89 except requests.HTTPError as e:
85 except requests.HTTPError as e:
90 real_status = e.response.status_code
86 real_status = e.response.status_code
91 assert real_status == status, \
87 assert real_status == status, \
92 "Expected status %d, got %d" % (real_status, status)
88 "Expected status %d, got %d" % (real_status, status)
93 if msg:
89 if msg:
94 assert msg in str(e), e
90 assert msg in str(e), e
95 else:
91 else:
96 assert False, "Expected HTTP error status" No newline at end of file
92 assert False, "Expected HTTP error status"
General Comments 0
You need to be logged in to leave comments. Login now