diff --git a/tests/pytest_collection_order.py b/tests/pytest_collection_order.py new file mode 100644 index 00000000..27da81e2 --- /dev/null +++ b/tests/pytest_collection_order.py @@ -0,0 +1,45 @@ +import tomllib +from pathlib import Path + +def _load_order_map(registry_path: Path) -> dict[str, dict[str, int]]: + if not registry_path.exists(): + return {} + with registry_path.open("rb") as f: + data = tomllib.load(f) + files = data.get("files", {}) + out: dict[str, dict[str, int]] = {} + for fname, entry in files.items(): + order_list = entry.get("test_order", []) + if isinstance(order_list, list): + out[fname] = {item["test_id"]: int(item["order"]) for item in order_list} + elif isinstance(order_list, dict): + out[fname] = {k: int(v) for k, v in order_list.items()} + return out + +def sort_items_by_order(items: list, registry_path: Path) -> list: + order_map = _load_order_map(registry_path) + if not order_map: + return list(items) + by_file: dict[str, list] = {} + for it in items: + nodeid = getattr(it, "nodeid", "") + fname = nodeid.split("::", 1)[0] if "::" in nodeid else "" + by_file.setdefault(fname, []).append(it) + out: list = [] + for fname, group in by_file.items(): + fmap = order_map.get(fname) + if not fmap: + out.extend(group) + continue + def _key(it, fmap=fmap, group=group) -> tuple[int, int]: + nid = getattr(it, "nodeid", "") + idx = fmap.get(nid, 1 << 30) + return (idx, group.index(it)) + out.extend(sorted(group, key=_key)) + return out + +def pytest_collection_modifyitems(config, items) -> None: + tests_dir = Path(getattr(config, "rootdir", Path.cwd())) + registry_path = tests_dir / "test_categories.toml" + new_items = sort_items_by_order(list(items), registry_path=registry_path) + items[:] = new_items