Skip to content

Commit 9aca9b6

Browse files
committed
add tests
1 parent b51eba7 commit 9aca9b6

File tree

11 files changed

+488
-358
lines changed

11 files changed

+488
-358
lines changed

Dockerfile

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1-
FROM python:slim
1+
FROM python:3.12-slim
22

3-
RUN apt-get update && apt-get install -yqq make
4-
RUN pip install poetry
5-
ENV POETRY_VIRTUALENVS_IN_PROJECT=true
3+
RUN apt-get update && \
4+
apt-get install -y make && \
5+
pip install uv
66

7+
ENV UV_LINK_MODE=copy
8+
ENV UV_COMPILE_BYTECODE=1
9+
RUN --mount=type=cache,target=/root/.cache/uv
710

811
WORKDIR /app
912
COPY . .
10-
RUN poetry install
13+
RUN make install
1114

1215
CMD ["make", "run"]

Makefile

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
PORT ?= 4000
22

33
install:
4-
poetry install
4+
uv sync
55

66
dev:
7-
poetry run flask --app app.server run --debug -h 0.0.0.0 -p $(PORT)
7+
uv run flask --app app.server run --debug -h 0.0.0.0 -p $(PORT)
88

99
run:
10-
poetry run gunicorn -w 4 -b 0.0.0.0:$(PORT) app.server:app
10+
uv run gunicorn -w 4 -b 0.0.0.0:$(PORT) app.server:app
1111

1212
start:
1313
make stop rm || true
@@ -24,3 +24,19 @@ rm:
2424

2525
bash:
2626
docker run --rm -it data-charts-api bash
27+
28+
PID_FILE = server.pid
29+
30+
test:
31+
env PORT=$(PORT) DATABASE_URL=postgres://student:[email protected]:5432/chartsdb \
32+
make dev & echo $$! > $(PID_FILE) && \
33+
sleep 2 && \
34+
uv run pytest; \
35+
status=$$?; \
36+
if [ -f $(PID_FILE) ]; then kill `cat $(PID_FILE)` && rm $(PID_FILE); fi; \
37+
exit $$status
38+
39+
lint:
40+
uv run ruff check .
41+
42+
check: test lint

app/__init__.py

Whitespace-only changes.

app/server.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
from flask import Flask, request
2-
from datetime import datetime
31
import logging
4-
import traceback
52
import os
6-
import psycopg
7-
from psycopg.rows import dict_row
3+
import traceback
4+
from datetime import datetime
85

6+
import psycopg
97
from dotenv import load_dotenv
8+
from flask import Flask, request
9+
from psycopg.rows import dict_row
1010

1111
load_dotenv()
1212

docker-compose.yml

Whitespace-only changes.

poetry.lock

Lines changed: 0 additions & 333 deletions
This file was deleted.

pyproject.toml

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,26 @@
1-
[tool.poetry]
2-
name = "app"
1+
[project]
2+
name = "data-charts-api"
33
version = "0.1.0"
4-
description = ""
5-
authors = ["Your Name <[email protected]>"]
4+
description = "api for data charts project"
5+
readme = "README.md"
6+
requires-python = ">=3.12"
7+
dependencies = [
8+
"flask>=3.0.3",
9+
"gunicorn>=23.0.0",
10+
"psycopg>=3.2.3",
11+
"python-dotenv>=1.0.1",
12+
]
613

7-
[tool.poetry.dependencies]
8-
python = "^3.10"
9-
flask = "^3.0.0"
10-
gunicorn = "^21.2.0"
11-
python-dotenv = "^1.0.0"
12-
psycopg = {extras = ["binary"], version = "^3.1.13"}
14+
[tool.uv]
15+
dev-dependencies = [
16+
"pytest>=8.3.3",
17+
"requests>=2.32.3",
18+
"ruff>=0.7.2",
19+
]
1320

21+
[tool.hatch.build.targets.wheel]
22+
packages = ["app"]
1423

1524
[build-system]
16-
requires = ["poetry-core"]
17-
build-backend = "poetry.core.masonry.api"
25+
requires = ["hatchling"]
26+
build-backend = "hatchling.build"

server.pid

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
170353

tests/conftest.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import sqlite3
2+
from datetime import datetime, timedelta
3+
4+
import pytest
5+
6+
from app.server import app
7+
8+
9+
def dict_factory(cursor, row):
10+
"""Преобразует результаты SQLite в словарь"""
11+
d = {}
12+
for idx, col in enumerate(cursor.description):
13+
d[col[0]] = row[idx]
14+
return d
15+
16+
@pytest.fixture
17+
def client():
18+
"""Фикстура для тестового клиента с SQLite в памяти"""
19+
# Создаем in-memory SQLite базу
20+
db = sqlite3.connect(':memory:', detect_types=sqlite3.PARSE_DECLTYPES)
21+
db.row_factory = dict_factory
22+
23+
# Создаем схему
24+
with db.cursor() as cur:
25+
cur.execute("""
26+
CREATE TABLE visits (
27+
id INTEGER PRIMARY KEY,
28+
datetime TIMESTAMP NOT NULL
29+
-- добавьте остальные поля
30+
)
31+
""")
32+
33+
cur.execute("""
34+
CREATE TABLE registrations (
35+
id INTEGER PRIMARY KEY,
36+
datetime TIMESTAMP NOT NULL
37+
-- добавьте остальные поля
38+
)
39+
""")
40+
41+
# Добавляем тестовые данные
42+
cur.execute("""
43+
INSERT INTO visits (datetime) VALUES
44+
(?), (?)
45+
""", (datetime.now(), datetime.now() - timedelta(days=1)))
46+
47+
cur.execute("""
48+
INSERT INTO registrations (datetime) VALUES
49+
(?)
50+
""", (datetime.now(),))
51+
52+
db.commit()
53+
54+
# Подменяем подключение к БД в приложении
55+
def get_test_db():
56+
return db
57+
58+
app.get_db = get_test_db
59+
60+
with app.test_client() as client:
61+
yield client
62+
63+
db.close()

tests/test_server.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import os
2+
3+
import requests
4+
5+
PORT = os.getenv('PORT')
6+
7+
def test_server():
8+
response = requests.get('http://localhost:4000/')
9+
assert response.status_code == 200
10+
assert response.text == 'It Works'
11+
12+
response = requests.get('http://localhost:4000/visits?begin=2023-03-01&end=2023-03-02')
13+
assert response.status_code == 200
14+
assert response.json()[0] == {
15+
"datetime": "Wed, 01 Mar 2023 10:36:22 GMT",
16+
"platform": "web",
17+
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.6",
18+
"visit_id": "1de9ea66-70d3-4a1f-8735-df5ef7697fb9"
19+
}

0 commit comments

Comments
 (0)