Skip to content
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
16 changes: 12 additions & 4 deletions .github/workflows/ci-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ jobs:
#CACHIER_TEST_DB: "dummy_db"
#CACHIER_TEST_USERNAME: "myuser"
#CACHIER_TEST_PASSWORD: "yourpassword"
CACHIER_TEST_VS_DOCKERIZED_MONGO: "true"
CACHIER_TEST_REDIS_HOST: "localhost"
CACHIER_TEST_REDIS_PORT: "6379"
CACHIER_TEST_REDIS_DB: "0"
Expand Down Expand Up @@ -137,7 +136,7 @@ jobs:
# prefix-key: "mongo-db"
# images: mongo:8
- name: Start MongoDB in docker
if: matrix.backend == 'mongodb'
if: matrix.backend == 'mongodb' && runner.os != 'Windows'
run: |
# start MongoDB in a container
docker run -d -p ${{ env.CACHIER_TEST_PORT }}:27017 --name mongodb mongo:8
Expand All @@ -146,9 +145,18 @@ jobs:
# show running containers
docker ps -a

- name: Unit tests (DB)
if: matrix.backend == 'mongodb'
- name: Unit tests (MongoDB, Docker)
if: matrix.backend == 'mongodb' && runner.os != 'Windows'
env:
CACHIER_TEST_VS_DOCKERIZED_MONGO: "true"
run: pytest -m "mongo" --cov=cachier --cov-report=term --cov-report=xml:cov.xml

- name: Unit tests (MongoDB, in-memory)
if: matrix.backend == 'mongodb' && runner.os == 'Windows'
env:
CACHIER_TEST_VS_DOCKERIZED_MONGO: "false"
run: pytest -m "mongo" --cov=cachier --cov-report=term --cov-report=xml:cov.xml

- name: Speed eval
run: python tests/speed_eval.py

Expand Down
6 changes: 3 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -853,11 +853,11 @@ This script automatically handles Docker container lifecycle, environment variab
# Clean up
docker stop cachier-test-mongo && docker rm cachier-test-mongo

**CI Environment:** The ``CACHIER_TEST_VS_DOCKERIZED_MONGO`` environment variable is set to ``True`` in the GitHub Actions CI environment, which runs tests against a real MongoDB instance on every commit and pull request.
**CI Environment:** GitHub Actions runs MongoDB tests against a real Dockerized MongoDB instance on Linux. Windows MongoDB jobs use the in-memory MongoDB backend because GitHub-hosted Windows runners do not provide a stable Docker daemon for Linux MongoDB containers.

Contributors are encouraged to test against a real MongoDB instance before submitting PRs to ensure compatibility, though the in-memory MongoDB instance serves as a good proxy for most development.
Contributors are encouraged to test against a real MongoDB instance before submitting PRs to ensure compatibility, though the in-memory MongoDB instance serves as a good proxy for most development and CI platform coverage.

**HOWEVER, the tests run against a live MongoDB instance when you submit a PR are the determining tests for deciding whether your code functions correctly against MongoDB.**
**HOWEVER, only the Linux MongoDB CI jobs are live-server integration tests. Windows MongoDB CI jobs still exercise the Mongo backend API surface, but they are compatibility coverage over ``pymongo_inmemory`` rather than proof of live MongoDB server behavior.**


Testing all backends locally
Expand Down
55 changes: 48 additions & 7 deletions scripts/test-local.sh
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,28 @@ check_dependencies() {
print_message $GREEN "All required dependencies are installed!"
}

run_pytest_phase() {
local phase_name="$1"
shift

print_message $BLUE "Running $phase_name: $(printf '%q ' "$@")"

local phase_exit_code=0
if "$@"; then
phase_exit_code=0
else
phase_exit_code=$?
fi

if [ "$phase_exit_code" -eq 0 ]; then
print_message $GREEN "$phase_name passed"
else
print_message $RED "$phase_name failed with exit code $phase_exit_code"
fi

return "$phase_exit_code"
}

# MongoDB functions
start_mongodb() {
print_message $YELLOW "Starting MongoDB container..."
Expand Down Expand Up @@ -613,23 +635,42 @@ EOF
PYTEST_ARGS+=(--cov=cachier --cov-report="$COVERAGE_REPORT")
SERIAL_PYTEST_ARGS+=(--cov=cachier --cov-report="$COVERAGE_REPORT" --cov-append)

# Print and run the command
print_message $BLUE "Running: $(printf '%q ' "${PYTEST_ARGS[@]}")"
"${PYTEST_ARGS[@]}"
MAIN_TEST_EXIT_CODE=0
SERIAL_TEST_EXIT_CODE=0
MAIN_TEST_STATUS="skipped"
SERIAL_TEST_STATUS="skipped"

if run_pytest_phase "main pytest phase" "${PYTEST_ARGS[@]}"; then
MAIN_TEST_EXIT_CODE=0
MAIN_TEST_STATUS="passed"
else
MAIN_TEST_EXIT_CODE=$?
MAIN_TEST_STATUS="failed ($MAIN_TEST_EXIT_CODE)"
fi

if [ "$run_serial_local_tests" = true ]; then
print_message $BLUE "Running serial local tests (pickle, memory) with: $(printf '%q ' "${SERIAL_PYTEST_ARGS[@]}")"
"${SERIAL_PYTEST_ARGS[@]}"
if run_pytest_phase "serial local pytest phase" "${SERIAL_PYTEST_ARGS[@]}"; then
SERIAL_TEST_EXIT_CODE=0
SERIAL_TEST_STATUS="passed"
else
SERIAL_TEST_EXIT_CODE=$?
SERIAL_TEST_STATUS="failed ($SERIAL_TEST_EXIT_CODE)"
fi
else
print_message $BLUE "Skipping serial local tests (pickle, memory) since not requested"
fi

TEST_EXIT_CODE=$?
TEST_EXIT_CODE=0
if [ "$MAIN_TEST_EXIT_CODE" -ne 0 ]; then
TEST_EXIT_CODE=$MAIN_TEST_EXIT_CODE
elif [ "$SERIAL_TEST_EXIT_CODE" -ne 0 ]; then
TEST_EXIT_CODE=$SERIAL_TEST_EXIT_CODE
fi

if [ $TEST_EXIT_CODE -eq 0 ]; then
print_message $GREEN "All tests passed!"
else
print_message $RED "Some tests failed. Exit code: $TEST_EXIT_CODE"
print_message $RED "Some tests failed. Main phase: $MAIN_TEST_STATUS, serial local phase: $SERIAL_TEST_STATUS"
fi

# Exit with test status
Expand Down
14 changes: 13 additions & 1 deletion tests/mongo_tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import platform
import sys
import warnings
from contextlib import suppress
from typing import Any
from urllib.parse import quote_plus

from birch import Birch # type: ignore[import-not-found]
Expand Down Expand Up @@ -41,6 +43,16 @@ class CfgKey:
_COLLECTION_NAME = f"cachier_test_{platform.system()}_{'.'.join(map(str, sys.version_info[:3]))}"


def _build_inmemory_mongo_client() -> Any:
with warnings.catch_warnings():
warnings.filterwarnings(
"ignore",
message="Python 3.14 will, by default, filter extracted tar archives.*",
category=DeprecationWarning,
)
return InMemoryMongoClient()


def _get_cachier_db_mongo_client():
host = quote_plus(CFG[CfgKey.HOST])
port = quote_plus(CFG[CfgKey.PORT])
Expand All @@ -55,7 +67,7 @@ def _test_mongetter():
_test_mongetter.client = _get_cachier_db_mongo_client()
else:
print("Using in-memory MongoDB instance for testing.")
_test_mongetter.client = InMemoryMongoClient()
_test_mongetter.client = _build_inmemory_mongo_client()
db_obj = _test_mongetter.client["cachier_test"]
if _COLLECTION_NAME not in db_obj.list_collection_names():
db_obj.create_collection(_COLLECTION_NAME)
Expand Down
Loading