##// END OF EJS Templates
tests: allow running tests via make file on different databases
marcink -
r2100:f2bf7ee3 default
parent child Browse files
Show More
@@ -1,35 +1,53 b''
1
1
2 .PHONY: clean docs docs-clean docs-cleanup test test-clean test-only web-build
2 .PHONY: clean docs docs-clean docs-cleanup test test-clean test-only test-only-postgres test-only-mysql web-build
3
3
4 WEBPACK=./node_modules/webpack/bin/webpack.js
4 WEBPACK=./node_modules/webpack/bin/webpack.js
5 GRUNT=grunt
5 GRUNT=grunt
6 NODE_PATH=./node_modules
6 NODE_PATH=./node_modules
7
7
8
8
9 clean:
9 clean:
10 make test-clean
10 make test-clean
11 find . -type f \( -iname '*.c' -o -iname '*.pyc' -o -iname '*.so' \) -exec rm '{}' ';'
11 find . -type f \( -iname '*.c' -o -iname '*.pyc' -o -iname '*.so' \) -exec rm '{}' ';'
12
12
13 test:
13 test:
14 make test-clean
14 make test-clean
15 make test-only
15 make test-only
16
16
17 test-clean:
17 test-clean:
18 rm -rf coverage.xml htmlcov junit.xml pylint.log result
18 rm -rf coverage.xml htmlcov junit.xml pylint.log result
19 find . -type d -name "__pycache__" -prune -exec rm -rf '{}' ';'
19 find . -type d -name "__pycache__" -prune -exec rm -rf '{}' ';'
20
20
21 test-only:
21 test-only:
22 PYTHONHASHSEED=random py.test -vv -r xw --cov=rhodecode --cov-report=term-missing --cov-report=html rhodecode
22 PYTHONHASHSEED=random \
23 py.test -x -vv -r xw -p no:sugar --cov=rhodecode \
24 --cov-report=term-missing --cov-report=html \
25 rhodecode
26
27 test-only-mysql:
28 PYTHONHASHSEED=random \
29 py.test -x -vv -r xw -p no:sugar --cov=rhodecode \
30 --cov-report=term-missing --cov-report=html \
31 --ini-config-override='{"app:main": {"sqlalchemy.db1.url": "mysql://root:qweqwe@localhost/rhodecode_test"}}' \
32 rhodecode
33
34 test-only-postgres:
35 PYTHONHASHSEED=random \
36 py.test -x -vv -r xw -p no:sugar --cov=rhodecode \
37 --cov-report=term-missing --cov-report=html \
38 --ini-config-override='{"app:main": {"sqlalchemy.db1.url": "postgresql://postgres:qweqwe@localhost/rhodecode_test"}}' \
39 rhodecode
40
23
41
24 docs:
42 docs:
25 (cd docs; nix-build default.nix -o result; make clean html)
43 (cd docs; nix-build default.nix -o result; make clean html)
26
44
27 docs-clean:
45 docs-clean:
28 (cd docs; make clean)
46 (cd docs; make clean)
29
47
30 docs-cleanup:
48 docs-cleanup:
31 (cd docs; make cleanup)
49 (cd docs; make cleanup)
32
50
33 web-build:
51 web-build:
34 NODE_PATH=$(NODE_PATH) $(GRUNT)
52 NODE_PATH=$(NODE_PATH) $(GRUNT)
35
53
@@ -1,422 +1,422 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import json
21 import json
22 import logging.config
22 import logging.config
23 import os
23 import os
24 import platform
24 import platform
25 import socket
25 import socket
26 import subprocess32
26 import subprocess32
27 import time
27 import time
28 from urllib2 import urlopen, URLError
28 from urllib2 import urlopen, URLError
29
29
30 import configobj
30 import configobj
31 import pylons
31 import pylons
32 import pytest
32 import pytest
33 import webob
33 import webob
34 from beaker.session import SessionObject
34 from beaker.session import SessionObject
35 from paste.deploy import loadapp
35 from paste.deploy import loadapp
36 from pylons.i18n.translation import _get_translator
36 from pylons.i18n.translation import _get_translator
37 from pylons.util import ContextObj
37 from pylons.util import ContextObj
38 from routes.util import URLGenerator
38 from routes.util import URLGenerator
39
39
40 from rhodecode.lib import vcs
40 from rhodecode.lib import vcs
41 from rhodecode.tests.fixture import TestINI
41 from rhodecode.tests.fixture import TestINI
42 import rhodecode
42 import rhodecode
43
43
44
44
45 def _parse_json(value):
45 def _parse_json(value):
46 return json.loads(value) if value else None
46 return json.loads(value) if value else None
47
47
48
48
49 def pytest_addoption(parser):
49 def pytest_addoption(parser):
50 parser.addoption(
50 parser.addoption(
51 '--test-loglevel', dest='test_loglevel',
51 '--test-loglevel', dest='test_loglevel',
52 help="Set default Logging level for tests, warn (default), info, debug")
52 help="Set default Logging level for tests, warn (default), info, debug")
53 group = parser.getgroup('pylons')
53 group = parser.getgroup('pylons')
54 group.addoption(
54 group.addoption(
55 '--with-pylons', dest='pylons_config',
55 '--with-pylons', dest='pylons_config',
56 help="Set up a Pylons environment with the specified config file.")
56 help="Set up a Pylons environment with the specified config file.")
57 group.addoption(
57 group.addoption(
58 '--pylons-config-override', action='store', type=_parse_json,
58 '--ini-config-override', action='store', type=_parse_json,
59 default=None, dest='pylons_config_override', help=(
59 default=None, dest='pylons_config_override', help=(
60 "Overrides the .ini file settings. Should be specified in JSON"
60 "Overrides the .ini file settings. Should be specified in JSON"
61 " format, e.g. '{\"section\": {\"parameter\": \"value\", ...}}'"
61 " format, e.g. '{\"section\": {\"parameter\": \"value\", ...}}'"
62 )
62 )
63 )
63 )
64 parser.addini(
64 parser.addini(
65 'pylons_config',
65 'pylons_config',
66 "Set up a Pylons environment with the specified config file.")
66 "Set up a Pylons environment with the specified config file.")
67
67
68 vcsgroup = parser.getgroup('vcs')
68 vcsgroup = parser.getgroup('vcs')
69 vcsgroup.addoption(
69 vcsgroup.addoption(
70 '--without-vcsserver', dest='with_vcsserver', action='store_false',
70 '--without-vcsserver', dest='with_vcsserver', action='store_false',
71 help="Do not start the VCSServer in a background process.")
71 help="Do not start the VCSServer in a background process.")
72 vcsgroup.addoption(
72 vcsgroup.addoption(
73 '--with-vcsserver-http', dest='vcsserver_config_http',
73 '--with-vcsserver-http', dest='vcsserver_config_http',
74 help="Start the HTTP VCSServer with the specified config file.")
74 help="Start the HTTP VCSServer with the specified config file.")
75 vcsgroup.addoption(
75 vcsgroup.addoption(
76 '--vcsserver-protocol', dest='vcsserver_protocol',
76 '--vcsserver-protocol', dest='vcsserver_protocol',
77 help="Start the VCSServer with HTTP protocol support.")
77 help="Start the VCSServer with HTTP protocol support.")
78 vcsgroup.addoption(
78 vcsgroup.addoption(
79 '--vcsserver-config-override', action='store', type=_parse_json,
79 '--vcsserver-config-override', action='store', type=_parse_json,
80 default=None, dest='vcsserver_config_override', help=(
80 default=None, dest='vcsserver_config_override', help=(
81 "Overrides the .ini file settings for the VCSServer. "
81 "Overrides the .ini file settings for the VCSServer. "
82 "Should be specified in JSON "
82 "Should be specified in JSON "
83 "format, e.g. '{\"section\": {\"parameter\": \"value\", ...}}'"
83 "format, e.g. '{\"section\": {\"parameter\": \"value\", ...}}'"
84 )
84 )
85 )
85 )
86 vcsgroup.addoption(
86 vcsgroup.addoption(
87 '--vcsserver-port', action='store', type=int,
87 '--vcsserver-port', action='store', type=int,
88 default=None, help=(
88 default=None, help=(
89 "Allows to set the port of the vcsserver. Useful when testing "
89 "Allows to set the port of the vcsserver. Useful when testing "
90 "against an already running server and random ports cause "
90 "against an already running server and random ports cause "
91 "trouble."))
91 "trouble."))
92 parser.addini(
92 parser.addini(
93 'vcsserver_config_http',
93 'vcsserver_config_http',
94 "Start the HTTP VCSServer with the specified config file.")
94 "Start the HTTP VCSServer with the specified config file.")
95 parser.addini(
95 parser.addini(
96 'vcsserver_protocol',
96 'vcsserver_protocol',
97 "Start the VCSServer with HTTP protocol support.")
97 "Start the VCSServer with HTTP protocol support.")
98
98
99
99
100 @pytest.fixture(scope='session')
100 @pytest.fixture(scope='session')
101 def vcsserver(request, vcsserver_port, vcsserver_factory):
101 def vcsserver(request, vcsserver_port, vcsserver_factory):
102 """
102 """
103 Session scope VCSServer.
103 Session scope VCSServer.
104
104
105 Tests wich need the VCSServer have to rely on this fixture in order
105 Tests wich need the VCSServer have to rely on this fixture in order
106 to ensure it will be running.
106 to ensure it will be running.
107
107
108 For specific needs, the fixture vcsserver_factory can be used. It allows to
108 For specific needs, the fixture vcsserver_factory can be used. It allows to
109 adjust the configuration file for the test run.
109 adjust the configuration file for the test run.
110
110
111 Command line args:
111 Command line args:
112
112
113 --without-vcsserver: Allows to switch this fixture off. You have to
113 --without-vcsserver: Allows to switch this fixture off. You have to
114 manually start the server.
114 manually start the server.
115
115
116 --vcsserver-port: Will expect the VCSServer to listen on this port.
116 --vcsserver-port: Will expect the VCSServer to listen on this port.
117 """
117 """
118
118
119 if not request.config.getoption('with_vcsserver'):
119 if not request.config.getoption('with_vcsserver'):
120 return None
120 return None
121
121
122 use_http = _use_vcs_http_server(request.config)
122 use_http = _use_vcs_http_server(request.config)
123 return vcsserver_factory(
123 return vcsserver_factory(
124 request, use_http=use_http, vcsserver_port=vcsserver_port)
124 request, use_http=use_http, vcsserver_port=vcsserver_port)
125
125
126
126
127 @pytest.fixture(scope='session')
127 @pytest.fixture(scope='session')
128 def vcsserver_factory(tmpdir_factory):
128 def vcsserver_factory(tmpdir_factory):
129 """
129 """
130 Use this if you need a running vcsserver with a special configuration.
130 Use this if you need a running vcsserver with a special configuration.
131 """
131 """
132
132
133 def factory(request, use_http=True, overrides=(), vcsserver_port=None):
133 def factory(request, use_http=True, overrides=(), vcsserver_port=None):
134
134
135 if vcsserver_port is None:
135 if vcsserver_port is None:
136 vcsserver_port = get_available_port()
136 vcsserver_port = get_available_port()
137
137
138 overrides = list(overrides)
138 overrides = list(overrides)
139 if use_http:
139 if use_http:
140 overrides.append({'server:main': {'port': vcsserver_port}})
140 overrides.append({'server:main': {'port': vcsserver_port}})
141 else:
141 else:
142 overrides.append({'DEFAULT': {'port': vcsserver_port}})
142 overrides.append({'DEFAULT': {'port': vcsserver_port}})
143
143
144 if is_cygwin():
144 if is_cygwin():
145 platform_override = {'DEFAULT': {
145 platform_override = {'DEFAULT': {
146 'beaker.cache.repo_object.type': 'nocache'}}
146 'beaker.cache.repo_object.type': 'nocache'}}
147 overrides.append(platform_override)
147 overrides.append(platform_override)
148
148
149 option_name = 'vcsserver_config_http' if use_http else ''
149 option_name = 'vcsserver_config_http' if use_http else ''
150 override_option_name = 'vcsserver_config_override'
150 override_option_name = 'vcsserver_config_override'
151 config_file = get_config(
151 config_file = get_config(
152 request.config, option_name=option_name,
152 request.config, option_name=option_name,
153 override_option_name=override_option_name, overrides=overrides,
153 override_option_name=override_option_name, overrides=overrides,
154 basetemp=tmpdir_factory.getbasetemp().strpath,
154 basetemp=tmpdir_factory.getbasetemp().strpath,
155 prefix='test_vcs_')
155 prefix='test_vcs_')
156
156
157 print("Using the VCSServer configuration:{}".format(config_file))
157 print("Using the VCSServer configuration:{}".format(config_file))
158 ServerClass = HttpVCSServer if use_http else None
158 ServerClass = HttpVCSServer if use_http else None
159 server = ServerClass(config_file)
159 server = ServerClass(config_file)
160 server.start()
160 server.start()
161
161
162 @request.addfinalizer
162 @request.addfinalizer
163 def cleanup():
163 def cleanup():
164 server.shutdown()
164 server.shutdown()
165
165
166 server.wait_until_ready()
166 server.wait_until_ready()
167 return server
167 return server
168
168
169 return factory
169 return factory
170
170
171
171
172 def is_cygwin():
172 def is_cygwin():
173 return 'cygwin' in platform.system().lower()
173 return 'cygwin' in platform.system().lower()
174
174
175
175
176 def _use_vcs_http_server(config):
176 def _use_vcs_http_server(config):
177 protocol_option = 'vcsserver_protocol'
177 protocol_option = 'vcsserver_protocol'
178 protocol = (
178 protocol = (
179 config.getoption(protocol_option) or
179 config.getoption(protocol_option) or
180 config.getini(protocol_option) or
180 config.getini(protocol_option) or
181 'http')
181 'http')
182 return protocol == 'http'
182 return protocol == 'http'
183
183
184
184
185 def _use_log_level(config):
185 def _use_log_level(config):
186 level = config.getoption('test_loglevel') or 'warn'
186 level = config.getoption('test_loglevel') or 'warn'
187 return level.upper()
187 return level.upper()
188
188
189
189
190 class VCSServer(object):
190 class VCSServer(object):
191 """
191 """
192 Represents a running VCSServer instance.
192 Represents a running VCSServer instance.
193 """
193 """
194
194
195 _args = []
195 _args = []
196
196
197 def start(self):
197 def start(self):
198 print("Starting the VCSServer: {}".format(self._args))
198 print("Starting the VCSServer: {}".format(self._args))
199 self.process = subprocess32.Popen(self._args)
199 self.process = subprocess32.Popen(self._args)
200
200
201 def wait_until_ready(self, timeout=30):
201 def wait_until_ready(self, timeout=30):
202 raise NotImplementedError()
202 raise NotImplementedError()
203
203
204 def shutdown(self):
204 def shutdown(self):
205 self.process.kill()
205 self.process.kill()
206
206
207
207
208 class HttpVCSServer(VCSServer):
208 class HttpVCSServer(VCSServer):
209 """
209 """
210 Represents a running VCSServer instance.
210 Represents a running VCSServer instance.
211 """
211 """
212 def __init__(self, config_file):
212 def __init__(self, config_file):
213 config_data = configobj.ConfigObj(config_file)
213 config_data = configobj.ConfigObj(config_file)
214 self._config = config_data['server:main']
214 self._config = config_data['server:main']
215
215
216 args = ['pserve', config_file]
216 args = ['pserve', config_file]
217 self._args = args
217 self._args = args
218
218
219 @property
219 @property
220 def http_url(self):
220 def http_url(self):
221 template = 'http://{host}:{port}/'
221 template = 'http://{host}:{port}/'
222 return template.format(**self._config)
222 return template.format(**self._config)
223
223
224 def start(self):
224 def start(self):
225 self.process = subprocess32.Popen(self._args)
225 self.process = subprocess32.Popen(self._args)
226
226
227 def wait_until_ready(self, timeout=30):
227 def wait_until_ready(self, timeout=30):
228 host = self._config['host']
228 host = self._config['host']
229 port = self._config['port']
229 port = self._config['port']
230 status_url = 'http://{host}:{port}/status'.format(host=host, port=port)
230 status_url = 'http://{host}:{port}/status'.format(host=host, port=port)
231 start = time.time()
231 start = time.time()
232
232
233 while time.time() - start < timeout:
233 while time.time() - start < timeout:
234 try:
234 try:
235 urlopen(status_url)
235 urlopen(status_url)
236 break
236 break
237 except URLError:
237 except URLError:
238 time.sleep(0.2)
238 time.sleep(0.2)
239 else:
239 else:
240 pytest.exit(
240 pytest.exit(
241 "Starting the VCSServer failed or took more than {} "
241 "Starting the VCSServer failed or took more than {} "
242 "seconds. cmd: `{}`".format(timeout, ' '.join(self._args)))
242 "seconds. cmd: `{}`".format(timeout, ' '.join(self._args)))
243
243
244 def shutdown(self):
244 def shutdown(self):
245 self.process.kill()
245 self.process.kill()
246
246
247
247
248 @pytest.fixture(scope='session')
248 @pytest.fixture(scope='session')
249 def pylons_config(request, tmpdir_factory, rcserver_port, vcsserver_port):
249 def pylons_config(request, tmpdir_factory, rcserver_port, vcsserver_port):
250 option_name = 'pylons_config'
250 option_name = 'pylons_config'
251 log_level = _use_log_level(request.config)
251 log_level = _use_log_level(request.config)
252
252
253 overrides = [
253 overrides = [
254 {'server:main': {'port': rcserver_port}},
254 {'server:main': {'port': rcserver_port}},
255 {'app:main': {
255 {'app:main': {
256 'vcs.server': 'localhost:%s' % vcsserver_port,
256 'vcs.server': 'localhost:%s' % vcsserver_port,
257 # johbo: We will always start the VCSServer on our own based on the
257 # johbo: We will always start the VCSServer on our own based on the
258 # fixtures of the test cases. For the test run it must always be
258 # fixtures of the test cases. For the test run it must always be
259 # off in the INI file.
259 # off in the INI file.
260 'vcs.start_server': 'false',
260 'vcs.start_server': 'false',
261 }},
261 }},
262
262
263 {'handler_console': {
263 {'handler_console': {
264 'class ': 'StreamHandler',
264 'class ': 'StreamHandler',
265 'args ': '(sys.stderr,)',
265 'args ': '(sys.stderr,)',
266 'level': log_level,
266 'level': log_level,
267 }},
267 }},
268
268
269 ]
269 ]
270 if _use_vcs_http_server(request.config):
270 if _use_vcs_http_server(request.config):
271 overrides.append({
271 overrides.append({
272 'app:main': {
272 'app:main': {
273 'vcs.server.protocol': 'http',
273 'vcs.server.protocol': 'http',
274 'vcs.scm_app_implementation': 'http',
274 'vcs.scm_app_implementation': 'http',
275 'vcs.hooks.protocol': 'http',
275 'vcs.hooks.protocol': 'http',
276 }
276 }
277 })
277 })
278
278
279 filename = get_config(
279 filename = get_config(
280 request.config, option_name=option_name,
280 request.config, option_name=option_name,
281 override_option_name='{}_override'.format(option_name),
281 override_option_name='{}_override'.format(option_name),
282 overrides=overrides,
282 overrides=overrides,
283 basetemp=tmpdir_factory.getbasetemp().strpath,
283 basetemp=tmpdir_factory.getbasetemp().strpath,
284 prefix='test_rce_')
284 prefix='test_rce_')
285 return filename
285 return filename
286
286
287
287
288 @pytest.fixture(scope='session')
288 @pytest.fixture(scope='session')
289 def rcserver_port(request):
289 def rcserver_port(request):
290 port = get_available_port()
290 port = get_available_port()
291 print('Using rcserver port {}'.format(port))
291 print('Using rcserver port {}'.format(port))
292 return port
292 return port
293
293
294
294
295 @pytest.fixture(scope='session')
295 @pytest.fixture(scope='session')
296 def vcsserver_port(request):
296 def vcsserver_port(request):
297 port = request.config.getoption('--vcsserver-port')
297 port = request.config.getoption('--vcsserver-port')
298 if port is None:
298 if port is None:
299 port = get_available_port()
299 port = get_available_port()
300 print('Using vcsserver port {}'.format(port))
300 print('Using vcsserver port {}'.format(port))
301 return port
301 return port
302
302
303
303
304 def get_available_port():
304 def get_available_port():
305 family = socket.AF_INET
305 family = socket.AF_INET
306 socktype = socket.SOCK_STREAM
306 socktype = socket.SOCK_STREAM
307 host = '127.0.0.1'
307 host = '127.0.0.1'
308
308
309 mysocket = socket.socket(family, socktype)
309 mysocket = socket.socket(family, socktype)
310 mysocket.bind((host, 0))
310 mysocket.bind((host, 0))
311 port = mysocket.getsockname()[1]
311 port = mysocket.getsockname()[1]
312 mysocket.close()
312 mysocket.close()
313 del mysocket
313 del mysocket
314 return port
314 return port
315
315
316
316
317 @pytest.fixture(scope='session')
317 @pytest.fixture(scope='session')
318 def available_port_factory():
318 def available_port_factory():
319 """
319 """
320 Returns a callable which returns free port numbers.
320 Returns a callable which returns free port numbers.
321 """
321 """
322 return get_available_port
322 return get_available_port
323
323
324
324
325 @pytest.fixture
325 @pytest.fixture
326 def available_port(available_port_factory):
326 def available_port(available_port_factory):
327 """
327 """
328 Gives you one free port for the current test.
328 Gives you one free port for the current test.
329
329
330 Uses "available_port_factory" to retrieve the port.
330 Uses "available_port_factory" to retrieve the port.
331 """
331 """
332 return available_port_factory()
332 return available_port_factory()
333
333
334
334
335 @pytest.fixture(scope='session')
335 @pytest.fixture(scope='session')
336 def pylonsapp(pylons_config, vcsserver, http_environ_session):
336 def pylonsapp(pylons_config, vcsserver, http_environ_session):
337 print("Using the RhodeCode configuration:{}".format(pylons_config))
337 print("Using the RhodeCode configuration:{}".format(pylons_config))
338 logging.config.fileConfig(
338 logging.config.fileConfig(
339 pylons_config, disable_existing_loggers=False)
339 pylons_config, disable_existing_loggers=False)
340 app = _setup_pylons_environment(pylons_config, http_environ_session)
340 app = _setup_pylons_environment(pylons_config, http_environ_session)
341 return app
341 return app
342
342
343
343
344 @pytest.fixture(scope='session')
344 @pytest.fixture(scope='session')
345 def testini_factory(tmpdir_factory, pylons_config):
345 def testini_factory(tmpdir_factory, pylons_config):
346 """
346 """
347 Factory to create an INI file based on TestINI.
347 Factory to create an INI file based on TestINI.
348
348
349 It will make sure to place the INI file in the correct directory.
349 It will make sure to place the INI file in the correct directory.
350 """
350 """
351 basetemp = tmpdir_factory.getbasetemp().strpath
351 basetemp = tmpdir_factory.getbasetemp().strpath
352 return TestIniFactory(basetemp, pylons_config)
352 return TestIniFactory(basetemp, pylons_config)
353
353
354
354
355 class TestIniFactory(object):
355 class TestIniFactory(object):
356
356
357 def __init__(self, basetemp, template_ini):
357 def __init__(self, basetemp, template_ini):
358 self._basetemp = basetemp
358 self._basetemp = basetemp
359 self._template_ini = template_ini
359 self._template_ini = template_ini
360
360
361 def __call__(self, ini_params, new_file_prefix='test'):
361 def __call__(self, ini_params, new_file_prefix='test'):
362 ini_file = TestINI(
362 ini_file = TestINI(
363 self._template_ini, ini_params=ini_params,
363 self._template_ini, ini_params=ini_params,
364 new_file_prefix=new_file_prefix, dir=self._basetemp)
364 new_file_prefix=new_file_prefix, dir=self._basetemp)
365 result = ini_file.create()
365 result = ini_file.create()
366 return result
366 return result
367
367
368
368
369 def get_config(
369 def get_config(
370 config, option_name, override_option_name, overrides=None,
370 config, option_name, override_option_name, overrides=None,
371 basetemp=None, prefix='test'):
371 basetemp=None, prefix='test'):
372 """
372 """
373 Find a configuration file and apply overrides for the given `prefix`.
373 Find a configuration file and apply overrides for the given `prefix`.
374 """
374 """
375 config_file = (
375 config_file = (
376 config.getoption(option_name) or config.getini(option_name))
376 config.getoption(option_name) or config.getini(option_name))
377 if not config_file:
377 if not config_file:
378 pytest.exit(
378 pytest.exit(
379 "Configuration error, could not extract {}.".format(option_name))
379 "Configuration error, could not extract {}.".format(option_name))
380
380
381 overrides = overrides or []
381 overrides = overrides or []
382 config_override = config.getoption(override_option_name)
382 config_override = config.getoption(override_option_name)
383 if config_override:
383 if config_override:
384 overrides.append(config_override)
384 overrides.append(config_override)
385 temp_ini_file = TestINI(
385 temp_ini_file = TestINI(
386 config_file, ini_params=overrides, new_file_prefix=prefix,
386 config_file, ini_params=overrides, new_file_prefix=prefix,
387 dir=basetemp)
387 dir=basetemp)
388
388
389 return temp_ini_file.create()
389 return temp_ini_file.create()
390
390
391
391
392 def _setup_pylons_environment(pylons_config, http_environ):
392 def _setup_pylons_environment(pylons_config, http_environ):
393 current_path = os.getcwd()
393 current_path = os.getcwd()
394 pylonsapp = loadapp(
394 pylonsapp = loadapp(
395 'config:' + pylons_config, relative_to=current_path)
395 'config:' + pylons_config, relative_to=current_path)
396
396
397 # Using rhodecode.CONFIG which is assigned during "load_environment".
397 # Using rhodecode.CONFIG which is assigned during "load_environment".
398 # The indirect approach is used, because "pylonsapp" may actually be
398 # The indirect approach is used, because "pylonsapp" may actually be
399 # the Pyramid application.
399 # the Pyramid application.
400 pylonsapp_config = rhodecode.CONFIG
400 pylonsapp_config = rhodecode.CONFIG
401 _init_stack(pylonsapp_config, environ=http_environ)
401 _init_stack(pylonsapp_config, environ=http_environ)
402
402
403 # For compatibility add the attribute "config" which would be
403 # For compatibility add the attribute "config" which would be
404 # present on the Pylons application.
404 # present on the Pylons application.
405 pylonsapp.config = pylonsapp_config
405 pylonsapp.config = pylonsapp_config
406 return pylonsapp
406 return pylonsapp
407
407
408
408
409 def _init_stack(config=None, environ=None):
409 def _init_stack(config=None, environ=None):
410 if not config:
410 if not config:
411 config = pylons.test.pylonsapp.config
411 config = pylons.test.pylonsapp.config
412 if not environ:
412 if not environ:
413 environ = {}
413 environ = {}
414 pylons.url._push_object(URLGenerator(config['routes.map'], environ or {}))
414 pylons.url._push_object(URLGenerator(config['routes.map'], environ or {}))
415 pylons.app_globals._push_object(config['pylons.app_globals'])
415 pylons.app_globals._push_object(config['pylons.app_globals'])
416 pylons.config._push_object(config)
416 pylons.config._push_object(config)
417 pylons.tmpl_context._push_object(ContextObj())
417 pylons.tmpl_context._push_object(ContextObj())
418 # Initialize a translator for tests that utilize i18n
418 # Initialize a translator for tests that utilize i18n
419 translator = _get_translator(pylons.config.get('lang'))
419 translator = _get_translator(pylons.config.get('lang'))
420 pylons.translator._push_object(translator)
420 pylons.translator._push_object(translator)
421 pylons.session._push_object(SessionObject(environ or {}))
421 pylons.session._push_object(SessionObject(environ or {}))
422 pylons.request._push_object(webob.Request.blank('', environ=environ))
422 pylons.request._push_object(webob.Request.blank('', environ=environ))
General Comments 0
You need to be logged in to leave comments. Login now