Skip to content

Commit

Permalink
Merge pull request #757 from WisdomPill/parallel_tests
Browse files Browse the repository at this point in the history
  • Loading branch information
WisdomPill authored Jan 4, 2025
2 parents c076898 + f9f5d0c commit ed27999
Show file tree
Hide file tree
Showing 25 changed files with 577 additions and 546 deletions.
15 changes: 5 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,13 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade tox tox-gh-actions
python -m pip install --upgrade tox-uv tox-gh-actions
- name: Docker compose up
run: docker compose -f docker/docker-compose.yml up -d --wait

- name: Tox tests
run: |
REDIS_PRIMARY=$(tests/start_redis.sh)
REDIS_SENTINEL=$(tests/start_redis.sh --sentinel)
CONTAINERS="$REDIS_PRIMARY $REDIS_SENTINEL"
trap "docker stop $CONTAINERS && docker rm $CONTAINERS" EXIT
tests/wait_for_redis.sh $REDIS_PRIMARY 6379
tests/wait_for_redis.sh $REDIS_SENTINEL 26379
tox
run: tox
env:
DJANGO: ${{ matrix.django-version }}
REDIS: ${{ matrix.redis-version }}
Expand Down
4 changes: 4 additions & 0 deletions changelog.d/757.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Speed up tests by using `pytest-xdist` and separating settings on different redis databases.
Dropped `pytest-django`
Using `docker-compose` for setting up redis containers for testing
Use `tox-uv`
30 changes: 30 additions & 0 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
services:

redis:
image: redis:latest
container_name: redis-primary
command: redis-server --enable-debug-command yes --protected-mode no
ports:
- 6379:6379
healthcheck:
test: redis-cli ping
interval: 5s
timeout: 5s
retries: 5

sentinel:
image: redis:latest
container_name: redis-sentinel
depends_on:
redis:
condition: service_healthy
entrypoint: "redis-sentinel /redis.conf --port 26379"
ports:
- 26379:26379
volumes:
- "./sentinel.conf:/redis.conf"
healthcheck:
test: redis-cli -p 26379 ping
interval: 5s
timeout: 5s
retries: 5
4 changes: 4 additions & 0 deletions docker/sentinel.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
sentinel monitor default_service 127.0.0.1 6379 1
sentinel down-after-milliseconds default_service 3200
sentinel failover-timeout default_service 10000
sentinel parallel-syncs default_service 1
32 changes: 7 additions & 25 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -85,20 +85,7 @@ REDIS =
[testenv]
passenv = CI, GITHUB*
commands =
{envpython} -m pytest --cov-report= --ds=settings.sqlite {posargs}
{envpython} -m pytest --cov-append --cov-report= --ds=settings.sqlite_herd {posargs}
{envpython} -m pytest --cov-append --cov-report= --ds=settings.sqlite_json {posargs}
{envpython} -m pytest --cov-append --cov-report= --ds=settings.sqlite_lz4 {posargs}
{envpython} -m pytest --cov-append --cov-report= --ds=settings.sqlite_msgpack {posargs}
{envpython} -m pytest --cov-append --cov-report= --ds=settings.sqlite_sentinel {posargs}
{envpython} -m pytest --cov-append --cov-report= --ds=settings.sqlite_sentinel_opts {posargs}
{envpython} -m pytest --cov-append --cov-report= --ds=settings.sqlite_sharding {posargs}
{envpython} -m pytest --cov-append --cov-report= --ds=settings.sqlite_usock {posargs}
{envpython} -m pytest --cov-append --cov-report= --ds=settings.sqlite_zlib {posargs}
{envpython} -m pytest --cov-append --cov-report= --ds=settings.sqlite_zstd {posargs}
{envpython} -m pytest --cov-append --cov-report= --ds=settings.sqlite_gzip {posargs}
{envpython} -m coverage report
{envpython} -m coverage xml
{envpython} -m pytest -n 4 {posargs}

deps =
dj42: Django>=4.2,<5.0
Expand All @@ -108,9 +95,9 @@ deps =
msgpack>=0.6.0
pytest
pytest-cov
pytest-django
pytest-pythonpath
pytest-mock
pytest-pythonpath
pytest-xdist
redismaster: https://github.com/redis/redis-py/archive/master.tar.gz
lz4>=0.15
pyzstd>=0.15
Expand All @@ -119,7 +106,7 @@ deps =
basepython = python3
envdir={toxworkdir}/lint
commands =
black: black --target-version py36 {posargs:--check --diff} setup.py django_redis/ tests/
black: black --target-version py38 {posargs:--check --diff} setup.py django_redis/ tests/
ruff: ruff {posargs:check --show-fixes} django_redis/ tests/
mypy: mypy {posargs:--cobertura-xml-report .} django_redis tests
deps =
Expand All @@ -130,24 +117,16 @@ deps =
mypy
# typing dependencies
pytest
pytest-django
pytest-mock
types-redis
skip_install = true

[tool:pytest]
DJANGO_SETTINGS_MODULE = settings.sqlite

addopts =
--doctest-modules
--cov=django_redis
--cov-config=setup.cfg
--no-cov-on-fail
filterwarnings =
error::DeprecationWarning
error::FutureWarning
error::PendingDeprecationWarning
ignore:.*distutils package is deprecated.*:DeprecationWarning
pythonpath = tests
testpaths = tests
xfail_strict = true
Expand All @@ -171,6 +150,9 @@ ignore_missing_settings = true
[mypy-lz4.frame]
ignore_missing_imports = true

[mypy-xdist.scheduler]
ignore_missing_imports = true

[mypy-pyzstd]
ignore_missing_imports = true

Expand Down
15 changes: 1 addition & 14 deletions tests/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,4 @@ Running the test suite
.. code-block:: bash
# start redis and a sentinel (uses docker with image redis:latest)
PRIMARY=$(tests/start_redis.sh)
SENTINEL=$(tests/start_redis.sh --sentinel)
# or just wait 5 - 10 seconds and most likely this would be the case
tests/wait_for_redis.sh $PRIMARY 6379
tests/wait_for_redis.sh $SENTINEL 26379
# run the tests
tox
# shut down redis
for container in $PRIMARY $SENTINEL; do
docker stop $container && docker rm $container
done
docker compose -f docker/docker-compose.yml up -d --wait
62 changes: 59 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,68 @@
import sys
from os import environ
from pathlib import Path
from typing import Iterable

import pytest
from django.core.cache import cache as default_cache
from xdist.scheduler import LoadScopeScheduling

from django_redis.cache import BaseCache
from tests.settings_wrapper import SettingsWrapper


@pytest.fixture
def cache() -> Iterable[BaseCache]:
class FixtureScheduling(LoadScopeScheduling):
"""Split by [] value. This is very hackish and might blow up any time!"""

def _split_scope(self, nodeid):
if "[sqlite" in nodeid:
return nodeid.rsplit("[")[-1].replace("]", "")
return None


def pytest_xdist_make_scheduler(log, config):
return FixtureScheduling(config, log)


def pytest_configure(config):
sys.path.insert(0, str(Path(__file__).absolute().parent))


@pytest.fixture()
def settings():
"""A Django settings object which restores changes after the testrun"""
wrapper = SettingsWrapper()
yield wrapper
wrapper.finalize()


@pytest.fixture()
def cache(cache_settings: str) -> Iterable[BaseCache]:
from django import setup

environ["DJANGO_SETTINGS_MODULE"] = f"settings.{cache_settings}"
setup()

from django.core.cache import cache as default_cache

yield default_cache
default_cache.clear()


def pytest_generate_tests(metafunc):
if "cache" in metafunc.fixturenames or "session" in metafunc.fixturenames:
# Mark
settings = [
"sqlite",
"sqlite_gzip",
"sqlite_herd",
"sqlite_json",
"sqlite_lz4",
"sqlite_msgpack",
"sqlite_sentinel",
"sqlite_sentinel_opts",
"sqlite_sharding",
"sqlite_usock",
"sqlite_zlib",
"sqlite_zstd",
]
metafunc.parametrize("cache_settings", settings)
8 changes: 4 additions & 4 deletions tests/settings/sqlite_gzip.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,31 @@
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": ["redis://127.0.0.1:6379?db=1", "redis://127.0.0.1:6379?db=1"],
"LOCATION": ["redis://127.0.0.1:6379?db=2", "redis://127.0.0.1:6379?db=2"],
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"COMPRESSOR": "django_redis.compressors.gzip.GzipCompressor",
},
},
"doesnotexist": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:56379?db=1",
"LOCATION": "redis://127.0.0.1:56379?db=2",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"COMPRESSOR": "django_redis.compressors.gzip.GzipCompressor",
},
},
"sample": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379?db=1,redis://127.0.0.1:6379?db=1",
"LOCATION": "redis://127.0.0.1:6379?db=2,redis://127.0.0.1:6379?db=2",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"COMPRESSOR": "django_redis.compressors.gzip.GzipCompressor",
},
},
"with_prefix": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379?db=1",
"LOCATION": "redis://127.0.0.1:6379?db=2",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"COMPRESSOR": "django_redis.compressors.gzip.GzipCompressor",
Expand Down
8 changes: 4 additions & 4 deletions tests/settings/sqlite_herd.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": ["redis://127.0.0.1:6379?db=5"],
"LOCATION": ["redis://127.0.0.1:6379?db=3"],
"OPTIONS": {"CLIENT_CLASS": "django_redis.client.HerdClient"},
},
"doesnotexist": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:56379?db=1",
"LOCATION": "redis://127.0.0.1:56379?db=3",
"OPTIONS": {"CLIENT_CLASS": "django_redis.client.HerdClient"},
},
"sample": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379?db=1,redis://127.0.0.1:6379?db=1",
"LOCATION": "redis://127.0.0.1:6379?db=3,redis://127.0.0.1:6379?db=3",
"OPTIONS": {"CLIENT_CLASS": "django_redis.client.HerdClient"},
},
"with_prefix": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379?db=1",
"LOCATION": "redis://127.0.0.1:6379?db=3",
"OPTIONS": {"CLIENT_CLASS": "django_redis.client.HerdClient"},
"KEY_PREFIX": "test-prefix",
},
Expand Down
8 changes: 4 additions & 4 deletions tests/settings/sqlite_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,31 @@
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": ["redis://127.0.0.1:6379?db=1", "redis://127.0.0.1:6379?db=1"],
"LOCATION": ["redis://127.0.0.1:6379?db=4", "redis://127.0.0.1:6379?db=4"],
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"SERIALIZER": "django_redis.serializers.json.JSONSerializer",
},
},
"doesnotexist": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:56379?db=1",
"LOCATION": "redis://127.0.0.1:56379?db=4",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"SERIALIZER": "django_redis.serializers.json.JSONSerializer",
},
},
"sample": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379?db=1,redis://127.0.0.1:6379?db=1",
"LOCATION": "redis://127.0.0.1:6379?db=4,redis://127.0.0.1:6379?db=4",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"SERIALIZER": "django_redis.serializers.json.JSONSerializer",
},
},
"with_prefix": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379?db=1",
"LOCATION": "redis://127.0.0.1:6379?db=4",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"SERIALIZER": "django_redis.serializers.json.JSONSerializer",
Expand Down
8 changes: 4 additions & 4 deletions tests/settings/sqlite_lz4.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,31 @@
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": ["redis://127.0.0.1:6379?db=1", "redis://127.0.0.1:6379?db=1"],
"LOCATION": ["redis://127.0.0.1:6379?db=5", "redis://127.0.0.1:6379?db=5"],
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"COMPRESSOR": "django_redis.compressors.lz4.Lz4Compressor",
},
},
"doesnotexist": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:56379?db=1",
"LOCATION": "redis://127.0.0.1:56379?db=5",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"COMPRESSOR": "django_redis.compressors.lz4.Lz4Compressor",
},
},
"sample": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "127.0.0.1:6379?db=1,127.0.0.1:6379?db=1",
"LOCATION": "127.0.0.1:6379?db=5,127.0.0.1:6379?db=5",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"COMPRESSOR": "django_redis.compressors.lz4.Lz4Compressor",
},
},
"with_prefix": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379?db=1",
"LOCATION": "redis://127.0.0.1:6379?db=5",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"COMPRESSOR": "django_redis.compressors.lz4.Lz4Compressor",
Expand Down
Loading

0 comments on commit ed27999

Please sign in to comment.