Skip to content

Commit 173e9a9

Browse files
gforsythcpcloud
authored andcommitted
docs(tests): add API docs for the testing base classes
refactor(tests): more documentation
1 parent e814c6b commit 173e9a9

File tree

8 files changed

+65
-7
lines changed

8 files changed

+65
-7
lines changed

docs/_quarto.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,3 +543,10 @@ quartodoc:
543543
- Options
544544
- Repr
545545
- SQL
546+
547+
- title: Contributing
548+
desc: "Ibis Backend Developer Documentation"
549+
package: ibis.backends.tests.base
550+
contents:
551+
- BackendTest
552+
- ServiceBackendTest

docs/contribute/05_reference.qmd

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
title: "Test Class Reference"
3+
---
4+
5+
This page provides a partial reference to the attributes, methods, properties
6+
and class-level variables that are used to help configure a backend for the Ibis
7+
test suite.
8+
9+
Contributors are encouraged to look over the methods and class-level variables
10+
in `ibis/backends/tests/base.py`.
11+
12+
To add a new backend test configuration import one of `BackendTest` or
13+
`ServiceBackendTest` into a `conftest.py` file with the path
14+
`ibis/backends/{backend_name}/tests/conftest.py`. Then update / override the
15+
relevant class-level variables and methods.
16+
17+
```python
18+
from ibis.backends.tests.base import BackendTest
19+
20+
class TestConf(BackendTest):
21+
"""Backend-specific class with information for testing."""
22+
23+
supports_divide_by_zero = True
24+
supports_floating_modulus = False
25+
returned_timestamp_unit = "us"
26+
supports_structs = True
27+
supports_json = True
28+
check_names = False
29+
force_sort = True
30+
31+
@staticmethod
32+
def connect(*args, **kwargs):
33+
...
34+
```
35+
36+
{{< include ../reference/BackendTest.qmd >}}
37+
{{< include ../reference/ServiceBackendTest.qmd >}}

ibis/backends/bigquery/tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class TestConf(BackendTest):
3434
supports_structs = True
3535
supports_json = True
3636
check_names = False
37-
force_sort_before_comparison = True
37+
force_sort = True
3838
deps = ("google.cloud.bigquery",)
3939

4040
@staticmethod

ibis/backends/clickhouse/tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class TestConf(ServiceBackendTest):
2929
supported_to_timestamp_units = {"s"}
3030
supports_floating_modulus = False
3131
supports_json = False
32-
force_sort_before_comparison = True
32+
force_sort = True
3333
rounding_method = "half_to_even"
3434
data_volume = "/var/lib/clickhouse/user_files/ibis"
3535
service_name = "clickhouse"

ibis/backends/flink/tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
class TestConf(BackendTest):
1313
supports_structs = False
14-
force_sort_before_comparison = True
14+
force_sort = True
1515
deps = "pandas", "pyflink"
1616

1717
@staticmethod

ibis/backends/impala/tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class TestConf(BackendTest):
3131
returned_timestamp_unit = "s"
3232
supports_structs = False
3333
supports_json = False
34-
force_sort_before_comparison = True
34+
force_sort = True
3535
deps = "fsspec", "requests", "impala"
3636

3737
def _load_data(self, **_: Any) -> None:

ibis/backends/tests/base.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class BackendTest(abc.ABC):
5959
"Whether special handling is needed for running a multi-process pytest run."
6060
supports_tpch: bool = False
6161
"Child class defines a `load_tpch` method that loads the required TPC-H tables into a connection."
62-
force_sort_before_comparison = False
62+
force_sort = False
6363
"Sort results before comparing against reference computation."
6464
rounding_method: Literal["away_from_zero", "half_to_even"] = "away_from_zero"
6565
"Name of round method to use for rounding test comparisons."
@@ -163,6 +163,7 @@ def load_data(
163163

164164
@classmethod
165165
def skip_if_missing_deps(cls) -> None:
166+
"""Add an `importorskip` for any missing dependencies."""
166167
for dep in cls.deps:
167168
pytest.importorskip(dep)
168169

@@ -176,7 +177,11 @@ def postload(self, **_): # noqa: B027
176177
def assert_series_equal(
177178
cls, left: pd.Series, right: pd.Series, *args: Any, **kwargs: Any
178179
) -> None:
179-
if cls.force_sort_before_comparison:
180+
"""Compare two Pandas Series, optionally ignoring order, dtype, and column name.
181+
182+
`force_sort`, `check_dtype`, and `check_names` are set as class-level variables.
183+
"""
184+
if cls.force_sort:
180185
left = left.sort_values().reset_index(drop=True)
181186
right = right.sort_values().reset_index(drop=True)
182187
kwargs.setdefault("check_dtype", cls.check_dtype)
@@ -187,7 +192,11 @@ def assert_series_equal(
187192
def assert_frame_equal(
188193
cls, left: pd.DataFrame, right: pd.DataFrame, *args: Any, **kwargs: Any
189194
) -> None:
190-
if cls.force_sort_before_comparison:
195+
"""Compare two Pandas DataFrames optionally ignoring order, and dtype.
196+
197+
`force_sort`, and `check_dtype` are set as class-level variables.
198+
"""
199+
if cls.force_sort:
191200
columns = list(set(left.columns) & set(right.columns))
192201
left = left.sort_values(by=columns)
193202
right = right.sort_values(by=columns)
@@ -344,9 +353,14 @@ class ServiceBackendTest(BackendTest):
344353
@property
345354
@abc.abstractmethod
346355
def test_files(self) -> Iterable[Path]:
356+
"""Returns an iterable of test files to load into a Docker container before testing."""
347357
...
348358

349359
def preload(self):
360+
"""Use `docker compose cp` to copy all files from `test_files` into a container.
361+
362+
`service_name` and `data_volume` are set as class-level variables.
363+
"""
350364
service = self.service_name
351365
data_volume = self.data_volume
352366
with concurrent.futures.ThreadPoolExecutor() as e:

0 commit comments

Comments
 (0)