Skip to content

Commit e594ca9

Browse files
committed
add pytest-xdist and tests in CI
1 parent 6b035c6 commit e594ca9

File tree

8 files changed

+119
-41
lines changed

8 files changed

+119
-41
lines changed

.github/workflows/ci.yml

+35
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,45 @@ jobs:
1212
uses: actions/setup-python@v5
1313
with:
1414
python-version: "3.11"
15+
cache: "poetry"
1516
- name: Install dependencies
1617
run: |
1718
poetry env use "3.11"
1819
poetry export --only lint --output lint-requirements.txt
1920
pip install -r lint-requirements.txt
2021
- name: Run Ruff
2122
run: ruff check --output-format=github .
23+
test:
24+
name: Run Tests
25+
needs: lint
26+
runs-on: ubuntu-latest
27+
services:
28+
postgres:
29+
image: postgres:15-alpine
30+
env:
31+
POSTGRES_USER: postgres
32+
POSTGRES_PASSWORD: postgres
33+
POSTGRES_DB: postgres
34+
ports: ["5432:5432"]
35+
redis:
36+
image: redis:7.0.12-alpine
37+
options: >-
38+
--health-cmd "redis-cli ping"
39+
--health-interval 10s
40+
--health-timeout 5s
41+
--health-retries 5
42+
ports:
43+
- 6379:6379
44+
steps:
45+
- uses: actions/checkout@v3
46+
- run: pipx install poetry
47+
- uses: actions/setup-python@v4
48+
with:
49+
python-version: 3.11
50+
cache: "poetry"
51+
- run: poetry install
52+
- run: poetry run pytest -x -n auto --dist loadfile
53+
env:
54+
DB_HOST: "localhost"
55+
REDIS_HOST: "localhost"
56+
REDIS_PORT: "6379"

.pre-commit-config.yaml

-14
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,4 @@
11
repos:
2-
- repo: https://github.com/pycqa/isort
3-
rev: 5.12.0
4-
hooks:
5-
- id: isort
6-
- repo: https://github.com/psf/black
7-
rev: 23.7.0
8-
hooks:
9-
- id: black
10-
- repo: https://github.com/pycqa/flake8
11-
rev: 6.0.0
12-
hooks:
13-
- id: flake8
14-
exclude: "src/tests/"
15-
additional_dependencies: [Flake8-pyproject]
162
- repo: https://github.com/astral-sh/ruff-pre-commit
173
# Ruff version.
184
rev: v0.3.0

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ WORKDIR /opt/chat
2121

2222
COPY poetry.lock pyproject.toml ./
2323
RUN pip install "poetry==$POETRY_VERSION"
24-
RUN poetry export --with dev --output requirements.txt
24+
RUN poetry export --with test,lint --output requirements.txt
2525
RUN pip install --no-deps -r requirements.txt
2626

2727
COPY . .

Makefile

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ down:
2222
test:
2323
docker exec -it chat-backend python -m pytest -svv $(target)
2424

25+
ftest:
26+
docker exec -it chat-backend python -m pytest -x -n 2 --dist loadfile
27+
2528
test-integration:
2629
docker exec -it chat-backend python -m pytest -m "integration" -svv
2730

poetry.lock

+35-11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pytest = "7.4.3"
3838
pytest-asyncio = "0.23.5"
3939
pytest-env = "1.1.3"
4040
pytest-mock = "3.12.0"
41+
pytest-xdist = "3.5.0"
4142

4243
[tool.poetry.group.lint.dependencies]
4344
ruff = "0.3.0"

src/config.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import logging
22
import os
3+
from random import randint
34

45
import boto3
56
from pydantic_settings import BaseSettings, SettingsConfigDict
@@ -58,7 +59,7 @@ class GlobalSettings(BaseSettings):
5859

5960

6061
class TestSettings(GlobalSettings):
61-
DB_SCHEMA: str = "test"
62+
DB_SCHEMA: str = f"test_{randint(1, 100)}"
6263

6364

6465
class DevelopmentSettings(GlobalSettings):
@@ -125,6 +126,10 @@ def get_settings():
125126
},
126127
"loggers": {
127128
"": {"handlers": ["default"], "level": settings.LOG_LEVEL, "propagate": False},
128-
"uvicorn": {"handlers": ["default"], "level": logging.ERROR, "propagate": False},
129+
"uvicorn": {
130+
"handlers": ["default"],
131+
"level": logging.ERROR,
132+
"propagate": False,
133+
},
129134
},
130135
}

tests/conftest.py

+37-13
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,14 @@
2121
f"postgresql+asyncpg://"
2222
f"{settings.DB_USER}:{settings.DB_PASSWORD}@{settings.DB_HOST}:{settings.DB_PORT}/{settings.DB_NAME}"
2323
)
24-
engine_test = create_async_engine(DATABASE_URL_TEST, connect_args={"server_settings": {"jit": "off"}})
24+
engine_test = create_async_engine(
25+
DATABASE_URL_TEST, connect_args={"server_settings": {"jit": "off"}}
26+
)
2527
autocommit_engine = engine_test.execution_options(isolation_level="AUTOCOMMIT")
2628

27-
async_session_maker = sessionmaker(autocommit_engine, class_=AsyncSession, expire_on_commit=False)
29+
async_session_maker = sessionmaker(
30+
autocommit_engine, class_=AsyncSession, expire_on_commit=False
31+
)
2832
metadata.bind = engine_test
2933

3034

@@ -36,7 +40,7 @@ async def override_get_async_session() -> AsyncGenerator[AsyncSession, None]:
3640
app.dependency_overrides[get_async_session] = override_get_async_session
3741

3842

39-
@pytest.fixture(scope="session")
43+
@pytest.fixture()
4044
async def db_session():
4145
async with autocommit_engine.begin() as conn:
4246
await conn.execute(text(f"CREATE SCHEMA IF NOT EXISTS {settings.DB_SCHEMA}"))
@@ -140,31 +144,43 @@ def authenticated_doug_client(async_client: AsyncClient, doug_user: User):
140144

141145

142146
@pytest.fixture
143-
async def bob_emily_chat(db_session: AsyncSession, bob_user: User, emily_user: User) -> Chat:
147+
async def bob_emily_chat(
148+
db_session: AsyncSession, bob_user: User, emily_user: User
149+
) -> Chat:
144150
chat = Chat(chat_type=ChatType.DIRECT)
145151
chat.users.append(bob_user)
146152
chat.users.append(emily_user)
147153
db_session.add(chat)
148154
await db_session.flush()
149155
# make empty read statuses for both users last_read_message_id = 0
150-
initiator_read_status = ReadStatus(chat_id=chat.id, user_id=bob_user.id, last_read_message_id=0)
151-
recipient_read_status = ReadStatus(chat_id=chat.id, user_id=emily_user.id, last_read_message_id=0)
156+
initiator_read_status = ReadStatus(
157+
chat_id=chat.id, user_id=bob_user.id, last_read_message_id=0
158+
)
159+
recipient_read_status = ReadStatus(
160+
chat_id=chat.id, user_id=emily_user.id, last_read_message_id=0
161+
)
152162
db_session.add_all([initiator_read_status, recipient_read_status])
153163
await db_session.commit()
154164

155165
return chat
156166

157167

158168
@pytest.fixture
159-
async def bob_doug_chat(db_session: AsyncSession, doug_user: User, bob_user: User) -> Chat:
169+
async def bob_doug_chat(
170+
db_session: AsyncSession, doug_user: User, bob_user: User
171+
) -> Chat:
160172
chat = Chat(chat_type=ChatType.DIRECT)
161173
chat.users.append(doug_user)
162174
chat.users.append(bob_user)
163175
db_session.add(chat)
164176
await db_session.flush()
165177
# make empty read statuses for both users last_read_message_id = 0
166-
initiator_read_status = ReadStatus(chat_id=chat.id, user_id=bob_user.id, last_read_message_id=0)
167-
recipient_read_status = ReadStatus(chat_id=chat.id, user_id=doug_user.id, last_read_message_id=0)
178+
initiator_read_status = ReadStatus(
179+
chat_id=chat.id, user_id=bob_user.id, last_read_message_id=0
180+
)
181+
recipient_read_status = ReadStatus(
182+
chat_id=chat.id, user_id=doug_user.id, last_read_message_id=0
183+
)
168184
db_session.add_all([initiator_read_status, recipient_read_status])
169185

170186
await db_session.commit()
@@ -199,12 +215,16 @@ async def bob_emily_chat_messages_history(
199215

200216
@pytest.fixture
201217
async def bob_read_status(
202-
db_session: AsyncSession, bob_user: User, bob_emily_chat_messages_history: list[Message]
218+
db_session: AsyncSession,
219+
bob_user: User,
220+
bob_emily_chat_messages_history: list[Message],
203221
) -> ReadStatus:
204222
# bob read 10 messages
205223
last_read_message = bob_emily_chat_messages_history[9]
206224
read_status = ReadStatus(
207-
user_id=bob_user.id, chat_id=last_read_message.chat.id, last_read_message_id=last_read_message.id
225+
user_id=bob_user.id,
226+
chat_id=last_read_message.chat.id,
227+
last_read_message_id=last_read_message.id,
208228
)
209229
db_session.add(read_status)
210230
await db_session.commit()
@@ -214,12 +234,16 @@ async def bob_read_status(
214234

215235
@pytest.fixture
216236
async def emily_read_status(
217-
db_session: AsyncSession, emily_user: User, bob_emily_chat_messages_history: list[Message]
237+
db_session: AsyncSession,
238+
emily_user: User,
239+
bob_emily_chat_messages_history: list[Message],
218240
) -> ReadStatus:
219241
# emily read 15 messages
220242
last_read_message = bob_emily_chat_messages_history[14]
221243
read_status = ReadStatus(
222-
user_id=emily_user.id, chat_id=last_read_message.chat.id, last_read_message_id=last_read_message.id
244+
user_id=emily_user.id,
245+
chat_id=last_read_message.chat.id,
246+
last_read_message_id=last_read_message.id,
223247
)
224248
db_session.add(read_status)
225249
await db_session.commit()

0 commit comments

Comments
 (0)