Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing: Demonstrate Python test layer implementations #280

Merged
merged 1 commit into from
Feb 12, 2024
Merged
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
20 changes: 20 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,23 @@ updates:
package-ecosystem: "gradle"
schedule:
interval: "weekly"

- directory: "/testing/native/python-pytest"
package-ecosystem: "pip"
schedule:
interval: "weekly"

- directory: "/testing/native/python-unittest"
package-ecosystem: "pip"
schedule:
interval: "weekly"

- directory: "/testing/testcontainers/python-pytest"
package-ecosystem: "pip"
schedule:
interval: "weekly"

- directory: "/testing/testcontainers/python-unittest"
package-ecosystem: "pip"
schedule:
interval: "weekly"
66 changes: 66 additions & 0 deletions .github/workflows/testing-native-python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: Native Testing with Python

on:
pull_request:
branches: ~
paths:
- '.github/workflows/testing-native-python.yml'
- 'testing/native/python**'
- 'requirements.txt'
push:
branches: [ main ]
paths:
- '.github/workflows/testing-native-python.yml'
- 'testing/native/python**'
- 'requirements.txt'

# Allow job to be triggered manually.
workflow_dispatch:

# Run job each night after CrateDB nightly has been published.
schedule:
- cron: '0 3 * * *'

# Cancel in-progress jobs when pushing to the same branch.
concurrency:
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.ref }}

jobs:
test:
name: "
Python: ${{ matrix.python-version }}
CrateDB: ${{ matrix.cratedb-version }}
on ${{ matrix.os }}"
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ 'ubuntu-latest', 'macos-latest' ]
python-version: [ '3.7', '3.11' ]
cratedb-version: [ 'nightly' ]

steps:

- name: Acquire sources
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
architecture: x64
cache: 'pip'
cache-dependency-path: |
requirements.txt
testing/native/python-pytest/requirements.txt
testing/native/python-unittest/requirements.txt

- name: Install utilities
run: |
pip install -r requirements.txt

- name: Validate testing/native/python-{pytest,unittest}
run: |
ngr test --accept-no-venv testing/native/python-pytest
ngr test --accept-no-venv testing/native/python-unittest
66 changes: 66 additions & 0 deletions .github/workflows/testing-testcontainers-python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: Testcontainers for Python

on:
pull_request:
branches: ~
paths:
- '.github/workflows/testing-testcontainers-python.yml'
- 'testing/testcontainers/python**'
- 'requirements.txt'
push:
branches: [ main ]
paths:
- '.github/workflows/testing-testcontainers-python.yml'
- 'testing/testcontainers/python**'
- 'requirements.txt'

# Allow job to be triggered manually.
workflow_dispatch:

# Run job each night after CrateDB nightly has been published.
schedule:
- cron: '0 3 * * *'

# Cancel in-progress jobs when pushing to the same branch.
concurrency:
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.ref }}

jobs:
test:
name: "
Python: ${{ matrix.python-version }}
CrateDB: ${{ matrix.cratedb-version }}
on ${{ matrix.os }}"
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ 'ubuntu-latest' ]
python-version: [ '3.7', '3.12' ]
cratedb-version: [ 'nightly' ]

steps:

- name: Acquire sources
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
architecture: x64
cache: 'pip'
cache-dependency-path: |
requirements.txt
testing/testcontainers/python-pytest/requirements.txt
testing/testcontainers/python-unittest/requirements.txt

- name: Install utilities
run: |
pip install -r requirements.txt

- name: Validate testing/testcontainers/python-{pytest,unittest}
run: |
ngr test --accept-no-venv testing/testcontainers/python-pytest
ngr test --accept-no-venv testing/testcontainers/python-unittest
43 changes: 43 additions & 0 deletions testing/native/python-pytest/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Using "pytest-crate" with CrateDB and pytest

[pytest-crate] wraps the CrateDB test layer from [cr8], and provides
a few pytest fixtures to conveniently make it accessible for test
cases based on pytest.

This folder contains example test cases demonstrating how to use the
`crate`, `crate_cursor`, and `crate_cursor` pytest fixtures exported
by [pytest-crate].

> [!TIP]
> Please also refer to the header sections of each of the provided
> example programs, to learn more about what's exactly inside.


## Run Tests

Acquire the `cratedb-examples` repository, and install sandbox and
prerequisites.
```shell
git clone https://github.com/crate/cratedb-examples
cd cratedb-examples
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```

Then, invoke the integration test cases.
```shell
export TC_KEEPALIVE=true
ngr test testing/native/python-pytest
```

Alternatively, you can change your working directory to the selected
test case folder, and run `pytest` inside there.
```shell
cd testing/native/python-pytest
pytest
```


[cr8]: https://pypi.org/project/cr8/
[pytest-crate]: https://pypi.org/project/pytest-crate/
10 changes: 10 additions & 0 deletions testing/native/python-pytest/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[tool.pytest.ini_options]
minversion = "2.0"
addopts = """
-rsfEX -p pytester --strict-markers --verbosity=3
--capture=no
"""
log_level = "DEBUG"
log_cli_level = "DEBUG"
testpaths = ["*.py"]
xfail_strict = true
3 changes: 3 additions & 0 deletions testing/native/python-pytest/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
crash==0.31.2
pytest<9
pytest-crate==0.3.0
51 changes: 51 additions & 0 deletions testing/native/python-pytest/test_pytest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""
Using "pytest-crate" with CrateDB and pytest

Build test harnesses around CrateDB using the `crate` pytest fixture
exported by `pytest-crate`. In turn, this is using `CrateNode`
exported by `cr8`.

https://pypi.org/project/pytest-crate/
https://pypi.org/project/cr8/
"""
import subprocess

SQL_STATEMENT = "SELECT * FROM sys.summits ORDER BY height DESC LIMIT 3;"


def test_crash(crate):
"""
After provisioning a test instance of CrateDB, invoke `crash`.
"""
http_url = crate.dsn()
command = f"time crash --hosts '{http_url}' --command 'SELECT * FROM sys.summits ORDER BY height DESC LIMIT 3;'"
subprocess.check_call(command, shell=True)


def test_crate(crate):
assert crate.dsn().startswith("http://127.0.0.1:42")
assert "http" in crate.addresses
assert crate.addresses["http"].host == "127.0.0.1"
assert 4300 > crate.addresses["http"].port >= 4200
assert "psql" in crate.addresses
assert crate.addresses["psql"].host == "127.0.0.1"
assert 5500 > crate.addresses["psql"].port >= 5432
assert "transport" in crate.addresses
assert crate.addresses["transport"].host == "127.0.0.1"
assert 4400 > crate.addresses["transport"].port >= 4300


def test_cursor(crate_cursor):
crate_cursor.execute("SELECT 1")
assert crate_cursor.fetchone() == [1]


def test_execute(crate_execute, crate_cursor):
for stmt in [
"CREATE TABLE pytest (name STRING, version INT)",
"INSERT INTO pytest (name, version) VALUES ('test_execute', 1)",
"REFRESH TABLE pytest",
]:
crate_execute(stmt)
crate_cursor.execute("SELECT name, version FROM pytest")
assert crate_cursor.fetchall() == [["test_execute", 1]]
1 change: 1 addition & 0 deletions testing/native/python-unittest/.ngr-type
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
python-unittest
41 changes: 41 additions & 0 deletions testing/native/python-unittest/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Using "cr8" test layers with CrateDB and unittest

[cr8] provides a subsystem to invoke throwaway instances of CrateDB
for testing purposes.

This folder contains example test cases demonstrating how to use the
`create_node` utility function and the `CrateNode` class, exported
by [cr8], within your Python unittest-based test cases.

> [!TIP]
> Please also refer to the header sections of each of the provided
> example programs, to learn more about what's exactly inside.


## Run Tests

Acquire the `cratedb-examples` repository, and install sandbox and
prerequisites.
```shell
git clone https://github.com/crate/cratedb-examples
cd cratedb-examples
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```

Then, invoke the integration test cases.
```shell
export TC_KEEPALIVE=true
ngr test testing/native/python-unittest
```

Alternatively, you can change your working directory to the selected
test case folder, and run `unittest` inside there.
```shell
cd testing/native/python-unittest
python -m unittest -vvv
```


[cr8]: https://pypi.org/project/cr8/
2 changes: 2 additions & 0 deletions testing/native/python-unittest/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cr8==0.25.0
crash==0.31.2
37 changes: 37 additions & 0 deletions testing/native/python-unittest/test_unittest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""
Using "cr8" test layers with CrateDB and unittest

Build test harnesses around CrateDB using the `create_node`
primitive exported by `cr8`.

https://pypi.org/project/cr8/
"""
import subprocess
from unittest import TestCase

from cr8.run_crate import create_node

# Run a testing instance of CrateDB.
# TODO: How to select a nightly release?
cratedb_layer = create_node(version="latest-testing")

SQL_STATEMENT = "SELECT * FROM sys.summits ORDER BY height DESC LIMIT 3;"


def setUpModule():
cratedb_layer.start()


def tearDownModule():
cratedb_layer.stop()


class CrashTest(TestCase):

def test_crash(self):
"""
After provisioning a test instance of CrateDB, invoke `crash`.
"""
http_url = cratedb_layer.http_url
command = f"time crash --hosts '{http_url}' --command '{SQL_STATEMENT}'"
subprocess.check_call(command, shell=True)
42 changes: 42 additions & 0 deletions testing/testcontainers/python-pytest/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Using "Testcontainers for Python" with CrateDB and pytest

[Testcontainers] is an open source framework for providing throwaway,
lightweight instances of databases, message brokers, web browsers, or
just about anything that can run in a Docker container.

This folder contains example test cases demonstrating how to use the
`cratedb_service` pytest fixture exported by [cratedb-toolkit].

> [!TIP]
> Please also refer to the header sections of each of the provided
> example programs, to learn more about what's exactly inside.


## Run Tests

Acquire the `cratedb-examples` repository, and install sandbox and
prerequisites.
```shell
git clone https://github.com/crate/cratedb-examples
cd cratedb-examples
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```

Then, invoke the integration test cases.
```shell
export TC_KEEPALIVE=true
ngr test testing/testcontainers/python-pytest
```

Alternatively, you can change your working directory to the selected
test case folder, and run `pytest` inside there.
```shell
cd testing/testcontainers/python-pytest
pytest
```


[cratedb-toolkit]: https://pypi.org/project/cratedb-toolkit/
[Testcontainers]: https://testcontainers.org/
Loading