Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,43 @@ Run tests in the project's root dir.
```
uv run pytest
```

## Integration tests

`tests/integration/` holds tests that run against third-party Substrait
implementations, which release on their own schedule: pyarrow as a producer whose
output we consume, and DuckDB and DataFusion as consumers of the plans we build.

The default (`addopts` in `pyproject.toml`) deselects `duckdb` and `datafusion`, so
the command above and CI both skip them: handing a lagging consumer a plan built at a
newer spec version can crash the interpreter natively, which no test run can report,
so a red result there is not even reliably a report. **pyarrow runs by default** --
it produces rather than consumes, so it cannot take the process down, and it is the
only place that would notice pyarrow's output shape drifting away from what the
extension-anchor handling assumes.

Select with `-m`, which replaces the default rather than narrowing it:

```
uv run pytest -m integration # every integration test
uv run pytest -m duckdb # just one integration type
uv run pytest -m "integration and not duckdb" # everything except one
```

Mind that `-m` **replaces** the default expression rather than narrowing it, so a `-m`
you meant as a restriction can widen the selection: `-m "not pyarrow"` re-enables
DuckDB and DataFusion, which is the one thing the default exists to prevent. To drop
pyarrow for a single run, skip `-m` and use `uv run pytest
--ignore=tests/integration/test_pyarrow_producer.py`; to drop it for good, add
`and not pyarrow` to the `addopts`.

Naming a path does not select a deselected marker either -- `uv run pytest
tests/integration/` still reports the engine tests as `deselected` until you pass a
`-m`.

The per-type markers are `pyarrow`, `duckdb`, and `datafusion`; each integration test
carries `integration` plus its own, so any one of them can be switched on or off
independently as those projects catch up. If a pyarrow release starts failing, add
`and not pyarrow` to the `addopts` rather than deleting the tests -- they record what
changed. New tests in `tests/integration/` need both markers, and any new marker has
to be registered in `[tool.pytest.ini_options]`.
18 changes: 18 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,24 @@ dev = ["pytest >= 7.0.0", "substrait-antlr==0.99.0", "pyyaml", "sqloxide", "deep
[tool.pytest.ini_options]
pythonpath = "src"
testpaths = "tests"
markers = [
"integration: exercises a third-party Substrait producer or consumer",
"pyarrow: integration test against pyarrow's Substrait output; runs by default",
"duckdb: integration test against duckdb's Substrait consumer; deselected by default",
"datafusion: integration test against datafusion's Substrait consumer; deselected by default",
]
# The default turns off the two integrations that cannot report their own failure, not
# integration testing as a category. DuckDB and DataFusion consume plans this library
# builds, and handing a lagging consumer a plan built at a newer spec version can crash
# the interpreter natively -- so they must not gate a plain `pytest`, which is what CI
# runs. pyarrow goes the other way (it produces, this library consumes), so it cannot
# take the process down and it currently passes: it runs by default, where it can catch
# a pyarrow release drifting away from the output shape the anchor handling assumes.
# Turn it off by adding `and not pyarrow` here if that day comes.
#
# A `-m` on the command line replaces this one rather than being ANDed with it, so
# `-m integration` runs every integration test and `-m duckdb` runs just that one.
addopts = ["-m", "not duckdb and not datafusion"]

[build-system]
requires = ["setuptools>=61.0.0", "setuptools_scm[toml]>=6.2.0"]
Expand Down
Loading