diff --git a/requirements.txt b/requirements.txt index 9c4da35..278ff90 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +aiosqlite==0.22.1 anyio==4.12.1 APScheduler==3.11.2 asyncpg==0.31.0 @@ -45,6 +46,7 @@ pyflakes==3.4.0 Pygments==2.19.2 pyOpenSSL==25.3.0 pytest==9.0.2 +pytest-asyncio==1.3.0 python-dotenv==1.2.1 python-telegram-bot==22.6 pytokens==0.4.0 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..158038b --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,62 @@ +import pytest +import pytest_asyncio +from db.models import Base, News +from sqlalchemy import create_engine +from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine +from sqlalchemy.orm import sessionmaker + +DATABASE_SYNC_URL = "sqlite:///:memory:" +DATABASE_ASYNC_URL = "sqlite+aiosqlite:///:memory:" + + +@pytest.fixture +def session(): + engine = create_engine(DATABASE_SYNC_URL, echo=False) + Base.metadata.create_all(engine) + Session = sessionmaker(engine) + session = Session() + yield session + session.close() + + +@pytest_asyncio.fixture +async def async_session(): + engine = create_async_engine(DATABASE_ASYNC_URL, echo=False) + async with engine.begin() as conn: + await conn.run_sync(Base.metadata.create_all) + AsyncSession = async_sessionmaker(engine, expire_on_commit=False) + async with AsyncSession() as async_session: + yield async_session + await engine.dispose() + + +@pytest.fixture +def news(): + test_news = { + "url": "https://panorama.pub/test-news", + "title": "Test Title", + "text": "Test Text", + "image": None, + } + return test_news + + +@pytest_asyncio.fixture +async def news_list(async_session): + first_news = News( + url="https://panorama.pub/test-news_1", + title="Test Title 1", + image=None, + text="Ttest Text_1", + ) + second_news = News( + url="https://panorama.pub/test-news_2", + title="Test Title 2", + image=None, + text="Ttest Text_2", + ) + + async_session.add_all([first_news, second_news]) + await async_session.commit() + + return [first_news, second_news] diff --git a/tests/test_bot_storage.py b/tests/test_bot_storage.py new file mode 100644 index 0000000..032ad6f --- /dev/null +++ b/tests/test_bot_storage.py @@ -0,0 +1,55 @@ +import pytest +from bot.bot_storage import ( + get_all_users, + get_last_sent_id, + get_news_after_id, + save_last_sent_news_id, +) + + +@pytest.mark.asyncio +async def test_get_last_sent_id(async_session): + """Проверка id последней отправленой новости""" + chat_id = 100 + + last_id = await get_last_sent_id(chat_id, async_session) + assert ( + last_id == 0 + ), "id последней отпрвленной новости должен быть равен 0, если нет отправленных новостей" + + await save_last_sent_news_id( + chat_id=chat_id, last_id=10, session=async_session + ) + last_id = await get_last_sent_id(chat_id, async_session) + assert ( + last_id == 10 + ), "id последней отпрвленной новости должен быть равен 10" + + +@pytest.mark.asyncio +async def test_get_news_after_id(async_session, news_list): + """Получение новостей""" + news = await get_news_after_id(last_id=0, session=async_session) + assert len(news) == 2, "Должно быть получено 2 новости" + assert ( + news[0].title == "Test Title 1" + ), "Заголовок первой новости должен быть 'Test Title 1'" + assert ( + news[1].title == "Test Title 2" + ), "Заголовок второй новости должен быть 'Test Title 2'" + + +@pytest.mark.asyncio +async def test_get_all_users(async_session): + """Получение пользователей""" + await save_last_sent_news_id( + chat_id=111, last_id=11, session=async_session + ) + await save_last_sent_news_id( + chat_id=222, last_id=22, session=async_session + ) + + users = await get_all_users(async_session) + assert len(users) == 2, "Должно быть 2 пользователя в базе" + assert users[0] == 111, "id первого юзера должен быть 111" + assert users[1] == 222, "id второго юзеера должен быть 222" diff --git a/tests/test_spider_storage.py b/tests/test_spider_storage.py new file mode 100644 index 0000000..fa3817e --- /dev/null +++ b/tests/test_spider_storage.py @@ -0,0 +1,20 @@ +from satire_pulp_parser.spider_storage import is_news_exists, save_news + + +def test_save_and_check_news(session, news): + """Проверяет что новостей нет в базе, + сохранение новости + и новость появилась в базе после сохранения.""" + assert not is_news_exists( + news["url"], session + ), "Перед сохраением новой новости её не должно быть в базе" + save_news( + news["url"], + news["title"], + news["image"], + news["text"], + session=session, + ) + assert is_news_exists( + news["url"], session + ), "Новость должна появиться в базе после сохранения"