Skip to content

Commit 488cd6d

Browse files
committed
Testing: Demonstrate Python test layer implementations
The patch demonstrates the whole matrix of building test harnesses with Python, using both unittest and pytest, with and without "Testcontainers for Python". It only exercises basic features of the corresponding test adapters. Demonstrating advanced features like test layer parameterization can be added on behalf of subsequent iterations.
1 parent cf2bf38 commit 488cd6d

File tree

19 files changed

+502
-0
lines changed

19 files changed

+502
-0
lines changed

.github/dependabot.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,13 @@ updates:
103103
package-ecosystem: "gradle"
104104
schedule:
105105
interval: "weekly"
106+
107+
- directory: "/testing/testcontainers/python-pytest"
108+
package-ecosystem: "pip"
109+
schedule:
110+
interval: "weekly"
111+
112+
- directory: "/testing/testcontainers/python-unittest"
113+
package-ecosystem: "pip"
114+
schedule:
115+
interval: "weekly"
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: Native Testing with Python
2+
3+
on:
4+
pull_request:
5+
branches: ~
6+
paths:
7+
- '.github/workflows/testing-native-python.yml'
8+
- 'testing/native/python**'
9+
- 'requirements.txt'
10+
push:
11+
branches: [ main ]
12+
paths:
13+
- '.github/workflows/testing-native-python.yml'
14+
- 'testing/native/python**'
15+
- 'requirements.txt'
16+
17+
# Allow job to be triggered manually.
18+
workflow_dispatch:
19+
20+
# Run job each night after CrateDB nightly has been published.
21+
schedule:
22+
- cron: '0 3 * * *'
23+
24+
# Cancel in-progress jobs when pushing to the same branch.
25+
concurrency:
26+
cancel-in-progress: true
27+
group: ${{ github.workflow }}-${{ github.ref }}
28+
29+
jobs:
30+
test:
31+
name: "
32+
Python: ${{ matrix.python-version }}
33+
CrateDB: ${{ matrix.cratedb-version }}
34+
on ${{ matrix.os }}"
35+
runs-on: ${{ matrix.os }}
36+
strategy:
37+
fail-fast: false
38+
matrix:
39+
os: [ 'ubuntu-latest', 'macos-latest' ]
40+
python-version: [ '3.7', '3.11' ]
41+
cratedb-version: [ 'nightly' ]
42+
43+
steps:
44+
45+
- name: Acquire sources
46+
uses: actions/checkout@v4
47+
48+
- name: Set up Python
49+
uses: actions/setup-python@v5
50+
with:
51+
python-version: ${{ matrix.python-version }}
52+
architecture: x64
53+
cache: 'pip'
54+
cache-dependency-path: |
55+
requirements.txt
56+
testing/native/python-pytest/requirements.txt
57+
testing/native/python-unittest/requirements.txt
58+
59+
- name: Install utilities
60+
run: |
61+
pip install -r requirements.txt
62+
63+
- name: Validate testing/native/python-{pytest,unittest}
64+
run: |
65+
ngr test --accept-no-venv testing/native/python-pytest
66+
ngr test --accept-no-venv testing/native/python-unittest
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: Testcontainers for Python
2+
3+
on:
4+
pull_request:
5+
branches: ~
6+
paths:
7+
- '.github/workflows/testing-testcontainers-python.yml'
8+
- 'testing/testcontainers/python**'
9+
- 'requirements.txt'
10+
push:
11+
branches: [ main ]
12+
paths:
13+
- '.github/workflows/testing-testcontainers-python.yml'
14+
- 'testing/testcontainers/python**'
15+
- 'requirements.txt'
16+
17+
# Allow job to be triggered manually.
18+
workflow_dispatch:
19+
20+
# Run job each night after CrateDB nightly has been published.
21+
schedule:
22+
- cron: '0 3 * * *'
23+
24+
# Cancel in-progress jobs when pushing to the same branch.
25+
concurrency:
26+
cancel-in-progress: true
27+
group: ${{ github.workflow }}-${{ github.ref }}
28+
29+
jobs:
30+
test:
31+
name: "
32+
Python: ${{ matrix.python-version }}
33+
CrateDB: ${{ matrix.cratedb-version }}
34+
on ${{ matrix.os }}"
35+
runs-on: ${{ matrix.os }}
36+
strategy:
37+
fail-fast: false
38+
matrix:
39+
os: [ 'ubuntu-latest' ]
40+
python-version: [ '3.7', '3.12' ]
41+
cratedb-version: [ 'nightly' ]
42+
43+
steps:
44+
45+
- name: Acquire sources
46+
uses: actions/checkout@v4
47+
48+
- name: Set up Python
49+
uses: actions/setup-python@v5
50+
with:
51+
python-version: ${{ matrix.python-version }}
52+
architecture: x64
53+
cache: 'pip'
54+
cache-dependency-path: |
55+
requirements.txt
56+
testing/testcontainers/python-pytest/requirements.txt
57+
testing/testcontainers/python-unittest/requirements.txt
58+
59+
- name: Install utilities
60+
run: |
61+
pip install -r requirements.txt
62+
63+
- name: Validate testing/testcontainers/python-{pytest,unittest}
64+
run: |
65+
ngr test --accept-no-venv testing/testcontainers/python-pytest
66+
ngr test --accept-no-venv testing/testcontainers/python-unittest
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Using "pytest-crate" with CrateDB and pytest
2+
3+
[pytest-crate] wraps the CrateDB test layer from [cr8], and provides
4+
a few pytest fixtures to conveniently make it accessible for test
5+
cases based on pytest.
6+
7+
This folder contains example test cases demonstrating how to use the
8+
`crate`, `crate_cursor`, and `crate_cursor` pytest fixtures exported
9+
by [pytest-crate].
10+
11+
> [!TIP]
12+
> Please also refer to the header sections of each of the provided
13+
> example programs, to learn more about what's exactly inside.
14+
15+
16+
## Run Tests
17+
18+
Acquire the `cratedb-examples` repository, and install sandbox and
19+
prerequisites.
20+
```shell
21+
git clone https://github.com/crate/cratedb-examples
22+
cd cratedb-examples
23+
python3 -m venv .venv
24+
source .venv/bin/activate
25+
pip install -r requirements.txt
26+
```
27+
28+
Then, invoke the integration test cases.
29+
```shell
30+
export TC_KEEPALIVE=true
31+
ngr test testing/native/python-pytest
32+
```
33+
34+
Alternatively, you can change your working directory to the selected
35+
test case folder, and run `pytest` inside there.
36+
```shell
37+
cd testing/native/python-pytest
38+
pytest
39+
```
40+
41+
42+
[cr8]: https://pypi.org/project/cr8/
43+
[pytest-crate]: https://pypi.org/project/pytest-crate/
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[tool.pytest.ini_options]
2+
minversion = "2.0"
3+
addopts = """
4+
-rsfEX -p pytester --strict-markers --verbosity=3
5+
--capture=no
6+
"""
7+
log_level = "DEBUG"
8+
log_cli_level = "DEBUG"
9+
testpaths = ["*.py"]
10+
xfail_strict = true
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
crash==0.31.2
2+
pytest<9
3+
pytest-crate==0.3.0
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""
2+
Using "pytest-crate" with CrateDB and pytest
3+
4+
Build test harnesses around CrateDB using the `crate` pytest fixture
5+
exported by `pytest-crate`. In turn, this is using `CrateNode`
6+
exported by `cr8`.
7+
8+
https://pypi.org/project/pytest-crate/
9+
https://pypi.org/project/cr8/
10+
"""
11+
import subprocess
12+
13+
SQL_STATEMENT = "SELECT * FROM sys.summits ORDER BY height DESC LIMIT 3;"
14+
15+
16+
def test_crash(crate):
17+
"""
18+
After provisioning a test instance of CrateDB, invoke `crash`.
19+
"""
20+
http_url = crate.dsn()
21+
command = f"time crash --hosts '{http_url}' --command 'SELECT * FROM sys.summits ORDER BY height DESC LIMIT 3;'"
22+
subprocess.check_call(command, shell=True)
23+
24+
25+
def test_crate(crate):
26+
assert crate.dsn().startswith("http://127.0.0.1:42")
27+
assert "http" in crate.addresses
28+
assert crate.addresses["http"].host == "127.0.0.1"
29+
assert 4300 > crate.addresses["http"].port >= 4200
30+
assert "psql" in crate.addresses
31+
assert crate.addresses["psql"].host == "127.0.0.1"
32+
assert 5500 > crate.addresses["psql"].port >= 5432
33+
assert "transport" in crate.addresses
34+
assert crate.addresses["transport"].host == "127.0.0.1"
35+
assert 4400 > crate.addresses["transport"].port >= 4300
36+
37+
38+
def test_cursor(crate_cursor):
39+
crate_cursor.execute("SELECT 1")
40+
assert crate_cursor.fetchone() == [1]
41+
42+
43+
def test_execute(crate_execute, crate_cursor):
44+
for stmt in [
45+
"CREATE TABLE pytest (name STRING, version INT)",
46+
"INSERT INTO pytest (name, version) VALUES ('test_execute', 1)",
47+
"REFRESH TABLE pytest",
48+
]:
49+
crate_execute(stmt)
50+
crate_cursor.execute("SELECT name, version FROM pytest")
51+
assert crate_cursor.fetchall() == [["test_execute", 1]]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
python-unittest
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Using "cr8" test layers with CrateDB and unittest
2+
3+
[cr8] provides a subsystem to invoke throwaway instances of CrateDB
4+
for testing purposes.
5+
6+
This folder contains example test cases demonstrating how to use the
7+
`create_node` utility function and the `CrateNode` class, exported
8+
by [cr8], within your Python unittest-based test cases.
9+
10+
> [!TIP]
11+
> Please also refer to the header sections of each of the provided
12+
> example programs, to learn more about what's exactly inside.
13+
14+
15+
## Run Tests
16+
17+
Acquire the `cratedb-examples` repository, and install sandbox and
18+
prerequisites.
19+
```shell
20+
git clone https://github.com/crate/cratedb-examples
21+
cd cratedb-examples
22+
python3 -m venv .venv
23+
source .venv/bin/activate
24+
pip install -r requirements.txt
25+
```
26+
27+
Then, invoke the integration test cases.
28+
```shell
29+
export TC_KEEPALIVE=true
30+
ngr test testing/native/python-unittest
31+
```
32+
33+
Alternatively, you can change your working directory to the selected
34+
test case folder, and run `unittest` inside there.
35+
```shell
36+
cd testing/native/python-unittest
37+
python -m unittest -vvv
38+
```
39+
40+
41+
[cr8]: https://pypi.org/project/cr8/
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
cr8==0.25.0
2+
crash==0.31.2
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""
2+
Using "cr8" test layers with CrateDB and unittest
3+
4+
Build test harnesses around CrateDB using the `create_node`
5+
primitive exported by `cr8`.
6+
7+
https://pypi.org/project/cr8/
8+
"""
9+
import subprocess
10+
from unittest import TestCase
11+
12+
from cr8.run_crate import create_node
13+
14+
# Run a testing instance of CrateDB.
15+
# TODO: How to select a nightly release?
16+
cratedb_layer = create_node(version="latest-testing")
17+
18+
SQL_STATEMENT = "SELECT * FROM sys.summits ORDER BY height DESC LIMIT 3;"
19+
20+
21+
def setUpModule():
22+
cratedb_layer.start()
23+
24+
25+
def tearDownModule():
26+
cratedb_layer.stop()
27+
28+
29+
class CrashTest(TestCase):
30+
31+
def test_crash(self):
32+
"""
33+
After provisioning a test instance of CrateDB, invoke `crash`.
34+
"""
35+
http_url = cratedb_layer.http_url
36+
command = f"time crash --hosts '{http_url}' --command '{SQL_STATEMENT}'"
37+
subprocess.check_call(command, shell=True)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Using "Testcontainers for Python" with CrateDB and pytest
2+
3+
[Testcontainers] is an open source framework for providing throwaway,
4+
lightweight instances of databases, message brokers, web browsers, or
5+
just about anything that can run in a Docker container.
6+
7+
This folder contains example test cases demonstrating how to use the
8+
`cratedb_service` pytest fixture exported by [cratedb-toolkit].
9+
10+
> [!TIP]
11+
> Please also refer to the header sections of each of the provided
12+
> example programs, to learn more about what's exactly inside.
13+
14+
15+
## Run Tests
16+
17+
Acquire the `cratedb-examples` repository, and install sandbox and
18+
prerequisites.
19+
```shell
20+
git clone https://github.com/crate/cratedb-examples
21+
cd cratedb-examples
22+
python3 -m venv .venv
23+
source .venv/bin/activate
24+
pip install -r requirements.txt
25+
```
26+
27+
Then, invoke the integration test cases.
28+
```shell
29+
export TC_KEEPALIVE=true
30+
ngr test testing/testcontainers/python-pytest
31+
```
32+
33+
Alternatively, you can change your working directory to the selected
34+
test case folder, and run `pytest` inside there.
35+
```shell
36+
cd testing/testcontainers/python-pytest
37+
pytest
38+
```
39+
40+
41+
[cratedb-toolkit]: https://pypi.org/project/cratedb-toolkit/
42+
[Testcontainers]: https://testcontainers.org/
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[tool.pytest.ini_options]
2+
minversion = "2.0"
3+
addopts = """
4+
-rsfEX -p pytester --strict-markers --verbosity=3
5+
--capture=no
6+
"""
7+
log_level = "DEBUG"
8+
log_cli_level = "DEBUG"
9+
testpaths = ["*.py"]
10+
xfail_strict = true

0 commit comments

Comments
 (0)