DEV Community

Cover image for Why your Telegram bot test is failing silently
Daniil
Daniil

Posted on

Why your Telegram bot test is failing silently

Telegram app logo is seen in this illustration taken, Aug 27, 2024.
Image: Reuters file

Sometimes the problem isn’t in your test code — it’s in how Telegram handles updates.

If your bot is running locally in polling mode, and your test also tries to read updates — nothing will break… but nothing will work either.

Let me explain what happened — and why this behavior is easy to overlook when you're just starting to test Telegram bots as myself.

The Problem

I was writing a test for the /start command using pytest.
The bot was running locally, the token was valid, everything looked fine — but the test was just...waiting.

Turns out, the issue wasn’t in the code — it was in the way Telegram’s getUpdates API works.

Here’s what was really going on:

My bot was running with .run_polling(), which continuously polls getUpdates in the background.
My test was also calling getUpdates manually, expecting to retrieve the /start command from a real Telegram chat.
The result? A hidden conflict.

Telegram only allows one active consumer of updates.

So when the bot is running, it “eats” all updates — and the test sees nothing.

🛠️ How to Fix It

Since you can’t simulate a user sending /start directly through the Telegram API (that’s forbidden), here are two reliable alternatives:

Option 1: Manual Trigger + Stored Log Verification
Best for CI or webhook-based bots.

You manually send /start from Telegram.
Your bot processes it and logs the result.
Your test waits briefly, then checks the log file or database to confirm the expected output.

Option 2: Simulate Telegram webhook with a fake payload

A fully automated way using requests.post() or similar to mock a real Telegram update:

You run your bot in webhook mode (instead of polling).
Telegram would normally send POST requests to your webhook URL (e.g. https://abc123.ngrok-free.app/webhook)
Instead, your test simulates this POST request using your own payload.
Your Flask or FastAPI app receives it and behaves as if it came from Telegram.

But why do I need Flask or FastAPI at all?

When using webhooks, Telegram sends updates to your bot as HTTP POST requests.

To receive them — you need a web server.

That’s where Flask or FastAPI comes in.
They expose an endpoint like /webhook that can receive and process Telegram’s payloads.

Webhook flow:

  1. Telegram sends an update: POST https://yourdomain.com/webhook
  2. Flask/FastAPI receives it and hands it over to python-telegram-bot
  3. Your handler function is called just like in polling mode

Without this, your bot simply won’t work in webhook mode — and you won’t be able to test real-world flows in CI/CD.

Testing Telegram bots has its nuances and bottlenecks, and this one was a surprise for me too.

But the deeper you go — the more power you unlock.
This case alone pushed me to explore better testing strategies and architect a more production-like setup, even for test automation.

Would you be interested in more deep-dives on Telegram bot testing?

Let me know in the comments or drop a DM — I’m currently building a courses on this topic using Pytest, Playwright, and Cypress.

Top comments (0)