From cd3e3dfda2a2690013014e4f94ca4102d6f5b946 Mon Sep 17 00:00:00 2001 From: Andreas Motl Date: Thu, 8 Feb 2024 14:30:17 +0100 Subject: [PATCH] Testing: Demonstrate test utilities with Python --- .github/dependabot.yml | 10 +++ .github/workflows/testing-native-python.yml | 66 +++++++++++++++++++ .../testing-testcontainers-python.yml | 66 +++++++++++++++++++ testing/native/python-pytest/pyproject.toml | 10 +++ testing/native/python-pytest/requirements.txt | 3 + testing/native/python-pytest/test_pytest.py | 46 +++++++++++++ testing/native/python-unittest/.ngr-type | 1 + .../native/python-unittest/requirements.txt | 1 + .../native/python-unittest/test_unittest.py | 33 ++++++++++ .../python-pytest/pyproject.toml | 10 +++ .../python-pytest/requirements.txt | 3 + .../python-pytest/test_pytest.py | 17 +++++ .../testcontainers/python-unittest/.ngr-type | 1 + .../python-unittest/requirements.txt | 2 + .../python-unittest/test_unittest.py | 34 ++++++++++ 15 files changed, 303 insertions(+) create mode 100644 .github/workflows/testing-native-python.yml create mode 100644 .github/workflows/testing-testcontainers-python.yml create mode 100644 testing/native/python-pytest/pyproject.toml create mode 100644 testing/native/python-pytest/requirements.txt create mode 100644 testing/native/python-pytest/test_pytest.py create mode 100644 testing/native/python-unittest/.ngr-type create mode 100644 testing/native/python-unittest/requirements.txt create mode 100644 testing/native/python-unittest/test_unittest.py create mode 100644 testing/testcontainers/python-pytest/pyproject.toml create mode 100644 testing/testcontainers/python-pytest/requirements.txt create mode 100644 testing/testcontainers/python-pytest/test_pytest.py create mode 100644 testing/testcontainers/python-unittest/.ngr-type create mode 100644 testing/testcontainers/python-unittest/requirements.txt create mode 100644 testing/testcontainers/python-unittest/test_unittest.py diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 97d01c3d..a84f6ec3 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -103,3 +103,13 @@ updates: package-ecosystem: "gradle" 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" diff --git a/.github/workflows/testing-native-python.yml b/.github/workflows/testing-native-python.yml new file mode 100644 index 00000000..aa41233c --- /dev/null +++ b/.github/workflows/testing-native-python.yml @@ -0,0 +1,66 @@ +name: 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 diff --git a/.github/workflows/testing-testcontainers-python.yml b/.github/workflows/testing-testcontainers-python.yml new file mode 100644 index 00000000..d7fcec9e --- /dev/null +++ b/.github/workflows/testing-testcontainers-python.yml @@ -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 diff --git a/testing/native/python-pytest/pyproject.toml b/testing/native/python-pytest/pyproject.toml new file mode 100644 index 00000000..eb399722 --- /dev/null +++ b/testing/native/python-pytest/pyproject.toml @@ -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 diff --git a/testing/native/python-pytest/requirements.txt b/testing/native/python-pytest/requirements.txt new file mode 100644 index 00000000..642ad119 --- /dev/null +++ b/testing/native/python-pytest/requirements.txt @@ -0,0 +1,3 @@ +crash==0.31.2 +pytest<9 +pytest-crate==0.3.0 diff --git a/testing/native/python-pytest/test_pytest.py b/testing/native/python-pytest/test_pytest.py new file mode 100644 index 00000000..fba2f541 --- /dev/null +++ b/testing/native/python-pytest/test_pytest.py @@ -0,0 +1,46 @@ +""" +Verify CrateDB test fixtures exported by `pytest-crate`. + +https://pypi.org/project/pytest-crate/ +""" +import shlex +import subprocess + + +def run(command: str): + subprocess.check_call(shlex.split(command)) + + +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]] + + +def test_crash(crate): + http_url = crate.dsn() + cmd = f"time crash --hosts '{http_url}' --command 'SELECT * FROM sys.summits ORDER BY height DESC LIMIT 3;'" + run(cmd) diff --git a/testing/native/python-unittest/.ngr-type b/testing/native/python-unittest/.ngr-type new file mode 100644 index 00000000..d225aa5c --- /dev/null +++ b/testing/native/python-unittest/.ngr-type @@ -0,0 +1 @@ +python-unittest diff --git a/testing/native/python-unittest/requirements.txt b/testing/native/python-unittest/requirements.txt new file mode 100644 index 00000000..bf11ad73 --- /dev/null +++ b/testing/native/python-unittest/requirements.txt @@ -0,0 +1 @@ +cr8==0.25.0 diff --git a/testing/native/python-unittest/test_unittest.py b/testing/native/python-unittest/test_unittest.py new file mode 100644 index 00000000..1751528d --- /dev/null +++ b/testing/native/python-unittest/test_unittest.py @@ -0,0 +1,33 @@ +""" +Verify CrateDB test layer exported by `cr8`. + +https://pypi.org/project/cr8/ +""" +import shlex +import subprocess +from unittest import TestCase + +from cr8.run_crate import create_node + + +cratedb_layer = create_node(version="latest-testing") + + +def run(command: str): + subprocess.check_call(shlex.split(command)) + + +def setUpModule(): + cratedb_layer.start() + + +def tearDownModule(): + cratedb_layer.stop() + + +class CrashTest(TestCase): + + def test_crash(self): + http_url = cratedb_layer.http_url + cmd = f"time crash --hosts '{http_url}' --command 'SELECT * FROM sys.summits ORDER BY height DESC LIMIT 3;'" + run(cmd) diff --git a/testing/testcontainers/python-pytest/pyproject.toml b/testing/testcontainers/python-pytest/pyproject.toml new file mode 100644 index 00000000..eb399722 --- /dev/null +++ b/testing/testcontainers/python-pytest/pyproject.toml @@ -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 diff --git a/testing/testcontainers/python-pytest/requirements.txt b/testing/testcontainers/python-pytest/requirements.txt new file mode 100644 index 00000000..31c14085 --- /dev/null +++ b/testing/testcontainers/python-pytest/requirements.txt @@ -0,0 +1,3 @@ +crash==0.31.2 +cratedb-toolkit[testing]==0.0.4 +pytest<9 diff --git a/testing/testcontainers/python-pytest/test_pytest.py b/testing/testcontainers/python-pytest/test_pytest.py new file mode 100644 index 00000000..35d6dbce --- /dev/null +++ b/testing/testcontainers/python-pytest/test_pytest.py @@ -0,0 +1,17 @@ +""" +Verify CrateDB with "Testcontainers for Python" exported by `cratedb-toolkit`. + +https://pypi.org/project/cratedb-toolkit/ +""" +import shlex +import subprocess + + +def run(command: str): + subprocess.check_call(shlex.split(command)) + + +def test_crash(cratedb_service): + http_url = cratedb_service.get_http_url() + cmd = f"time crash --hosts '{http_url}' --command 'SELECT * FROM sys.summits ORDER BY height DESC LIMIT 3;'" + run(cmd) diff --git a/testing/testcontainers/python-unittest/.ngr-type b/testing/testcontainers/python-unittest/.ngr-type new file mode 100644 index 00000000..d225aa5c --- /dev/null +++ b/testing/testcontainers/python-unittest/.ngr-type @@ -0,0 +1 @@ +python-unittest diff --git a/testing/testcontainers/python-unittest/requirements.txt b/testing/testcontainers/python-unittest/requirements.txt new file mode 100644 index 00000000..29524e55 --- /dev/null +++ b/testing/testcontainers/python-unittest/requirements.txt @@ -0,0 +1,2 @@ +crash==0.31.2 +cratedb-toolkit[testing]==0.0.4 diff --git a/testing/testcontainers/python-unittest/test_unittest.py b/testing/testcontainers/python-unittest/test_unittest.py new file mode 100644 index 00000000..61604b13 --- /dev/null +++ b/testing/testcontainers/python-unittest/test_unittest.py @@ -0,0 +1,34 @@ +""" +Verify CrateDB with "Testcontainers for Python" exported by `cratedb-toolkit`. + +https://pypi.org/project/cratedb-toolkit/ +""" +import shlex +import subprocess +from unittest import TestCase + +from cratedb_toolkit.testing.testcontainers.cratedb import CrateDBTestAdapter + +cratedb_service = CrateDBTestAdapter() + + +def run(command: str): + subprocess.check_call(shlex.split(command)) + + +def setUpModule(): + cratedb_service.start() + + +def tearDownModule(): + cratedb_service.stop() + + +class CrashTest(TestCase): + def setUp(self): + cratedb_service.reset() + + def test_crash(self): + http_url = cratedb_service.get_http_url() + cmd = f"time crash --hosts '{http_url}' --command 'SELECT * FROM sys.summits ORDER BY height DESC LIMIT 3;'" + run(cmd)