Skip to content

Commit 6d1ad31

Browse files
Add tests for Shortify and update docker compose (#1469)
1 parent 736ae87 commit 6d1ad31

File tree

9 files changed

+89
-10
lines changed

9 files changed

+89
-10
lines changed

demos/shortify/config/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ redis:
66
maxsize: 5
77

88
host: 127.0.0.1
9-
port: 9002
9+
port: 9001

demos/shortify/docker-compose.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
redis:
1+
services:
2+
redis:
23
image: redis:6
34
ports:
4-
- 6379:6379
5+
- 6379:6379

demos/shortify/pytest.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ addopts =
1212
# show values of the local vars in errors:
1313
--showlocals
1414
asyncio_mode = auto
15+
asyncio_default_fixture_loop_scope = function
1516
filterwarnings =
1617
error
1718
testpaths = tests/

demos/shortify/requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ aiohttp-jinja2==1.6
33
pyyaml==6.0.2
44
redis==6.1.0
55
trafaret==2.1.1
6+
pytest-aiohttp==1.1.0
7+
pytest-asyncio==0.26

demos/shortify/shortify/main.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import aiohttp_jinja2
66
import jinja2
77
from aiohttp import web
8+
from redis.asyncio import Redis
89

910
from shortify.routes import setup_routes
1011
from shortify.utils import init_redis, load_config
@@ -14,10 +15,13 @@
1415
PROJ_ROOT = pathlib.Path(__file__).parent.parent
1516
TEMPLATES_ROOT = pathlib.Path(__file__).parent / 'templates'
1617

18+
# Define AppKey for Redis
19+
REDIS_KEY = web.AppKey("REDIS_KEY", Redis)
20+
1721

1822
async def setup_redis(app, conf):
1923
redis = await init_redis(conf["redis"])
20-
app["redis"] = redis
24+
app[REDIS_KEY] = redis
2125
return redis
2226

2327

@@ -28,7 +32,7 @@ def setup_jinja(app):
2832

2933

3034
async def init():
31-
conf = load_config(PROJ_ROOT / 'config' / 'config.yml')
35+
conf = load_config(PROJ_ROOT / "config" / "config.yml")
3236

3337
app = web.Application()
3438
redis = await setup_redis(app, conf)

demos/shortify/shortify/views.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ async def shortify(self, request):
1919
long_url = fetch_url(data)
2020

2121
index = await self._redis.incr("shortify:count")
22-
path = encode(index)
22+
path = encode(index - 1)
2323
key = "shortify:{}".format(path)
2424
await self._redis.set(key, long_url)
2525

@@ -36,4 +36,4 @@ async def redirect(self, request):
3636
location = await self._redis.get(key)
3737
if not location:
3838
raise web.HTTPNotFound()
39-
return web.HTTPFound(location=location.decode())
39+
raise web.HTTPFound(location=location.decode())

demos/shortify/tests/__init__.py

Whitespace-only changes.

demos/shortify/tests/conftest.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import asyncio
2+
3+
import pytest
4+
from redis import asyncio as aioredis
5+
6+
from shortify.main import init, PROJ_ROOT
7+
from shortify.utils import load_config
8+
9+
TEST_CONFIG_PATH = PROJ_ROOT / "config" / "config.yml"
10+
TEST_CONFIG = load_config(TEST_CONFIG_PATH.as_posix())
11+
12+
13+
@pytest.fixture
14+
async def cli(aiohttp_client):
15+
app, _, _ = await init()
16+
return await aiohttp_client(app)
17+
18+
19+
@pytest.fixture
20+
async def redis():
21+
"""Create a Redis connection for testing."""
22+
redis_config = TEST_CONFIG["redis"]
23+
redis = await aioredis.from_url(
24+
f"redis://{redis_config['host']}:{redis_config['port']}",
25+
)
26+
yield redis
27+
await redis.aclose()
28+
# Give time for all connections to close properly
29+
await asyncio.sleep(0.1)
30+
31+
32+
@pytest.fixture(autouse=True)
33+
async def clean_redis(redis):
34+
"""Clean Redis database before each test."""
35+
await redis.flushdb()
36+
# Give time for all connections to close properly
37+
await asyncio.sleep(0.1)

demos/shortify/tests/test_shortify.py

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,37 @@
1-
async def test_something():
2-
# TODO: Create some actual tests.
3-
assert True
1+
async def test_create_short_url(cli, clean_redis):
2+
"""Test creating a short URL for a long URL."""
3+
long_url = "https://example.com/very/long/url/that/needs/shortening"
4+
5+
async with cli.post("/shortify", json={"url": long_url}) as resp:
6+
await resp.read()
7+
assert resp.status == 200
8+
9+
data = await resp.json()
10+
assert "url" in data
11+
assert data["url"] == "http://127.0.0.1:9001/a"
12+
13+
14+
async def test_redirect_to_long_url(cli, clean_redis):
15+
"""Test redirecting from short URL to original long URL."""
16+
long_url = "https://example.com/very/long/url/that/needs/shortening"
17+
18+
# Create a short URL
19+
async with cli.post("/shortify", json={"url": long_url}) as resp:
20+
await resp.read()
21+
assert resp.status == 200
22+
data = await resp.json()
23+
short_url = data["url"]
24+
short_code = short_url.split("/")[-1]
25+
26+
# Test the redirect
27+
async with cli.get(f"/{short_code}", allow_redirects=False) as resp:
28+
await resp.read()
29+
assert resp.status == 302
30+
assert resp.headers["Location"] == long_url
31+
32+
33+
async def test_invalid_short_url(cli, clean_redis):
34+
"""Test accessing a non-existent short URL."""
35+
async with cli.get("/nonexistent", allow_redirects=False) as resp:
36+
await resp.read()
37+
assert resp.status == 404

0 commit comments

Comments
 (0)