Skip to content

Commit

Permalink
Reduce Code Duplication in Testing Defaults (#3419)
Browse files Browse the repository at this point in the history
  • Loading branch information
Bibo-Joshi committed Dec 12, 2022
1 parent 9c3053b commit ff645c6
Show file tree
Hide file tree
Showing 33 changed files with 537 additions and 502 deletions.
420 changes: 420 additions & 0 deletions tests/auxil/bot_method_checks.py

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions tests/auxil/object_conversions.py
@@ -0,0 +1,25 @@
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2022
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser Public License for more details.
#
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].


def env_var_2_bool(env_var: object) -> bool:
if isinstance(env_var, bool):
return env_var
if not isinstance(env_var, str):
return False
return env_var.lower().strip() == "true"
384 changes: 3 additions & 381 deletions tests/conftest.py

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions tests/test_animation.py
Expand Up @@ -25,12 +25,12 @@
from telegram.error import BadRequest, TelegramError
from telegram.helpers import escape_markdown
from telegram.request import RequestData
from tests.conftest import (
from tests.auxil.bot_method_checks import (
check_defaults_handling,
check_shortcut_call,
check_shortcut_signature,
data_file,
)
from tests.conftest import data_file


@pytest.fixture(scope="function")
Expand Down
3 changes: 2 additions & 1 deletion tests/test_applicationbuilder.py
Expand Up @@ -38,7 +38,8 @@
from telegram.ext._applicationbuilder import _BOT_CHECKS
from telegram.request import HTTPXRequest

from .conftest import PRIVATE_KEY, data_file, env_var_2_bool
from .auxil.object_conversions import env_var_2_bool
from .conftest import PRIVATE_KEY, data_file

TEST_WITH_OPT_DEPS = env_var_2_bool(os.getenv("TEST_WITH_OPT_DEPS", True))

Expand Down
4 changes: 2 additions & 2 deletions tests/test_audio.py
Expand Up @@ -25,12 +25,12 @@
from telegram.error import TelegramError
from telegram.helpers import escape_markdown
from telegram.request import RequestData
from tests.conftest import (
from tests.auxil.bot_method_checks import (
check_defaults_handling,
check_shortcut_call,
check_shortcut_signature,
data_file,
)
from tests.conftest import data_file


@pytest.fixture(scope="function")
Expand Down
95 changes: 14 additions & 81 deletions tests/test_bot.py
Expand Up @@ -38,14 +38,12 @@
ChatAdministratorRights,
ChatPermissions,
Dice,
File,
InlineKeyboardButton,
InlineKeyboardMarkup,
InlineQueryResultArticle,
InlineQueryResultDocument,
InlineQueryResultVoice,
InputFile,
InputMedia,
InputMessageContent,
InputTextMessageContent,
LabeledPrice,
Expand All @@ -64,7 +62,7 @@
WebAppInfo,
)
from telegram._utils.datetime import UTC, from_timestamp, to_timestamp
from telegram._utils.defaultvalue import DEFAULT_NONE, DefaultValue
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram.constants import (
ChatAction,
InlineQueryLimit,
Expand All @@ -76,15 +74,9 @@
from telegram.ext import ExtBot, InvalidCallbackData
from telegram.helpers import escape_markdown
from telegram.request import BaseRequest, HTTPXRequest, RequestData
from tests.auxil.bot_method_checks import check_defaults_handling
from tests.bots import FALLBACKS
from tests.conftest import (
GITHUB_ACTION,
build_kwargs,
check_defaults_handling,
data_file,
expect_bad_request,
make_bot,
)
from tests.conftest import GITHUB_ACTION, data_file, expect_bad_request, make_bot


def to_camel_case(snake_str):
Expand Down Expand Up @@ -449,77 +441,18 @@ async def test_defaults_handling(
Finally, there are some tests for Defaults.{parse_mode, quote, allow_sending_without_reply}
at the appropriate places, as those are the only things we can actually check.
"""
if bot_method_name.lower().replace("_", "") == "getupdates":
return
if bot_method_name.lower().replace("_", "") == "getme":
# Mocking get_me within check_defaults_handling messes with the cached values like
# Bot.{bot, username, id, …}` unless we return the expected User object.
return_value = bot.bot
else:
return_value = None

try:
# Check that ExtBot does the right thing
bot_method = getattr(bot, bot_method_name)
assert await check_defaults_handling(bot_method, bot)

# check that tg.Bot does the right thing
# make_assertion basically checks everything that happens in
# Bot._insert_defaults and Bot._insert_defaults_for_ilq_results
async def make_assertion(url, request_data: RequestData, *args, **kwargs):
json_data = request_data.parameters

# Check regular kwargs
for k, v in json_data.items():
if isinstance(v, DefaultValue):
pytest.fail(f"Parameter {k} was passed as DefaultValue to request")
elif isinstance(v, InputMedia) and isinstance(v.parse_mode, DefaultValue):
pytest.fail(f"Parameter {k} has a DefaultValue parse_mode")
# Check InputMedia
elif k == "media" and isinstance(v, list):
if any(isinstance(med.get("parse_mode"), DefaultValue) for med in v):
pytest.fail("One of the media items has a DefaultValue parse_mode")

# Check inline query results
if bot_method_name.lower().replace("_", "") == "answerinlinequery":
for result_dict in json_data["results"]:
if isinstance(result_dict.get("parse_mode"), DefaultValue):
pytest.fail("InlineQueryResult has DefaultValue parse_mode")
imc = result_dict.get("input_message_content")
if imc and isinstance(imc.get("parse_mode"), DefaultValue):
pytest.fail(
"InlineQueryResult is InputMessageContext with DefaultValue "
"parse_mode "
)
if imc and isinstance(imc.get("disable_web_page_preview"), DefaultValue):
pytest.fail(
"InlineQueryResult is InputMessageContext with DefaultValue "
"disable_web_page_preview "
)
# Check datetime conversion
until_date = json_data.pop("until_date", None)
if until_date and until_date != 946684800:
pytest.fail("Naive until_date was not interpreted as UTC")

if bot_method_name in ["get_file", "getFile"]:
# The get_file methods try to check if the result is a local file
return File(file_id="result", file_unique_id="result").to_dict()

method = getattr(raw_bot, bot_method_name)
signature = inspect.signature(method)
kwargs_need_default = [
kwarg
for kwarg, value in signature.parameters.items()
if isinstance(value.default, DefaultValue)
]
monkeypatch.setattr(raw_bot.request, "post", make_assertion)
await method(**build_kwargs(inspect.signature(method), kwargs_need_default))
finally:
await bot.get_me() # because running the mock-get_me messages with bot.bot & friends

method = getattr(raw_bot, bot_method_name)
signature = inspect.signature(method)
kwargs_need_default = [
kwarg
for kwarg, value in signature.parameters.items()
if isinstance(value.default, DefaultValue)
]
monkeypatch.setattr(raw_bot.request, "post", make_assertion)
await method(**build_kwargs(inspect.signature(method), kwargs_need_default))
# Check that ExtBot does the right thing
bot_method = getattr(bot, bot_method_name)
raw_bot_method = getattr(raw_bot, bot_method_name)
assert await check_defaults_handling(bot_method, bot, return_value=return_value)
assert await check_defaults_handling(raw_bot_method, raw_bot, return_value=return_value)

def test_ext_bot_signature(self):
"""
Expand Down
2 changes: 1 addition & 1 deletion tests/test_callbackdatacache.py
Expand Up @@ -28,7 +28,7 @@
from telegram._utils.datetime import UTC
from telegram.ext import ExtBot
from telegram.ext._callbackdatacache import CallbackDataCache, InvalidCallbackData, _KeyboardData
from tests.conftest import env_var_2_bool
from tests.auxil.object_conversions import env_var_2_bool


@pytest.fixture(scope="function")
Expand Down
6 changes: 5 additions & 1 deletion tests/test_callbackquery.py
Expand Up @@ -22,7 +22,11 @@
import pytest

from telegram import Audio, Bot, CallbackQuery, Chat, Message, User
from tests.conftest import check_defaults_handling, check_shortcut_call, check_shortcut_signature
from tests.auxil.bot_method_checks import (
check_defaults_handling,
check_shortcut_call,
check_shortcut_signature,
)


@pytest.fixture(scope="function", params=["message", "inline"])
Expand Down
6 changes: 5 additions & 1 deletion tests/test_chat.py
Expand Up @@ -22,7 +22,11 @@
from telegram import Bot, Chat, ChatLocation, ChatPermissions, Location, User
from telegram.constants import ChatAction, ChatType
from telegram.helpers import escape_markdown
from tests.conftest import check_defaults_handling, check_shortcut_call, check_shortcut_signature
from tests.auxil.bot_method_checks import (
check_defaults_handling,
check_shortcut_call,
check_shortcut_signature,
)


@pytest.fixture(scope="class")
Expand Down
6 changes: 5 additions & 1 deletion tests/test_chatjoinrequest.py
Expand Up @@ -22,7 +22,11 @@

from telegram import Bot, Chat, ChatInviteLink, ChatJoinRequest, User
from telegram._utils.datetime import UTC, to_timestamp
from tests.conftest import check_defaults_handling, check_shortcut_call, check_shortcut_signature
from tests.auxil.bot_method_checks import (
check_defaults_handling,
check_shortcut_call,
check_shortcut_signature,
)


@pytest.fixture(scope="class")
Expand Down
5 changes: 2 additions & 3 deletions tests/test_chatphoto.py
Expand Up @@ -25,13 +25,12 @@
from telegram import Bot, ChatPhoto, Voice
from telegram.error import TelegramError
from telegram.request import RequestData
from tests.conftest import (
from tests.auxil.bot_method_checks import (
check_defaults_handling,
check_shortcut_call,
check_shortcut_signature,
data_file,
expect_bad_request,
)
from tests.conftest import data_file, expect_bad_request


@pytest.fixture(scope="function")
Expand Down
2 changes: 1 addition & 1 deletion tests/test_datetime.py
Expand Up @@ -26,7 +26,7 @@
from telegram.ext import Defaults

# sample time specification values categorised into absolute / delta / time-of-day
from tests.conftest import env_var_2_bool
from tests.auxil.object_conversions import env_var_2_bool

ABSOLUTE_TIME_SPECS = [
dtm.datetime.now(tz=dtm.timezone(dtm.timedelta(hours=-7))).replace(second=0, microsecond=0),
Expand Down
2 changes: 1 addition & 1 deletion tests/test_defaults.py
Expand Up @@ -25,7 +25,7 @@

from telegram import User
from telegram.ext import Defaults
from tests.conftest import env_var_2_bool
from tests.auxil.object_conversions import env_var_2_bool

TEST_WITH_OPT_DEPS = env_var_2_bool(os.getenv("TEST_WITH_OPT_DEPS", True))

Expand Down
4 changes: 2 additions & 2 deletions tests/test_document.py
Expand Up @@ -25,12 +25,12 @@
from telegram.error import BadRequest, TelegramError
from telegram.helpers import escape_markdown
from telegram.request import RequestData
from tests.conftest import (
from tests.auxil.bot_method_checks import (
check_defaults_handling,
check_shortcut_call,
check_shortcut_signature,
data_file,
)
from tests.conftest import data_file


@pytest.fixture(scope="function")
Expand Down
6 changes: 5 additions & 1 deletion tests/test_inlinequery.py
Expand Up @@ -20,7 +20,11 @@
import pytest

from telegram import Bot, InlineQuery, Location, Update, User
from tests.conftest import check_defaults_handling, check_shortcut_call, check_shortcut_signature
from tests.auxil.bot_method_checks import (
check_defaults_handling,
check_shortcut_call,
check_shortcut_signature,
)


@pytest.fixture(scope="class")
Expand Down
2 changes: 1 addition & 1 deletion tests/test_jobqueue.py
Expand Up @@ -27,7 +27,7 @@
import pytest

from telegram.ext import ApplicationBuilder, CallbackContext, ContextTypes, Job, JobQueue
from tests.conftest import env_var_2_bool
from tests.auxil.object_conversions import env_var_2_bool

TEST_WITH_OPT_DEPS = env_var_2_bool(os.getenv("TEST_WITH_OPT_DEPS", True))

Expand Down
6 changes: 5 additions & 1 deletion tests/test_message.py
Expand Up @@ -55,7 +55,11 @@
)
from telegram.constants import ChatAction, ParseMode
from telegram.ext import Defaults
from tests.conftest import check_defaults_handling, check_shortcut_call, check_shortcut_signature
from tests.auxil.bot_method_checks import (
check_defaults_handling,
check_shortcut_call,
check_shortcut_signature,
)
from tests.test_passport import RAW_PASSPORT_DATA


Expand Down
2 changes: 1 addition & 1 deletion tests/test_meta.py
Expand Up @@ -20,7 +20,7 @@

import pytest

from tests.conftest import env_var_2_bool
from tests.auxil.object_conversions import env_var_2_bool

skip_disabled = pytest.mark.skipif(
not env_var_2_bool(os.getenv("TEST_BUILD", False)), reason="TEST_BUILD not enabled"
Expand Down
2 changes: 1 addition & 1 deletion tests/test_no_passport.py
Expand Up @@ -32,7 +32,7 @@

from telegram import _bot as bot
from telegram._passport import credentials as credentials
from tests.conftest import env_var_2_bool
from tests.auxil.object_conversions import env_var_2_bool

TEST_WITH_OPT_DEPS = env_var_2_bool(os.getenv("TEST_WITH_OPT_DEPS", True))

Expand Down
2 changes: 1 addition & 1 deletion tests/test_official.py
Expand Up @@ -26,7 +26,7 @@

import telegram
from telegram._utils.defaultvalue import DefaultValue
from tests.conftest import env_var_2_bool
from tests.auxil.object_conversions import env_var_2_bool

IGNORED_OBJECTS = ("ResponseParameters", "CallbackGame")
IGNORED_PARAMETERS = {
Expand Down
6 changes: 5 additions & 1 deletion tests/test_passportfile.py
Expand Up @@ -19,7 +19,11 @@
import pytest

from telegram import Bot, File, PassportElementError, PassportFile
from tests.conftest import check_defaults_handling, check_shortcut_call, check_shortcut_signature
from tests.auxil.bot_method_checks import (
check_defaults_handling,
check_shortcut_call,
check_shortcut_signature,
)


@pytest.fixture(scope="class")
Expand Down
5 changes: 2 additions & 3 deletions tests/test_photo.py
Expand Up @@ -25,13 +25,12 @@
from telegram.error import BadRequest, TelegramError
from telegram.helpers import escape_markdown
from telegram.request import RequestData
from tests.conftest import (
from tests.auxil.bot_method_checks import (
check_defaults_handling,
check_shortcut_call,
check_shortcut_signature,
data_file,
expect_bad_request,
)
from tests.conftest import data_file, expect_bad_request


@pytest.fixture(scope="function")
Expand Down
6 changes: 5 additions & 1 deletion tests/test_precheckoutquery.py
Expand Up @@ -20,7 +20,11 @@
import pytest

from telegram import Bot, OrderInfo, PreCheckoutQuery, Update, User
from tests.conftest import check_defaults_handling, check_shortcut_call, check_shortcut_signature
from tests.auxil.bot_method_checks import (
check_defaults_handling,
check_shortcut_call,
check_shortcut_signature,
)


@pytest.fixture(scope="class")
Expand Down

0 comments on commit ff645c6

Please sign in to comment.