Skip to main content

A testing framework for Aiogram 3.x Telegram bots

Project description

Aiogram Test Framework

A testing framework for Aiogram 3.x Telegram bots that provides:

  • Mocking the Telegram Bot API
  • Capturing all outgoing bot requests
  • Simulating user interactions
  • Testing handlers with full middleware chain

Installation

pip install aiogram-test-framework

Quick Start

import pytest
from aiogram import Bot, Dispatcher
from aiogram_test_framework import AsyncBotTestMixin


def setup_dispatcher(bot: Bot, dispatcher: Dispatcher) -> None:
    """Configure dispatcher with middlewares and handlers."""
    # Your setup code here
    pass


class TestMyHandler(AsyncBotTestMixin):
    @pytest.fixture(autouse=True)
    async def setup(self):
        self.client = await self.setup_client(
            setup_dispatcher_func=setup_dispatcher,
        )
        yield
        await self.client.close()
        self.reset_factories()

    async def test_start_command(self):
        user = self.client.create_user()
        await user.send_command("start")
        assert user.has_received_message_containing("Welcome")

Components

TestClient

High-level test client for interacting with an Aiogram bot.

from aiogram_test_framework import TestClient

# Create client
client = await TestClient.create(
    bot_token="123456:ABC-DEF",
    bot_id=123456,
    bot_username="test_bot",
    bot_first_name="Test Bot",
    setup_dispatcher_func=setup_dispatcher,
)

# Create users and interact
user = client.create_user()
await user.send_command("start")
assert user.has_received_message_containing("Welcome")

# Close when done
await client.close()

MockBot

A mock Bot that captures all API requests for testing.

from aiogram_test_framework import MockBot, RequestCapture

capture = RequestCapture()
bot = MockBot(
    capture=capture,
    token="123456:ABC-DEF",
    bot_id=123456,
    bot_username="test_bot",
    bot_first_name="Test Bot",
)

# Use bot in tests...
await bot.send_message(chat_id=123, text="Hello")

# Check captured requests
messages = capture.get_sent_messages()
assert len(messages) == 1
assert messages[0].text == "Hello"

RequestCapture

Captures and stores all requests made by the bot to the Telegram API.

from aiogram_test_framework import RequestCapture, RequestType

capture = RequestCapture()

# After bot makes requests...
messages = capture.get_sent_messages()
messages = capture.get_sent_messages(chat_id=12345)  # Filter by chat
edited = capture.get_edited_messages()
deleted = capture.get_deleted_messages()
callbacks = capture.get_callback_answers()
dice_sends = capture.get_dice_sends()

# Get last message
last = capture.get_last_message()
last_in_chat = capture.get_last_message(chat_id=12345)

# Check content
has_welcome = capture.has_message_containing("Welcome")
has_welcome = capture.has_message_containing("Welcome", chat_id=12345)

# Get by type
all_sends = capture.get_by_type(RequestType.SEND_MESSAGE)
count = capture.count_by_type(RequestType.SEND_MESSAGE)

# Clear for next test
capture.clear()

TestUser

Represents a simulated Telegram user that can interact with the bot.

# Create via client
user = client.create_user(user_id=12345, first_name="John")

# Send messages/commands
responses = await user.send_message("Hello bot")
responses = await user.send_command("start")
responses = await user.send_command("start", args="referral_code")

# Click inline buttons
responses = await user.click_button("callback_data")

# Check responses
messages = user.get_sent_messages()
last = user.get_last_message()
has_welcome = user.has_received_message_containing("Welcome")

Factories

The framework provides factories for creating mock Telegram objects:

  • UserFactory - Create mock User objects
  • ChatFactory - Create mock Chat objects
  • MessageFactory - Create mock Message objects
  • CallbackQueryFactory - Create mock CallbackQuery objects
  • UpdateFactory - Create mock Update objects
  • KeyboardFactory - Create mock keyboard markups
from aiogram_test_framework import UserFactory, MessageFactory

# Create user
user = UserFactory.create(
    user_id=12345,
    first_name="John",
    username="johndoe",
)

# Create message
message = MessageFactory.create(
    text="Hello!",
    from_user=user,
)

# Create command
command = MessageFactory.create_command(
    command="start",
    from_user=user,
    args="ref123",
)

Usage with Different Test Frameworks

pytest

import pytest
from aiogram_test_framework import AsyncBotTestMixin


class TestMyHandler(AsyncBotTestMixin):
    @pytest.fixture(autouse=True)
    async def setup(self):
        self.client = await self.setup_client(
            setup_dispatcher_func=setup_dispatcher,
        )
        yield
        await self.client.close()
        self.reset_factories()

    async def test_start_command(self):
        user = self.client.create_user()
        await user.send_command("start")
        assert user.has_received_message_containing("Welcome")

unittest

import asyncio
import unittest
from aiogram_test_framework import AsyncBotTestMixin


class TestMyHandler(unittest.TestCase, AsyncBotTestMixin):
    def setUp(self):
        self.loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self.loop)
        self.client = self.loop.run_until_complete(
            self.setup_client(setup_dispatcher_func=setup_dispatcher)
        )

    def tearDown(self):
        if hasattr(self, 'client') and self.client:
            self.loop.run_until_complete(self.client.close())
        self.reset_factories()
        self.loop.close()

    def test_start_command(self):
        async def run_test():
            user = self.client.create_user()
            await user.send_command("start")
            assert user.has_received_message_containing("Welcome")

        self.loop.run_until_complete(run_test())

Django

from asgiref.sync import async_to_sync
from django.test import TransactionTestCase
from aiogram_test_framework import AsyncBotTestMixin


class TestMyHandler(TransactionTestCase, AsyncBotTestMixin):
    def setUp(self) -> None:
        async_to_sync(self._async_setup)()

    def tearDown(self) -> None:
        async_to_sync(self._async_teardown)()

    async def _async_setup(self) -> None:
        self.client = await self.setup_client(
            setup_dispatcher_func=setup_dispatcher,
        )

    async def _async_teardown(self) -> None:
        await self.client.close()
        self.reset_factories()

    async def test_start_command(self) -> None:
        user = self.client.create_user()
        await user.send_command("start")
        assert user.has_received_message_containing("Welcome")

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aiogram_test_framework-0.1.2.tar.gz (23.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aiogram_test_framework-0.1.2-py3-none-any.whl (16.8 kB view details)

Uploaded Python 3

File details

Details for the file aiogram_test_framework-0.1.2.tar.gz.

File metadata

  • Download URL: aiogram_test_framework-0.1.2.tar.gz
  • Upload date:
  • Size: 23.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for aiogram_test_framework-0.1.2.tar.gz
Algorithm Hash digest
SHA256 8965c8261181d02e2ea5b0e76f9c682dc70b4c2951d14711f87f442695cb7481
MD5 8610c248c67a50d07e44eb7e291c8777
BLAKE2b-256 54c9b903838290228dbffd72b7e203b9fad792df2bd7bf0c5cd72066b9033e91

See more details on using hashes here.

File details

Details for the file aiogram_test_framework-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for aiogram_test_framework-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 0ab69664a4bd3259bb6bb9a2aa87c3b417e770f9baffa209f417d45015bbe78c
MD5 c47a2df9edbfe7f54138272b5cb639dd
BLAKE2b-256 d4dbaa15d1a90ea78ef687d168ab8414ef2ac467c7d127e3355231483c621019

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page