Skip to content

Commit 8ac202d

Browse files
tobixenclaude
andcommitted
test: fix RFC6638 scheduling test collection and server config merging
- Rename TestSchedulingBase → _TestSchedulingBase so pytest no longer collects the base class directly (it has _users=[] → noisy skip). The docstring already said "no Test prefix" but the code disagreed. - Teach load_from_config to merge scheduling_users into an already- registered server (case-insensitive name match) instead of registering a duplicate. This allows a caldav_test_servers.yaml entry like: cyrus: scheduling_users: [...] to augment the auto-discovered CyrusTestServer without doubling up. - If a config entry contains only test-metadata keys (scheduling_users, type, enabled) and no matching server is already registered, skip it silently — it is intended to augment a running server, not create a new one (avoids spurious test runs when e.g. Cyrus isn't started locally but the CI-oriented config file is present). - Update CI step to write per-server scheduling_users for both Cyrus and Baikal (instead of the previous global rfc6638_users approach). - Update caldav_test_servers.yaml.example with Baikal and SOGo scheduling_users examples and explain when to use the legacy rfc6638_users fallback. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 11abd77 commit 8ac202d

File tree

4 files changed

+88
-45
lines changed

4 files changed

+88
-45
lines changed

.github/workflows/tests.yaml

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -278,23 +278,33 @@ jobs:
278278
fi
279279
- name: Configure RFC6638 scheduling test users
280280
run: |
281-
# Write test config with rfc6638_users for scheduling tests.
281+
# Write test config with scheduling_users for each server that supports it.
282282
# Cyrus pre-creates user1-user5 (password 'x') with scheduling support.
283283
# Baikal users user1-user3 are in the pre-seeded db.sqlite.
284-
# Two separate config sections for each server; CI uses Cyrus.
284+
# These configs are merged into auto-discovered servers by the registry.
285285
cat > tests/caldav_test_servers.yaml << 'EOF'
286-
# RFC6638 scheduling test users - written by CI
287-
# Cyrus pre-creates user1-user5 with password 'x' and supports scheduling
288-
rfc6638_users:
289-
- url: http://localhost:8802/dav/calendars/user/user1
290-
username: user1
291-
password: x
292-
- url: http://localhost:8802/dav/calendars/user/user2
293-
username: user2
294-
password: x
295-
- url: http://localhost:8802/dav/calendars/user/user3
296-
username: user3
297-
password: x
286+
cyrus:
287+
scheduling_users:
288+
- url: http://localhost:8802/dav/calendars/user/user1
289+
username: user1
290+
password: x
291+
- url: http://localhost:8802/dav/calendars/user/user2
292+
username: user2
293+
password: x
294+
- url: http://localhost:8802/dav/calendars/user/user3
295+
username: user3
296+
password: x
297+
baikal:
298+
scheduling_users:
299+
- url: http://localhost:8800/dav.php/
300+
username: user1
301+
password: testpass1
302+
- url: http://localhost:8800/dav.php/
303+
username: user2
304+
password: testpass2
305+
- url: http://localhost:8800/dav.php/
306+
username: user3
307+
password: testpass3
298308
EOF
299309
- run: tox -e py
300310
env:

tests/caldav_test_servers.yaml.example

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,42 @@ test-servers:
161161
# RFC6638 scheduling test users (optional)
162162
# =========================================================================
163163
#
164-
# For testing calendar scheduling (meeting invites, etc.), define at least
165-
# three users on the same CalDAV server that can send invites to each other.
166-
# This section lives at the TOP LEVEL (not under test-servers).
164+
# Preferred: add scheduling_users inside a server block (as shown for Cyrus
165+
# above). The registry merges it into the already-registered server, and
166+
# pytest generates a TestSchedulingForServer<Name> class automatically.
167+
#
168+
# Baikal (user1-user3 in pre-seeded db.sqlite, passwords testpass1-3):
169+
#
170+
# baikal:
171+
# scheduling_users:
172+
# - url: http://localhost:8800/dav.php/
173+
# username: user1
174+
# password: testpass1
175+
# - url: http://localhost:8800/dav.php/
176+
# username: user2
177+
# password: testpass2
178+
# - url: http://localhost:8800/dav.php/
179+
# username: user3
180+
# password: testpass3
181+
#
182+
# SOGo (user1-user3 from init-sogo-users.sql, passwords testpass1-3):
183+
#
184+
# sogo:
185+
# scheduling_users:
186+
# - url: http://localhost:8803/SOGo/dav/user1
187+
# username: user1
188+
# password: testpass1
189+
# - url: http://localhost:8803/SOGo/dav/user2
190+
# username: user2
191+
# password: testpass2
192+
# - url: http://localhost:8803/SOGo/dav/user3
193+
# username: user3
194+
# password: testpass3
195+
#
196+
# Legacy: top-level rfc6638_users creates a single TestScheduling class
197+
# that is not tied to any specific server in the test run. Prefer the
198+
# per-server scheduling_users approach above.
167199
#
168-
# Cyrus (pre-creates user1-user5 with password 'x'):
169200
# rfc6638_users:
170201
# - url: http://localhost:8802/dav/calendars/user/user1
171202
# username: user1
@@ -176,27 +207,3 @@ test-servers:
176207
# - url: http://localhost:8802/dav/calendars/user/user3
177208
# username: user3
178209
# password: x
179-
#
180-
# Baikal (user1-user3 are in the pre-seeded db.sqlite, passwords testpass1-3):
181-
# rfc6638_users:
182-
# - url: http://localhost:8800/dav.php/
183-
# username: user1
184-
# password: testpass1
185-
# - url: http://localhost:8800/dav.php/
186-
# username: user2
187-
# password: testpass2
188-
# - url: http://localhost:8800/dav.php/
189-
# username: user3
190-
# password: testpass3
191-
#
192-
# SOGo (user1-user3 from init-sogo-users.sql, passwords testpass1-3):
193-
# rfc6638_users:
194-
# - url: http://localhost:8803/SOGo/dav/user1
195-
# username: user1
196-
# password: testpass1
197-
# - url: http://localhost:8803/SOGo/dav/user2
198-
# username: user2
199-
# password: testpass2
200-
# - url: http://localhost:8803/SOGo/dav/user3
201-
# username: user3
202-
# password: testpass3

tests/test_caldav.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ def test_multi_server_meta_section(self) -> None:
670670
assert len(clients) == 2
671671

672672

673-
class TestSchedulingBase:
673+
class _TestSchedulingBase:
674674
"""
675675
Base class for RFC6638 scheduling tests. Not collected directly by
676676
pytest (no ``Test`` prefix); concrete subclasses supply ``_users``.
@@ -793,7 +793,7 @@ def testInviteAndRespond(self):
793793
if rfc6638_users:
794794
TestScheduling = type(
795795
"TestScheduling",
796-
(TestSchedulingBase,),
796+
(_TestSchedulingBase,),
797797
{"_users": rfc6638_users},
798798
)
799799

@@ -3689,6 +3689,6 @@ def testWithEnvironment(self):
36893689
_sched_classname = "TestSchedulingForServer" + _servername
36903690
vars()[_sched_classname] = type(
36913691
_sched_classname,
3692-
(TestSchedulingBase,),
3692+
(_TestSchedulingBase,),
36933693
{"_users": _caldav_server["scheduling_users"]},
36943694
)

tests/test_servers/registry.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,32 @@ def load_from_config(self, config: dict) -> None:
189189
if not server_config.get("enabled", True):
190190
continue
191191

192+
# Keys that only carry test-specific metadata, not connection config.
193+
_TEST_ONLY_KEYS = frozenset({"scheduling_users"})
194+
_META_KEYS = frozenset({"type", "enabled", "name"})
195+
196+
# If an auto-discovered server with the same name (case-insensitive) is
197+
# already registered, merge extra test-only fields (like scheduling_users)
198+
# into it instead of registering a duplicate.
199+
existing_key = next(
200+
(k for k in self._servers if k.lower() == name.lower()), None
201+
)
202+
if existing_key is not None:
203+
if "scheduling_users" in server_config:
204+
self._servers[existing_key].config["scheduling_users"] = server_config[
205+
"scheduling_users"
206+
]
207+
continue
208+
209+
# If the config only contains test-only metadata (no real connection
210+
# params) and there is no existing server to merge into, skip: the
211+
# entry is intended only to augment a running server, not to register
212+
# a new one (e.g. a config written for CI that references Cyrus
213+
# scheduling users but Cyrus isn't started locally).
214+
non_connection_keys = {k for k in server_config if k not in _META_KEYS | _TEST_ONLY_KEYS}
215+
if not non_connection_keys:
216+
continue
217+
192218
server_type = server_config.get("type", name)
193219
server_class = get_server_class(server_type)
194220

0 commit comments

Comments
 (0)