##// END OF EJS Templates
tests: added special no-newline test name generator
marcink -
r1720:a62461f9 default
parent child Browse files
Show More
@@ -1,251 +1,265 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 os
21 import os
22 import time
22 import time
23 import logging
23 import logging
24 import datetime
24 import datetime
25 import hashlib
25 import hashlib
26 import tempfile
26 import tempfile
27 from os.path import join as jn
27 from os.path import join as jn
28
28
29 from tempfile import _RandomNameSequence
29 from tempfile import _RandomNameSequence
30
30
31 from paste.deploy import loadapp
31 from paste.deploy import loadapp
32 from paste.script.appinstall import SetupCommand
32 from paste.script.appinstall import SetupCommand
33
33
34 import pylons
34 import pylons
35 import pylons.test
35 import pylons.test
36 from pylons import config, url
36 from pylons import config, url
37 from pylons.i18n.translation import _get_translator
37 from pylons.i18n.translation import _get_translator
38 from pylons.util import ContextObj
38 from pylons.util import ContextObj
39
39
40 from routes.util import URLGenerator
40 from routes.util import URLGenerator
41 from nose.plugins.skip import SkipTest
41 from nose.plugins.skip import SkipTest
42 import pytest
42 import pytest
43
43
44 from rhodecode import is_windows
44 from rhodecode import is_windows
45 from rhodecode.config.routing import ADMIN_PREFIX
45 from rhodecode.config.routing import ADMIN_PREFIX
46 from rhodecode.model.meta import Session
46 from rhodecode.model.meta import Session
47 from rhodecode.model.db import User
47 from rhodecode.model.db import User
48 from rhodecode.lib import auth
48 from rhodecode.lib import auth
49 from rhodecode.lib.helpers import flash, link_to
49 from rhodecode.lib.helpers import flash, link_to
50 from rhodecode.lib.utils2 import safe_unicode, safe_str
50 from rhodecode.lib.utils2 import safe_unicode, safe_str
51 from rhodecode.tests.utils import get_session_from_response
51 from rhodecode.tests.utils import get_session_from_response
52
52
53
53
54 log = logging.getLogger(__name__)
54 log = logging.getLogger(__name__)
55
55
56 __all__ = [
56 __all__ = [
57 'get_new_dir', 'TestController', 'SkipTest',
57 'get_new_dir', 'TestController', 'SkipTest',
58 'url', 'link_to', 'ldap_lib_installed', 'clear_all_caches',
58 'url', 'link_to', 'ldap_lib_installed', 'clear_all_caches',
59 'assert_session_flash', 'login_user',
59 'assert_session_flash', 'login_user', 'no_newline_id_generator',
60 'TESTS_TMP_PATH', 'HG_REPO', 'GIT_REPO', 'SVN_REPO',
60 'TESTS_TMP_PATH', 'HG_REPO', 'GIT_REPO', 'SVN_REPO',
61 'NEW_HG_REPO', 'NEW_GIT_REPO',
61 'NEW_HG_REPO', 'NEW_GIT_REPO',
62 'HG_FORK', 'GIT_FORK', 'TEST_USER_ADMIN_LOGIN', 'TEST_USER_ADMIN_PASS',
62 'HG_FORK', 'GIT_FORK', 'TEST_USER_ADMIN_LOGIN', 'TEST_USER_ADMIN_PASS',
63 'TEST_USER_REGULAR_LOGIN', 'TEST_USER_REGULAR_PASS',
63 'TEST_USER_REGULAR_LOGIN', 'TEST_USER_REGULAR_PASS',
64 'TEST_USER_REGULAR_EMAIL', 'TEST_USER_REGULAR2_LOGIN',
64 'TEST_USER_REGULAR_EMAIL', 'TEST_USER_REGULAR2_LOGIN',
65 'TEST_USER_REGULAR2_PASS', 'TEST_USER_REGULAR2_EMAIL', 'TEST_HG_REPO',
65 'TEST_USER_REGULAR2_PASS', 'TEST_USER_REGULAR2_EMAIL', 'TEST_HG_REPO',
66 'TEST_HG_REPO_CLONE', 'TEST_HG_REPO_PULL', 'TEST_GIT_REPO',
66 'TEST_HG_REPO_CLONE', 'TEST_HG_REPO_PULL', 'TEST_GIT_REPO',
67 'TEST_GIT_REPO_CLONE', 'TEST_GIT_REPO_PULL', 'SCM_TESTS',
67 'TEST_GIT_REPO_CLONE', 'TEST_GIT_REPO_PULL', 'SCM_TESTS',
68 ]
68 ]
69
69
70 # Invoke websetup with the current config file
70 # Invoke websetup with the current config file
71 # SetupCommand('setup-app').run([config_file])
71 # SetupCommand('setup-app').run([config_file])
72
72
73 # SOME GLOBALS FOR TESTS
73 # SOME GLOBALS FOR TESTS
74 TEST_DIR = tempfile.gettempdir()
74 TEST_DIR = tempfile.gettempdir()
75
75
76 TESTS_TMP_PATH = jn(TEST_DIR, 'rc_test_%s' % _RandomNameSequence().next())
76 TESTS_TMP_PATH = jn(TEST_DIR, 'rc_test_%s' % _RandomNameSequence().next())
77 TEST_USER_ADMIN_LOGIN = 'test_admin'
77 TEST_USER_ADMIN_LOGIN = 'test_admin'
78 TEST_USER_ADMIN_PASS = 'test12'
78 TEST_USER_ADMIN_PASS = 'test12'
79 TEST_USER_ADMIN_EMAIL = 'test_admin@mail.com'
79 TEST_USER_ADMIN_EMAIL = 'test_admin@mail.com'
80
80
81 TEST_USER_REGULAR_LOGIN = 'test_regular'
81 TEST_USER_REGULAR_LOGIN = 'test_regular'
82 TEST_USER_REGULAR_PASS = 'test12'
82 TEST_USER_REGULAR_PASS = 'test12'
83 TEST_USER_REGULAR_EMAIL = 'test_regular@mail.com'
83 TEST_USER_REGULAR_EMAIL = 'test_regular@mail.com'
84
84
85 TEST_USER_REGULAR2_LOGIN = 'test_regular2'
85 TEST_USER_REGULAR2_LOGIN = 'test_regular2'
86 TEST_USER_REGULAR2_PASS = 'test12'
86 TEST_USER_REGULAR2_PASS = 'test12'
87 TEST_USER_REGULAR2_EMAIL = 'test_regular2@mail.com'
87 TEST_USER_REGULAR2_EMAIL = 'test_regular2@mail.com'
88
88
89 HG_REPO = 'vcs_test_hg'
89 HG_REPO = 'vcs_test_hg'
90 GIT_REPO = 'vcs_test_git'
90 GIT_REPO = 'vcs_test_git'
91 SVN_REPO = 'vcs_test_svn'
91 SVN_REPO = 'vcs_test_svn'
92
92
93 NEW_HG_REPO = 'vcs_test_hg_new'
93 NEW_HG_REPO = 'vcs_test_hg_new'
94 NEW_GIT_REPO = 'vcs_test_git_new'
94 NEW_GIT_REPO = 'vcs_test_git_new'
95
95
96 HG_FORK = 'vcs_test_hg_fork'
96 HG_FORK = 'vcs_test_hg_fork'
97 GIT_FORK = 'vcs_test_git_fork'
97 GIT_FORK = 'vcs_test_git_fork'
98
98
99 ## VCS
99 ## VCS
100 SCM_TESTS = ['hg', 'git']
100 SCM_TESTS = ['hg', 'git']
101 uniq_suffix = str(int(time.mktime(datetime.datetime.now().timetuple())))
101 uniq_suffix = str(int(time.mktime(datetime.datetime.now().timetuple())))
102
102
103 TEST_GIT_REPO = jn(TESTS_TMP_PATH, GIT_REPO)
103 TEST_GIT_REPO = jn(TESTS_TMP_PATH, GIT_REPO)
104 TEST_GIT_REPO_CLONE = jn(TESTS_TMP_PATH, 'vcsgitclone%s' % uniq_suffix)
104 TEST_GIT_REPO_CLONE = jn(TESTS_TMP_PATH, 'vcsgitclone%s' % uniq_suffix)
105 TEST_GIT_REPO_PULL = jn(TESTS_TMP_PATH, 'vcsgitpull%s' % uniq_suffix)
105 TEST_GIT_REPO_PULL = jn(TESTS_TMP_PATH, 'vcsgitpull%s' % uniq_suffix)
106
106
107 TEST_HG_REPO = jn(TESTS_TMP_PATH, HG_REPO)
107 TEST_HG_REPO = jn(TESTS_TMP_PATH, HG_REPO)
108 TEST_HG_REPO_CLONE = jn(TESTS_TMP_PATH, 'vcshgclone%s' % uniq_suffix)
108 TEST_HG_REPO_CLONE = jn(TESTS_TMP_PATH, 'vcshgclone%s' % uniq_suffix)
109 TEST_HG_REPO_PULL = jn(TESTS_TMP_PATH, 'vcshgpull%s' % uniq_suffix)
109 TEST_HG_REPO_PULL = jn(TESTS_TMP_PATH, 'vcshgpull%s' % uniq_suffix)
110
110
111 TEST_REPO_PREFIX = 'vcs-test'
111 TEST_REPO_PREFIX = 'vcs-test'
112
112
113
113
114 # skip ldap tests if LDAP lib is not installed
114 # skip ldap tests if LDAP lib is not installed
115 ldap_lib_installed = False
115 ldap_lib_installed = False
116 try:
116 try:
117 import ldap
117 import ldap
118 ldap_lib_installed = True
118 ldap_lib_installed = True
119 except ImportError:
119 except ImportError:
120 # means that python-ldap is not installed
120 # means that python-ldap is not installed
121 pass
121 pass
122
122
123
123
124 def clear_all_caches():
124 def clear_all_caches():
125 from beaker.cache import cache_managers
125 from beaker.cache import cache_managers
126 for _cache in cache_managers.values():
126 for _cache in cache_managers.values():
127 _cache.clear()
127 _cache.clear()
128
128
129
129
130 def get_new_dir(title):
130 def get_new_dir(title):
131 """
131 """
132 Returns always new directory path.
132 Returns always new directory path.
133 """
133 """
134 from rhodecode.tests.vcs.utils import get_normalized_path
134 from rhodecode.tests.vcs.utils import get_normalized_path
135 name_parts = [TEST_REPO_PREFIX]
135 name_parts = [TEST_REPO_PREFIX]
136 if title:
136 if title:
137 name_parts.append(title)
137 name_parts.append(title)
138 hex_str = hashlib.sha1('%s %s' % (os.getpid(), time.time())).hexdigest()
138 hex_str = hashlib.sha1('%s %s' % (os.getpid(), time.time())).hexdigest()
139 name_parts.append(hex_str)
139 name_parts.append(hex_str)
140 name = '-'.join(name_parts)
140 name = '-'.join(name_parts)
141 path = os.path.join(TEST_DIR, name)
141 path = os.path.join(TEST_DIR, name)
142 return get_normalized_path(path)
142 return get_normalized_path(path)
143
143
144
144
145 @pytest.mark.usefixtures('app', 'index_location')
145 @pytest.mark.usefixtures('app', 'index_location')
146 class TestController(object):
146 class TestController(object):
147
147
148 maxDiff = None
148 maxDiff = None
149
149
150 def log_user(self, username=TEST_USER_ADMIN_LOGIN,
150 def log_user(self, username=TEST_USER_ADMIN_LOGIN,
151 password=TEST_USER_ADMIN_PASS):
151 password=TEST_USER_ADMIN_PASS):
152 self._logged_username = username
152 self._logged_username = username
153 self._session = login_user_session(self.app, username, password)
153 self._session = login_user_session(self.app, username, password)
154 self.csrf_token = auth.get_csrf_token(self._session)
154 self.csrf_token = auth.get_csrf_token(self._session)
155
155
156 return self._session['rhodecode_user']
156 return self._session['rhodecode_user']
157
157
158 def logout_user(self):
158 def logout_user(self):
159 logout_user_session(self.app, auth.get_csrf_token(self._session))
159 logout_user_session(self.app, auth.get_csrf_token(self._session))
160 self.csrf_token = None
160 self.csrf_token = None
161 self._logged_username = None
161 self._logged_username = None
162 self._session = None
162 self._session = None
163
163
164 def _get_logged_user(self):
164 def _get_logged_user(self):
165 return User.get_by_username(self._logged_username)
165 return User.get_by_username(self._logged_username)
166
166
167
167
168 def login_user_session(
168 def login_user_session(
169 app, username=TEST_USER_ADMIN_LOGIN, password=TEST_USER_ADMIN_PASS):
169 app, username=TEST_USER_ADMIN_LOGIN, password=TEST_USER_ADMIN_PASS):
170 from rhodecode.tests.functional.test_login import login_url
170 from rhodecode.tests.functional.test_login import login_url
171 response = app.post(
171 response = app.post(
172 login_url,
172 login_url,
173 {'username': username, 'password': password})
173 {'username': username, 'password': password})
174 if 'invalid user name' in response.body:
174 if 'invalid user name' in response.body:
175 pytest.fail('could not login using %s %s' % (username, password))
175 pytest.fail('could not login using %s %s' % (username, password))
176
176
177 assert response.status == '302 Found'
177 assert response.status == '302 Found'
178 response = response.follow()
178 response = response.follow()
179 assert response.status == '200 OK'
179 assert response.status == '200 OK'
180
180
181 session = get_session_from_response(response)
181 session = get_session_from_response(response)
182 assert 'rhodecode_user' in session
182 assert 'rhodecode_user' in session
183 rc_user = session['rhodecode_user']
183 rc_user = session['rhodecode_user']
184 assert rc_user.get('username') == username
184 assert rc_user.get('username') == username
185 assert rc_user.get('is_authenticated')
185 assert rc_user.get('is_authenticated')
186
186
187 return session
187 return session
188
188
189
189
190 def logout_user_session(app, csrf_token):
190 def logout_user_session(app, csrf_token):
191 from rhodecode.tests.functional.test_login import logut_url
191 from rhodecode.tests.functional.test_login import logut_url
192 app.post(logut_url, {'csrf_token': csrf_token}, status=302)
192 app.post(logut_url, {'csrf_token': csrf_token}, status=302)
193
193
194
194
195 def login_user(app, username=TEST_USER_ADMIN_LOGIN,
195 def login_user(app, username=TEST_USER_ADMIN_LOGIN,
196 password=TEST_USER_ADMIN_PASS):
196 password=TEST_USER_ADMIN_PASS):
197 return login_user_session(app, username, password)['rhodecode_user']
197 return login_user_session(app, username, password)['rhodecode_user']
198
198
199
199
200 def assert_session_flash(response=None, msg=None, category=None):
200 def assert_session_flash(response=None, msg=None, category=None):
201 """
201 """
202 Assert on a flash message in the current session.
202 Assert on a flash message in the current session.
203
203
204 :param msg: Required. The expected message. Will be evaluated if a
204 :param msg: Required. The expected message. Will be evaluated if a
205 :class:`LazyString` is passed in.
205 :class:`LazyString` is passed in.
206 :param response: Optional. For functional testing, pass in the response
206 :param response: Optional. For functional testing, pass in the response
207 object. Otherwise don't pass in any value.
207 object. Otherwise don't pass in any value.
208 :param category: Optional. If passed, the message category will be
208 :param category: Optional. If passed, the message category will be
209 checked as well.
209 checked as well.
210 """
210 """
211 if msg is None:
211 if msg is None:
212 raise ValueError("Parameter msg is required.")
212 raise ValueError("Parameter msg is required.")
213
213
214 messages = flash.pop_messages()
214 messages = flash.pop_messages()
215 msg = _eval_if_lazy(msg)
215 msg = _eval_if_lazy(msg)
216
216
217 assert messages, 'unable to find message `%s` in empty flash list' % msg
217 assert messages, 'unable to find message `%s` in empty flash list' % msg
218 message = messages[0]
218 message = messages[0]
219
219
220 message_text = _eval_if_lazy(message.message)
220 message_text = _eval_if_lazy(message.message)
221
221
222 if msg not in message_text:
222 if msg not in message_text:
223 fail_msg = u'msg `%s` not found in session ' \
223 fail_msg = u'msg `%s` not found in session ' \
224 u'flash: got `%s` (type:%s) instead' % (
224 u'flash: got `%s` (type:%s) instead' % (
225 msg, message_text, type(message_text))
225 msg, message_text, type(message_text))
226
226
227 pytest.fail(safe_str(fail_msg))
227 pytest.fail(safe_str(fail_msg))
228 if category:
228 if category:
229 assert category == message.category
229 assert category == message.category
230
230
231
231
232 def _eval_if_lazy(value):
232 def _eval_if_lazy(value):
233 return value.eval() if hasattr(value, 'eval') else value
233 return value.eval() if hasattr(value, 'eval') else value
234
234
235
235
236 def assert_not_in_session_flash(response, msg, category=None):
236 def assert_not_in_session_flash(response, msg, category=None):
237 assert 'flash' in response.session, 'Response session has no flash key'
237 assert 'flash' in response.session, 'Response session has no flash key'
238 message_category, message_text = response.session['flash'][0]
238 message_category, message_text = response.session['flash'][0]
239 if msg in message_text:
239 if msg in message_text:
240 msg = u'msg `%s` found in session flash: got `%s` instead' % (
240 msg = u'msg `%s` found in session flash: got `%s` instead' % (
241 msg, message_text)
241 msg, message_text)
242 pytest.fail(safe_str(msg))
242 pytest.fail(safe_str(msg))
243 if category:
243 if category:
244 assert category == message_category
244 assert category == message_category
245
245
246
246
247 def assert_session_flash_is_empty(response):
247 def assert_session_flash_is_empty(response):
248 if 'flash' in response.session:
248 if 'flash' in response.session:
249 msg = 'flash messages are present in session:%s' % \
249 msg = 'flash messages are present in session:%s' % \
250 response.session['flash'][0]
250 response.session['flash'][0]
251 pytest.fail(safe_str(msg))
251 pytest.fail(safe_str(msg))
252
253
254 def no_newline_id_generator(test_name):
255 """
256 Generates a test name without spaces or newlines characters. Used for
257 nicer output of progress of test
258 """
259 org_name = test_name
260 test_name = test_name\
261 .replace('\n', '_N') \
262 .replace('\t', '_T') \
263 .replace(' ', '_S')
264
265 return test_name or 'test-with-empty-name'
General Comments 0
You need to be logged in to leave comments. Login now