1

I am trying to create a pytest file testing multiple functions (start and name) of a telegram bot. I managed to test each function individually and it works, but when I try to test multiple functions, it shows error: PytestUnhandledCoroutineWarning: async def functions are not natively supported and have been skipped. You need to install a suitable plugin for your async framework. Even though I already have installed the plugin mentioned -pytest asyncio.

This is the project file for reference

import logging
from telegram import Update
from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler, MessageHandler, filters

task_list = {}
formatted_task_list = []
done_list = {}
formatted_done_list = []
user_name = {}


async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user_id = update.effective_user.id
    if user_id not in task_list:
        task_list[user_id] = []
        done_list[user_id] = []
        user_name[user_id] = "Task"
    await context.bot.send_message(chat_id=update.effective_chat.id, text="Hello! Welcome to Task List")


async def name(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user_id = update.effective_user.id
    if user_id in task_list:
        user_id = update.effective_user.id
        user_name[user_id] = " ".join(context.args)
        user_name[user_id] = f"<b>{user_name[user_id]}</b>"
        await context.bot.send_message(chat_id=update.effective_chat.id, text=f"Your list will be named {user_name[user_id]}. You're set!", parse_mode="HTML")
    else:
        await context.bot.send_message(chat_id=update.effective_chat.id, text="Type /start to start using this bot.")

def main():
    application = ApplicationBuilder().token('My tokens').build()

    start_handler = CommandHandler(['start', 'hello'], start)
    name_handler = CommandHandler('name', name)

    application.add_handler(start_handler)
    application.add_handler(name_handler)

    application.run_polling()


if __name__ == "__main__":
    main()

Here is my pytest code

import pytest
from unittest.mock import AsyncMock, patch
from project import start, view, add, name

# Mocks
class MockUser:
    def __init__(self, id):
        self.id = id

class MockChat:
    def __init__(self, id):
        self.id = id

class MockBot:
    async def send_message(self, chat_id, text):
        pass

# Test case
@pytest.mark.asyncio
@patch('project.task_list', {932872542: ['Example Task']})
@patch('project.done_list', {932872542: []})
@patch('project.user_name', {932872542: 'Task'})


async def test_start_function():
    update_mock = AsyncMock()
    context_mock = AsyncMock()
    context_mock.bot = AsyncMock()
    update_mock.effective_user = MockUser(932872542)
    update_mock.effective_chat = MockChat(123)
    update_mock.message.text = "/start"

    await start(update_mock, context_mock)

    context_mock.bot.send_message.assert_called_once_with(
        chat_id=123,
        text="Hello! Welcome to Task List")



async def test_name_function():
    update_mock = AsyncMock()
    context_mock = AsyncMock()
    context_mock.bot = AsyncMock()
    update_mock.effective_user = MockUser(932872542)
    update_mock.effective_chat = MockChat(123)

    update_mock.message.text = "/name New List"
    context_mock.args = ["New", "List"]

    await name(update_mock, context_mock)

    context_mock.bot.send_message.assert_called_once_with(
        chat_id=123,
        text="Your list will be named <b>New List</b>. You're set!",
        parse_mode="HTML",
    )



if __name__ == "__main__":
    pytest.main()

Thank you!

Lili
  • 11
  • 2

0 Answers0