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!