diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index bd0d5d772..f6000e8fa 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -112,6 +112,10 @@ jobs: run: | python test/_helper/setup_testdb.py -u "admin" -p "$COUCHDB_ADMIN_PASSWORD" - name: Test with coverage + unittest + env: + # A CouchDB service container is always started for this job (see `services:` above), so a + # missing or misconfigured CouchDB should fail the build, not silently skip the CouchDB tests. + REQUIRE_COUCHDB_INTEGRATION_TESTS: "1" run: | python -m coverage run --source=basyx -m unittest - name: Report test coverage diff --git a/sdk/test/_helper/setup_testdb.py b/sdk/test/_helper/setup_testdb.py index e5f15d0ae..c093b726f 100755 --- a/sdk/test/_helper/setup_testdb.py +++ b/sdk/test/_helper/setup_testdb.py @@ -13,8 +13,10 @@ setup_testdb.py -u admin -p admin_password -If no CouchDB server at the configured URL, the script will exit with exit code 1. To avoid the error exit code (for use -in CI), provide the ``--failsafe`` option. +If no CouchDB server is reachable at the configured URL, or the test database already exists, the script exits with +exit code 1 by default. CI relies on this to fail fast if the CouchDB service container isn't healthy, rather than +silently continuing into a test run that would just skip the CouchDB-backed tests. For idempotent/local re-runs +where an already-existing database is expected and fine, pass ``--failsafe`` to exit with code 0 instead. """ import argparse diff --git a/sdk/test/_helper/test_helpers.py b/sdk/test/_helper/test_helpers.py index 3633519a1..4dbe47664 100644 --- a/sdk/test/_helper/test_helpers.py +++ b/sdk/test/_helper/test_helpers.py @@ -7,6 +7,7 @@ import base64 import configparser +import os import os.path import urllib.error import urllib.request @@ -20,7 +21,12 @@ ) -# Check if CouchDB database is available. Otherwise, skip tests. +# Set this environment variable, to fail (instead of skip) the CouchDB tests when no CouchDB is reachable +REQUIRE_COUCHDB_INTEGRATION_TESTS = os.environ.get("REQUIRE_COUCHDB_INTEGRATION_TESTS", "false").lower() in { + "1", "true", "yes", +} + +# Check if CouchDB database is available. Otherwise, skip tests (unless REQUIRE_COUCHDB_INTEGRATION_TESTS is set). try: request = urllib.request.Request( "{}/{}".format( diff --git a/sdk/test/backend/test_couchdb.py b/sdk/test/backend/test_couchdb.py index 829ccb889..350ccbc78 100644 --- a/sdk/test/backend/test_couchdb.py +++ b/sdk/test/backend/test_couchdb.py @@ -10,7 +10,12 @@ from basyx.aas.backend import couchdb from basyx.aas.examples.data.example_aas import * -from test._helper.test_helpers import COUCHDB_ERROR, COUCHDB_OKAY, TEST_CONFIG +from test._helper.test_helpers import ( + COUCHDB_ERROR, + COUCHDB_OKAY, + REQUIRE_COUCHDB_INTEGRATION_TESTS, + TEST_CONFIG, +) source_core: str = ( "couchdb://" @@ -22,12 +27,21 @@ @unittest.skipUnless( - COUCHDB_OKAY, + COUCHDB_OKAY or REQUIRE_COUCHDB_INTEGRATION_TESTS, "No CouchDB is reachable at {}/{}: {}".format( TEST_CONFIG["couchdb"]["url"], TEST_CONFIG["couchdb"]["database"], COUCHDB_ERROR ), ) class CouchDBBackendTest(unittest.TestCase): + + @classmethod + def setUpClass(cls) -> None: + if not COUCHDB_OKAY: + raise RuntimeError( + f"REQUIRE_COUCHDB_INTEGRATION_TESTS is set, but no CouchDB is reachable at " + f"{TEST_CONFIG['couchdb']['url']}/{TEST_CONFIG['couchdb']['database']}: {COUCHDB_ERROR}" + ) + def setUp(self) -> None: self.couch_identifiable_store = couchdb.CouchDBIdentifiableStore( TEST_CONFIG["couchdb"]["url"], TEST_CONFIG["couchdb"]["database"]