Skip to content

Commit

Permalink
feat(redis): support AsyncRedisContainer (#442)
Browse files Browse the repository at this point in the history
Co-authored-by: bstrausser <bstrausser@locusrobotics.com>
  • Loading branch information
bearrito and bstrausser committed Mar 6, 2024
1 parent 5356caf commit cc4cb37
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 4 deletions.
27 changes: 27 additions & 0 deletions modules/redis/testcontainers/redis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from typing import Optional

import redis
from redis.asyncio import Redis as asyncRedis
from testcontainers.core.container import DockerContainer
from testcontainers.core.utils import raise_for_deprecated_parameter
from testcontainers.core.waiting_utils import wait_container_is_ready
Expand Down Expand Up @@ -69,3 +70,29 @@ def start(self) -> "RedisContainer":
super().start()
self._connect()
return self


class AsyncRedisContainer(RedisContainer):
"""
Redis container.
Example
-------
.. doctest::
>>> from testcontainers.redis import AsyncRedisContainer
>>> with AsyncRedisContainer() as redis_container:
... redis_client =await redis_container.get_async_client()
"""

def __init__(self, image="redis:latest", port_to_expose=6379, password=None, **kwargs):
super().__init__(image, port_to_expose, password, **kwargs)

async def get_async_client(self, **kwargs):
return await asyncRedis(
host=self.get_container_host_ip(),
port=self.get_exposed_port(self.port),
password=self.password,
**kwargs,
)
46 changes: 45 additions & 1 deletion modules/redis/tests/test_redis.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import time

from testcontainers.redis import RedisContainer
from testcontainers.redis import RedisContainer, AsyncRedisContainer
import pytest


def test_docker_run_redis():
Expand All @@ -23,6 +24,49 @@ def test_docker_run_redis_with_password():
assert client.get("hello") == "world"


pytest.mark.usefixtures("anyio_backend")


@pytest.mark.parametrize("anyio_backend", ["asyncio"])
async def test_key_set_in_async_redis(anyio_backend):
with AsyncRedisContainer() as container:
async_redis_client: redis.Redis = await container.get_async_client(decode_responses=True)
key = "key"
expected_value = 1
await async_redis_client.set(key, expected_value)
actual_value = await async_redis_client.get(key)
assert int(actual_value) == expected_value


pytest.mark.usefixtures("anyio_backend")


@pytest.mark.parametrize("anyio_backend", ["asyncio"])
@pytest.mark.skip(reason="Need to sort out async pub/sub")
async def test_docker_run_async_redis(anyio_backend):
config = AsyncRedisContainer()
with config as container:
client: redis.Redis = await container.get_async_client(decode_responses=True)
p = await client.pubsub()
await p.subscribe("test")
await client.publish("test", "new_msg")
msg = wait_for_message(p)
assert "data" in msg
assert b"new_msg", msg["data"]


pytest.mark.usefixtures("anyio_backend")


@pytest.mark.parametrize("anyio_backend", ["asyncio"])
async def test_docker_run_async_redis_with_password(anyio_backend):
config = AsyncRedisContainer(password="mypass")
with config as container:
client: redis.Redis = await container.get_async_client(decode_responses=True)
await client.set("hello", "world")
assert await client.get("hello") == "world"


def wait_for_message(pubsub, timeout=1, ignore_subscribe_messages=True):
now = time.time()
timeout = now + timeout
Expand Down
42 changes: 39 additions & 3 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ pytest = "7.4.3"
pytest-cov = "4.1.0"
sphinx = "^7.2.6"
twine = "^4.0.2"
anyio = "^4.3.0"

[[tool.poetry.source]]
name = "PyPI"
Expand Down

0 comments on commit cc4cb37

Please sign in to comment.