##// END OF EJS Templates
pytest: report vcsserver failures always
super-admin -
r4990:15b1fad9 default
parent child Browse files
Show More
@@ -1,21 +1,21 b''
1 [pytest]
1 [pytest]
2 testpaths = rhodecode
2 testpaths = rhodecode
3 norecursedirs = rhodecode/public rhodecode/templates tests/scripts
3 norecursedirs = rhodecode/public rhodecode/templates tests/scripts
4 cache_dir = /tmp/.pytest_cache
4 cache_dir = /tmp/.pytest_cache
5
5
6 pyramid_config = rhodecode/tests/rhodecode.ini
6 pyramid_config = rhodecode/tests/rhodecode.ini
7 vcsserver_protocol = http
7 vcsserver_protocol = http
8 vcsserver_config_http = rhodecode/tests/vcsserver_http.ini
8 vcsserver_config_http = rhodecode/tests/vcsserver_http.ini
9
9
10 addopts =
10 addopts =
11 --pdbcls=IPython.terminal.debugger:TerminalPdb
11 --pdbcls=IPython.terminal.debugger:TerminalPdb
12 --strict-markers
12 --strict-markers
13 --capture=no
13 --capture=no
14 --show-capture=no
14 --show-capture=all
15
15
16 markers =
16 markers =
17 vcs_operations: Mark tests depending on a running RhodeCode instance.
17 vcs_operations: Mark tests depending on a running RhodeCode instance.
18 xfail_backends: Mark tests as xfail for given backends.
18 xfail_backends: Mark tests as xfail for given backends.
19 skip_backends: Mark tests as skipped for given backends.
19 skip_backends: Mark tests as skipped for given backends.
20 backends: Mark backends
20 backends: Mark backends
21 dbs: database markers for running tests for given DB
21 dbs: database markers for running tests for given DB
@@ -1,200 +1,200 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2020 RhodeCode GmbH
3 # Copyright (C) 2010-2020 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 pytest
21 import pytest
22 from rhodecode.lib import ext_json
22 from rhodecode.lib import ext_json
23
23
24
24
25 pytest_plugins = [
25 pytest_plugins = [
26 "rhodecode.tests.fixture_mods.fixture_pyramid",
26 "rhodecode.tests.fixture_mods.fixture_pyramid",
27 "rhodecode.tests.fixture_mods.fixture_utils",
27 "rhodecode.tests.fixture_mods.fixture_utils",
28 ]
28 ]
29
29
30
30
31 def pytest_configure(config):
31 def pytest_configure(config):
32 from rhodecode.config import patches
32 from rhodecode.config import patches
33
33
34
34
35 def pytest_addoption(parser):
35 def pytest_addoption(parser):
36
36
37 def _parse_json(value):
37 def _parse_json(value):
38 return ext_json.str_json(value) if value else None
38 return ext_json.str_json(value) if value else None
39
39
40 def _split_comma(value):
40 def _split_comma(value):
41 return value.split(',')
41 return value.split(',')
42
42
43 parser.addoption(
43 parser.addoption(
44 '--keep-tmp-path', action='store_true',
44 '--keep-tmp-path', action='store_true',
45 help="Keep the test temporary directories")
45 help="Keep the test temporary directories")
46 parser.addoption(
46 parser.addoption(
47 '--backends', action='store', type=_split_comma,
47 '--backends', action='store', type=_split_comma,
48 default=['git', 'hg', 'svn'],
48 default=['git', 'hg', 'svn'],
49 help="Select which backends to test for backend specific tests.")
49 help="Select which backends to test for backend specific tests.")
50 parser.addoption(
50 parser.addoption(
51 '--dbs', action='store', type=_split_comma,
51 '--dbs', action='store', type=_split_comma,
52 default=['sqlite'],
52 default=['sqlite'],
53 help="Select which database to test for database specific tests. "
53 help="Select which database to test for database specific tests. "
54 "Possible options are sqlite,postgres,mysql")
54 "Possible options are sqlite,postgres,mysql")
55 parser.addoption(
55 parser.addoption(
56 '--appenlight', '--ae', action='store_true',
56 '--appenlight', '--ae', action='store_true',
57 help="Track statistics in appenlight.")
57 help="Track statistics in appenlight.")
58 parser.addoption(
58 parser.addoption(
59 '--appenlight-api-key', '--ae-key',
59 '--appenlight-api-key', '--ae-key',
60 help="API key for Appenlight.")
60 help="API key for Appenlight.")
61 parser.addoption(
61 parser.addoption(
62 '--appenlight-url', '--ae-url',
62 '--appenlight-url', '--ae-url',
63 default="https://ae.rhodecode.com",
63 default="https://ae.rhodecode.com",
64 help="Appenlight service URL, defaults to https://ae.rhodecode.com")
64 help="Appenlight service URL, defaults to https://ae.rhodecode.com")
65 parser.addoption(
65 parser.addoption(
66 '--sqlite-connection-string', action='store',
66 '--sqlite-connection-string', action='store',
67 default='', help="Connection string for the dbs tests with SQLite")
67 default='', help="Connection string for the dbs tests with SQLite")
68 parser.addoption(
68 parser.addoption(
69 '--postgres-connection-string', action='store',
69 '--postgres-connection-string', action='store',
70 default='', help="Connection string for the dbs tests with Postgres")
70 default='', help="Connection string for the dbs tests with Postgres")
71 parser.addoption(
71 parser.addoption(
72 '--mysql-connection-string', action='store',
72 '--mysql-connection-string', action='store',
73 default='', help="Connection string for the dbs tests with MySQL")
73 default='', help="Connection string for the dbs tests with MySQL")
74 parser.addoption(
74 parser.addoption(
75 '--repeat', type=int, default=100,
75 '--repeat', type=int, default=100,
76 help="Number of repetitions in performance tests.")
76 help="Number of repetitions in performance tests.")
77
77
78 parser.addoption(
78 parser.addoption(
79 '--test-loglevel', dest='test_loglevel',
79 '--test-loglevel', dest='test_loglevel',
80 help="Set default Logging level for tests, critical(default), error, warn , info, debug")
80 help="Set default Logging level for tests, critical(default), error, warn , info, debug")
81 group = parser.getgroup('pylons')
81 group = parser.getgroup('pylons')
82 group.addoption(
82 group.addoption(
83 '--with-pylons', dest='pyramid_config',
83 '--with-pylons', dest='pyramid_config',
84 help="Set up a Pylons environment with the specified config file.")
84 help="Set up a Pylons environment with the specified config file.")
85 group.addoption(
85 group.addoption(
86 '--ini-config-override', action='store', type=_parse_json,
86 '--ini-config-override', action='store', type=_parse_json,
87 default=None, dest='pyramid_config_override', help=(
87 default=None, dest='pyramid_config_override', help=(
88 "Overrides the .ini file settings. Should be specified in JSON"
88 "Overrides the .ini file settings. Should be specified in JSON"
89 " format, e.g. '{\"section\": {\"parameter\": \"value\", ...}}'"
89 " format, e.g. '{\"section\": {\"parameter\": \"value\", ...}}'"
90 )
90 )
91 )
91 )
92 parser.addini(
92 parser.addini(
93 'pyramid_config',
93 'pyramid_config',
94 "Set up a Pyramid environment with the specified config file.")
94 "Set up a Pyramid environment with the specified config file.")
95
95
96 vcsgroup = parser.getgroup('vcs')
96 vcsgroup = parser.getgroup('vcs')
97 vcsgroup.addoption(
97 vcsgroup.addoption(
98 '--without-vcsserver', dest='with_vcsserver', action='store_false',
98 '--without-vcsserver', dest='with_vcsserver', action='store_false',
99 help="Do not start the VCSServer in a background process.")
99 help="Do not start the VCSServer in a background process.")
100 vcsgroup.addoption(
100 vcsgroup.addoption(
101 '--with-vcsserver-http', dest='vcsserver_config_http',
101 '--with-vcsserver-http', dest='vcsserver_config_http',
102 help="Start the HTTP VCSServer with the specified config file.")
102 help="Start the HTTP VCSServer with the specified config file.")
103 vcsgroup.addoption(
103 vcsgroup.addoption(
104 '--vcsserver-protocol', dest='vcsserver_protocol',
104 '--vcsserver-protocol', dest='vcsserver_protocol',
105 help="Start the VCSServer with HTTP protocol support.")
105 help="Start the VCSServer with HTTP protocol support.")
106 vcsgroup.addoption(
106 vcsgroup.addoption(
107 '--vcsserver-config-override', action='store', type=_parse_json,
107 '--vcsserver-config-override', action='store', type=_parse_json,
108 default=None, dest='vcsserver_config_override', help=(
108 default=None, dest='vcsserver_config_override', help=(
109 "Overrides the .ini file settings for the VCSServer. "
109 "Overrides the .ini file settings for the VCSServer. "
110 "Should be specified in JSON "
110 "Should be specified in JSON "
111 "format, e.g. '{\"section\": {\"parameter\": \"value\", ...}}'"
111 "format, e.g. '{\"section\": {\"parameter\": \"value\", ...}}'"
112 )
112 )
113 )
113 )
114 vcsgroup.addoption(
114 vcsgroup.addoption(
115 '--vcsserver-port', action='store', type=int,
115 '--vcsserver-port', action='store', type=int,
116 default=None, help=(
116 default=None, help=(
117 "Allows to set the port of the vcsserver. Useful when testing "
117 "Allows to set the port of the vcsserver. Useful when testing "
118 "against an already running server and random ports cause "
118 "against an already running server and random ports cause "
119 "trouble."))
119 "trouble."))
120 parser.addini(
120 parser.addini(
121 'vcsserver_config_http',
121 'vcsserver_config_http',
122 "Start the HTTP VCSServer with the specified config file.")
122 "Start the HTTP VCSServer with the specified config file.")
123 parser.addini(
123 parser.addini(
124 'vcsserver_protocol',
124 'vcsserver_protocol',
125 "Start the VCSServer with HTTP protocol support.")
125 "Start the VCSServer with HTTP protocol support.")
126
126
127
127
128 @pytest.hookimpl(tryfirst=True, hookwrapper=True)
128 @pytest.hookimpl(tryfirst=True, hookwrapper=True)
129 def pytest_runtest_makereport(item, call):
129 def pytest_runtest_makereport(item, call):
130 """
130 """
131 Adding the remote traceback if the exception has this information.
131 Adding the remote traceback if the exception has this information.
132
132
133 VCSServer attaches this information as the attribute `_vcs_server_traceback`
133 VCSServer attaches this information as the attribute `_vcs_server_traceback`
134 to the exception instance.
134 to the exception instance.
135 """
135 """
136 outcome = yield
136 outcome = yield
137 report = outcome.get_result()
137 report = outcome.get_result()
138
138
139 if call.excinfo:
139 if call.excinfo:
140 exc = call.excinfo.value
140 exc = call.excinfo.value
141 vcsserver_traceback = getattr(exc, '_vcs_server_traceback', None)
141 vcsserver_traceback = getattr(exc, '_vcs_server_traceback', None)
142
142
143 if vcsserver_traceback:
143 if vcsserver_traceback and report.outcome == 'failed':
144 section = f'VCSServer remote traceback {report.when}'
144 section = f'VCSServer remote traceback {report.when}'
145 report.sections.append((section, vcsserver_traceback))
145 report.sections.append((section, vcsserver_traceback))
146
146
147
147
148 def pytest_collection_modifyitems(session, config, items):
148 def pytest_collection_modifyitems(session, config, items):
149 # nottest marked, compare nose, used for transition from nose to pytest
149 # nottest marked, compare nose, used for transition from nose to pytest
150 remaining = [
150 remaining = [
151 i for i in items if getattr(i.obj, '__test__', True)]
151 i for i in items if getattr(i.obj, '__test__', True)]
152 items[:] = remaining
152 items[:] = remaining
153
153
154 # NOTE(marcink): custom test ordering, db tests and vcstests are slowes and should
154 # NOTE(marcink): custom test ordering, db tests and vcstests are slowes and should
155 # be executed at the end for faster test feedback
155 # be executed at the end for faster test feedback
156 def sorter(item):
156 def sorter(item):
157 pos = 0
157 pos = 0
158 key = item._nodeid
158 key = item._nodeid
159 if key.startswith('rhodecode/tests/database'):
159 if key.startswith('rhodecode/tests/database'):
160 pos = 1
160 pos = 1
161 elif key.startswith('rhodecode/tests/vcs_operations'):
161 elif key.startswith('rhodecode/tests/vcs_operations'):
162 pos = 2
162 pos = 2
163
163
164 return pos
164 return pos
165
165
166 items.sort(key=sorter)
166 items.sort(key=sorter)
167
167
168
168
169 def get_backends_from_metafunc(metafunc):
169 def get_backends_from_metafunc(metafunc):
170 requested_backends = set(metafunc.config.getoption('--backends'))
170 requested_backends = set(metafunc.config.getoption('--backends'))
171 backend_mark = metafunc.definition.get_closest_marker('backends')
171 backend_mark = metafunc.definition.get_closest_marker('backends')
172 if backend_mark:
172 if backend_mark:
173 # Supported backends by this test function, created from
173 # Supported backends by this test function, created from
174 # pytest.mark.backends
174 # pytest.mark.backends
175 backends = backend_mark.args
175 backends = backend_mark.args
176 elif hasattr(metafunc.cls, 'backend_alias'):
176 elif hasattr(metafunc.cls, 'backend_alias'):
177 # Support class attribute "backend_alias", this is mainly
177 # Support class attribute "backend_alias", this is mainly
178 # for legacy reasons for tests not yet using pytest.mark.backends
178 # for legacy reasons for tests not yet using pytest.mark.backends
179 backends = [metafunc.cls.backend_alias]
179 backends = [metafunc.cls.backend_alias]
180 else:
180 else:
181 backends = metafunc.config.getoption('--backends')
181 backends = metafunc.config.getoption('--backends')
182 return requested_backends.intersection(backends)
182 return requested_backends.intersection(backends)
183
183
184
184
185 def pytest_generate_tests(metafunc):
185 def pytest_generate_tests(metafunc):
186
186
187 # Support test generation based on --backend parameter
187 # Support test generation based on --backend parameter
188 if 'backend_alias' in metafunc.fixturenames:
188 if 'backend_alias' in metafunc.fixturenames:
189 backends = get_backends_from_metafunc(metafunc)
189 backends = get_backends_from_metafunc(metafunc)
190 scope = None
190 scope = None
191 if not backends:
191 if not backends:
192 pytest.skip("Not enabled for any of selected backends")
192 pytest.skip("Not enabled for any of selected backends")
193
193
194 metafunc.parametrize('backend_alias', backends, scope=scope)
194 metafunc.parametrize('backend_alias', backends, scope=scope)
195
195
196 backend_mark = metafunc.definition.get_closest_marker('backends')
196 backend_mark = metafunc.definition.get_closest_marker('backends')
197 if backend_mark:
197 if backend_mark:
198 backends = get_backends_from_metafunc(metafunc)
198 backends = get_backends_from_metafunc(metafunc)
199 if not backends:
199 if not backends:
200 pytest.skip("Not enabled for any of selected backends")
200 pytest.skip("Not enabled for any of selected backends")
General Comments 0
You need to be logged in to leave comments. Login now