Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: tests/utils.py

Issue 29912588: Issue 7019 - [CMS] Refactor `test_server.py` (Closed)
Patch Set: Added test_and_wait to test server fixture Created Oct. 25, 2018, 12:22 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tests/test_page_outputs.py ('k') | tox.ini » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # This file is part of the Adblock Plus web scripts, 1 # This file is part of the Adblock Plus web scripts,
2 # Copyright (C) 2006-present eyeo GmbH 2 # Copyright (C) 2006-present eyeo GmbH
3 # 3 #
4 # Adblock Plus is free software: you can redistribute it and/or modify 4 # Adblock Plus is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License version 3 as 5 # it under the terms of the GNU General Public License version 3 as
6 # published by the Free Software Foundation. 6 # published by the Free Software Foundation.
7 # 7 #
8 # Adblock Plus is distributed in the hope that it will be useful, 8 # Adblock Plus is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details. 11 # GNU General Public License for more details.
12 # 12 #
13 # You should have received a copy of the GNU General Public License 13 # You should have received a copy of the GNU General Public License
14 # along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 14 # along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
15 15
16 import contextlib 16 import contextlib
17 import os 17 import os
18 import signal 18 import signal
19 import subprocess 19 import subprocess
20 import time 20 import time
21 import zipfile 21 import zipfile
22 from io import BytesIO 22 from io import BytesIO
23 import urllib2
24 import traceback
23 25
24 import pytest 26 import pytest
25 27
26 28
27 def get_dir_contents(path): 29 def get_dir_contents(path):
28 # TODO: This function is duplicated in test_page_outputs.py. 30 # TODO: This function is duplicated in test_page_outputs.py.
29 dirdata = {} 31 dirdata = {}
30 for dirpath, dirnames, filenames in os.walk(path): 32 for dirpath, dirnames, filenames in os.walk(path):
31 for output_file in filenames: 33 for output_file in filenames:
32 filepath = os.path.join(dirpath, output_file) 34 filepath = os.path.join(dirpath, output_file)
33 with open(filepath) as f: 35 with open(filepath) as f:
34 locale = os.path.split(os.path.split(filepath)[0])[1] 36 locale = os.path.split(os.path.split(filepath)[0])[1]
35 dirdata[os.path.join(locale, output_file)] = f.read().strip() 37 dirdata[os.path.join(locale, output_file)] = f.read().strip()
36 return dirdata 38 return dirdata
37 39
38 40
39 @contextlib.contextmanager 41 @contextlib.contextmanager
40 def run_test_server(site_path): 42 def run_test_server(site_path, new_env=None):
41 """Run test server, yield its URL. Terminate server on next iteration. 43 """Run test server, yield its URL. Terminate server on next iteration.
42 44
43 This function is intended be used in a pytest fixture. 45 This function is intended be used in a pytest fixture.
46
47 Parameters
48 ----------
49 site_path: str
50 The path to the website's source code.
51 new_env: dict
52 The environment under which the server will be run. If `None`, this
53 will be inherited from the main process.
54
55 Returns
56 -------
57 str
58 The url where the server runs.
59
44 """ 60 """
45 args = ['python', 'runserver.py', site_path] 61 args = ['python', 'runserver.py', site_path]
46 # Werkzeug is a dependency of flask which we are using for the mock api 62 # Werkzeug is a dependency of flask which we are using for the mock api
47 # however there is an issue with Werkzeug that prevents it from properly 63 # however there is an issue with Werkzeug that prevents it from properly
48 # handling the SIGTERM sent by p.kill() or terminate() 64 # handling the SIGTERM sent by p.kill() or terminate()
49 # Issue: https://github.com/pallets/werkzeug/issues/58 65 # Issue: https://github.com/pallets/werkzeug/issues/58
50 p = subprocess.Popen(args, stdout=subprocess.PIPE, preexec_fn=os.setsid) 66 p = subprocess.Popen(args, stdout=subprocess.PIPE, preexec_fn=os.setsid,
51 time.sleep(0.5) 67 env=new_env)
68 works, err = _test_server_and_wait()
69 if not works:
70 os.killpg(os.getpgid(p.pid), signal.SIGINT)
Vasily Kuznetsov 2018/10/25 15:51:43 We can get rid of the replication of this line usi
Tudor Avram 2018/10/29 10:42:51 Done.
71 raise Exception('Could not get the server running on `http://localhost'
72 ':5000/`. See traceback:\n{}'.format(err))
52 yield 'http://localhost:5000/' 73 yield 'http://localhost:5000/'
53 os.killpg(os.getpgid(p.pid), signal.SIGTERM) 74 os.killpg(os.getpgid(p.pid), signal.SIGINT)
75
76
77 def _test_server_and_wait():
78 """Test the server started by `run_test_server` and fail after 2s.
79
80 Expects the server to be active at `http://localhost:5000/`.
81
82 Returns
83 -------
84 bool
85 True - if the server works as expected
86 False - otherwise
87 str or None
88 The traceback of the error - if the server connection fails
89 None - otherwise
90
91 Raises
92 ------
93 Exception
94 If the server is not running after retry-ing for 2 seconds.
95
96 """
97 start_time = time.time()
98
99 while True:
100 try:
101 urllib2.urlopen('http://localhost:5000/')
102 return True, None
103 except Exception:
104 time.sleep(.1)
105 if time.time() - start_time > 2:
106 return False, traceback.format_exc()
54 107
55 108
56 def create_in_memory_zip(file_names, file_data): 109 def create_in_memory_zip(file_names, file_data):
57 """Create a BytesIO object with the contents of a zip file. 110 """Create a BytesIO object with the contents of a zip file.
58 111
59 Parameters 112 Parameters
60 ---------- 113 ----------
61 file_names: iterable 114 file_names: iterable
62 Of file names. Should be the full paths of the file inside the zip. 115 Of file names. Should be the full paths of the file inside the zip.
63 file_data: iterable 116 file_data: iterable
(...skipping 13 matching lines...) Expand all
77 130
78 memory_zip.seek(0) 131 memory_zip.seek(0)
79 return memory_zip 132 return memory_zip
80 133
81 134
82 def exception_test(func, exception, exp_msg, *args, **kw): 135 def exception_test(func, exception, exp_msg, *args, **kw):
83 with pytest.raises(exception) as err: 136 with pytest.raises(exception) as err:
84 func(*args, **kw) 137 func(*args, **kw)
85 138
86 assert exp_msg in str(err.value) 139 assert exp_msg in str(err.value)
OLDNEW
« no previous file with comments | « tests/test_page_outputs.py ('k') | tox.ini » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld