Merge 'test.py: suport subfolders' from Artsiom Mishuta

this PR is propper(pythonic) chance of commit 288a47f815

Creating an own folder used to be needed for two reasons:

we want a separate test suite, with its own settings
we want to structure tests, e.g. tablets, raft, schema, gossip.
We've been creating many folders recently. However, test suite
infrastructure is expensive in test.py - each suite has its own
pool of servers, concurrency settings and so on.

Make it possible to structure tests without too many suites,
by supporting subfolders within a suite.

As an example, this PR move mv tests into a separate folder

custom test.py lookup also works.
tests can be run as:

1. ./tools/toolchain/dbuild ./test.py --no-gather-metrics --mode=dev topology_custom/mv/tablets/test_mv_tablets_empty_ip
2. ./tools/toolchain/dbuild ./test.py --no-gather-metrics --mode=dev topology_custom/mv/tablets
3. ./tools/toolchain/dbuild ./test.py --no-gather-metrics --mode=dev topology_custom/mv

Fixes https://github.com/scylladb/scylladb/issues/20570

Closes scylladb/scylladb#22816

* github.com:scylladb/scylladb:
  test.py: move mv tests into a separate folder
  test.py: suport subfolders
This commit is contained in:
Nadav Har'El
2025-02-16 12:36:25 +02:00
13 changed files with 19 additions and 32 deletions

33
test.py
View File

@@ -252,8 +252,9 @@ class TestSuite(ABC):
return []
def build_test_list(self) -> List[str]:
return [os.path.splitext(t.relative_to(self.suite_path))[0] for t in
self.suite_path.glob(self.pattern)]
pattern = self.pattern if isinstance(self.pattern, list) else [self.pattern]
tests = itertools.chain(*[self.suite_path.rglob(i) for i in pattern])
return [os.path.splitext(t.relative_to(self.suite_path))[0] for t in tests]
async def add_test_list(self) -> None:
options = self.options
@@ -583,15 +584,9 @@ class PythonTestSuite(TestSuite):
return create_cluster
def build_test_list(self) -> List[str]:
"""For pytest, search for directories recursively"""
path = self.suite_path
pytests = itertools.chain(path.rglob("*_test.py"), path.rglob("test_*.py"))
return [os.path.splitext(t.relative_to(self.suite_path))[0] for t in pytests]
@property
def pattern(self) -> str:
assert False
return ["*_test.py","test_*.py"]
async def add_test(self, shortname, casename) -> None:
test = PythonTest(self.next_id((shortname, self.suite_key)), shortname, casename, self)
@@ -611,9 +606,6 @@ class CQLApprovalTestSuite(PythonTestSuite):
def __init__(self, path, cfg, options: argparse.Namespace, mode) -> None:
super().__init__(path, cfg, options, mode)
def build_test_list(self) -> List[str]:
return TestSuite.build_test_list(self)
async def add_test(self, shortname: str, casename: str) -> None:
test = CQLApprovalTest(self.next_id((shortname, self.suite_key)), shortname, self)
self.tests.append(test)
@@ -630,20 +622,11 @@ class TopologyTestSuite(PythonTestSuite):
are done per test case.
"""
def build_test_list(self) -> List[str]:
"""Build list of Topology python tests"""
return TestSuite.build_test_list(self)
async def add_test(self, shortname: str, casename: str) -> None:
"""Add test to suite"""
test = TopologyTest(self.next_id((shortname, 'topology', self.mode)), shortname, casename, self)
self.tests.append(test)
@property
def pattern(self) -> str:
"""Python pattern"""
return "test_*.py"
def junit_tests(self):
"""Return an empty list, since topology tests are excluded from an aggregated Junit report to prevent double
count in the CI report"""
@@ -681,15 +664,9 @@ class ToolTestSuite(TestSuite):
def __init__(self, path, cfg: dict, options: argparse.Namespace, mode: str) -> None:
super().__init__(path, cfg, options, mode)
def build_test_list(self) -> List[str]:
"""For pytest, search for directories recursively"""
path = self.suite_path
pytests = itertools.chain(path.rglob("*_test.py"), path.rglob("test_*.py"))
return [os.path.splitext(t.relative_to(self.suite_path))[0] for t in pytests]
@property
def pattern(self) -> str:
assert False
return ["*_test.py", "test_*.py"]
async def add_test(self, shortname, casename) -> None:
test = ToolTest(self.next_id((shortname, self.suite_key)), shortname, self)

View File

@@ -0,0 +1,5 @@
#
# Copyright (C) 2025-present ScyllaDB
#
# SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
#

View File

@@ -0,0 +1,5 @@
#
# Copyright (C) 2025-present ScyllaDB
#
# SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
#

View File

@@ -12,7 +12,7 @@ from test.pylib.util import wait_for_cql_and_get_hosts
from test.pylib.internal_types import ServerInfo
from test.topology.conftest import skip_mode
from .test_alternator import get_alternator, alternator_config, full_query
from test.topology_custom.test_alternator import get_alternator, alternator_config, full_query
import pytest
import asyncio

View File

@@ -18,7 +18,7 @@ import logging
from test.topology.conftest import skip_mode
from test.topology.util import get_topology_coordinator, find_server_by_host_id
from test.topology_custom.test_mv_tablets import get_tablet_replicas
from test.topology_custom.mv.tablets.test_mv_tablets import get_tablet_replicas
logger = logging.getLogger(__name__)

View File

@@ -12,7 +12,7 @@ import logging
from test.topology.conftest import skip_mode
from test.pylib.util import wait_for_view
from test.topology_custom.test_mv_tablets import pin_the_only_tablet, get_tablet_replicas
from test.topology_custom.mv.tablets.test_mv_tablets import pin_the_only_tablet, get_tablet_replicas
from cassandra.cluster import ConsistencyLevel, EXEC_PROFILE_DEFAULT # type: ignore
from cassandra.cqltypes import Int32Type # type: ignore

View File

@@ -11,7 +11,7 @@ import asyncio
import pytest
from test.topology.conftest import skip_mode
from test.pylib.util import wait_for_view, wait_for
from test.topology_custom.test_mv_tablets import pin_the_only_tablet
from test.topology_custom.mv.tablets.test_mv_tablets import pin_the_only_tablet
from test.pylib.tablets import get_tablet_replica
logger = logging.getLogger(__name__)