Repository: python-telegram-bot/python-telegram-bot
Pull request: Refactor and overhaul the test suite
Closes #3407. I did not include the `req` marker, but if you'd like that can be easily added as well.

Also some new "features":

- `Dict(Ext)Bot` now overrides `get_me` to return a cached `User` object, which is obtained from the `bot_info` fixture. This saves lots of requests to the real `get_me` every time we initialize a bot, app, or updater.
- A test marked as flaky won't re-run if the test failed with a flood, or was marked to xfail anyway.
- Some tests which make a lot of requests are now run concurrently instead.
- The testing without dependencies part in the CI is now done in one go instead of starting separate runs

Many tests were optimized as well, which should decrease the flakyness in the CI.

#### How do I review this?!

It is best to review by commit, the changes are specific and I rebased multiple times to make sure changes fit in a certain category.

Problem statement:
[REFACTOR] Split test classes into two: `TestXXXNoRequest` & `TestXXXRequest`
Currently each of our test files has about one TestClass, which tests everything about the class together. This is not optimal because:

1. Some tests in the class make actual requests to Telegram, thus slowing down development if you've made substantial changes to the class, but don't actually want to test the request part yet.
2. It makes the tests slightly more readable, bearable and just a bit more organized.

### Implementation

For example, `test_sticker.py` should now look like:

``` python
class StickerSpace:  # namespace class
     emoji = "💪🏽 "
     ...

@pytest.mark.no_req   # for faster development cycle
class TestStickerNoRequest:
    def test_de_json(...):
        ...
    def test_a_mock_request(...):
        ...

@pytest.mark.req  # don't think we need this, but let me know if you'd like this
@pytest.mark.flaky(3, 1)
class TestStickerRequest:
    def test_custom_emoji(...):
        await bot.get_sticker_set(...)

```

Along with this change, I'll also try to simplify/shorten some tests, if possible.

Hints from issue discussion:
Interesting idea. For "substantial changes but not testing the request part"  you probably mean something like first testing that the immutability logic in #3249 works on an "internal" level before checking if it introduces any issues with the Bot AP?

The downsides I see of splitting everything up into several classes are

* probably tideous work to split everything up
* While writing tests one needs to remember what goes where
* Increasing scrolling time

An additional solution that came to my mind would be to monkeypatch `HTTPXRequest.do_post` to `pytail.xfail("Not running tests that make a reuquest")`. I guess it should be possible somehow to make that patch dependent on some flag that can be passed to `pytest`
> Interesting idea. For "substantial changes but not testing the request part" you probably mean something like first testing that the immutability logic in #3249 works on an "internal" level before checking if it introduces any issues with the Bot AP?

can also be helpful in that case, yeah. Sometimes you want test a couple of (non-request) components together, but since they are mixed with longer taking request tests, it slows down development time. The current solution to this, adding a `@pytest.mark.dev` to tests you want to test separately also increases development time (cause you have to add and then remember to remove it) and negates its actual purpose.

> * probably tideous work to split everything up

It's a mostly one time thing and since each test doesn't depend on other tests it shouldn't cause issues.

> * While writing tests one needs to remember what goes where

The idea is when you open the file, it becomes instantly clear what should go where. I'll try to maximize this as much as possible.

> * Increasing scrolling time

I'd say it would decrease scrolling time. For example in a new API update, you'll have to currently scroll everywhere to modify existing tests (specially when you don't know exactly what to change). This is mostly happening cause it's not ordered. E.g. `test_eq` is usually at the end of the file, but `test_de_json` is usually at the beginning.

> An additional solution that came to my mind would be to monkeypatch `HTTPXRequest.do_post` to `pytail.xfail("Not running tests that make a reuquest")`. I guess it should be possible somehow to make that patch dependent on some flag that can be passed to `pytest`

maybe that could work as well, but it violates point 2. in the OP. It's daunting right now to check how the tests work, and this would introduce some hidden logic.

> I'd say it would decrease scrolling time. For example in a new API update, you'll have to currently scroll everywhere to modify existing tests (specially when you don't know exactly what to change). This is mostly happening cause it's not ordered. E.g. test_eq is usually at the end of the file, but test_de_json is usually at the beginning.

Okay, this probably depends on the specific task. If I'm adding a new class, I imagine that sorting by request/no-request leads to me scrolling up & down quite a bit b/c I'm not necessarily adding the tests in that order. I may be proven wrong :)

> maybe that could work as well, but it violates point 2. in the OP.

Point 2 could be achieved at least partially by sorting the tests within the same class though, right? We could add a notable comment break between some, something like

```python
# <---------------------------------------------------------------------------->
# Tests Below this line make requests to the Bot API
# <---------------------------------------------------------------------------->
```

Though I agree that skipping all the `flaky` decorators would indeed be cool :D

> It's daunting right now to check how the tests work, and this would introduce some hidden logic.

I'm not sure if I correctly understand what you mean by the first part of the sentence.
For the hidden logic, I must say that for anyone who hasn't spent a lot of type with `pytest`, `@pytest.mark.{no_req, req, dev}` are IMO little more explicit. Either way you'll have to pass a parameter to `pytest` and just by seeing the decorator `@pytest.mark.no_req`, I don't think it's obvious what that's for and how it can be used.

---

Another general question/comment: This would only make sense for the classes in the `telegram` module, right? B/C for `tg.ext` we mostly don't make any requests at all and if we do (I think we do at least a few times in testing `Application`) the main intent is not to test the API functionality, but how it interates into ext 🤔 

> I'm not sure if I correctly understand what you mean by the first part of the sentence. 

I mean new users, who are not too familiar with pytest have a hard time understanding what's going on, so some explicitness would help them more.

> just by seeing the decorator `@pytest.mark.no_req`, I don't think it's obvious what that's for and how it can be used.

I'll also add a short comment next to each of these explaining how to use them.
 
> Another general question/comment: This would only make sense for the classes in the `telegram` module, right? 

yep. 
> > just by seeing the decorator `@pytest.mark.no_req`, I don't think it's obvious what that's for and how it can be used.
> 
> I'll also add a short comment next to each of these explaining how to use them.

I wouldn't like that tbh. The comments would have to be repeated many times and may easily be forgotten when writing new tests. Plus, it's only really helpful once for each new person looking into the tests (which isn't *that* often).
What would you instead think of adding a `README` to the `tests` directory that gathers some useful insights on how the tests work and what goes where? We could also make it a wiki page (for easier editing) and have the readme point there. The contrib guide could also point to that file.

------

In total I'll vote +1 on adding an option to exclude requests-based tests (as I can see the benefit of that) and -0 on splitting tests into different classes for that (as I'm not entirely convinced of the benefit of that).

I'd like to hear the opinion of the other team members before any PR is opened for this.

> What would you instead think of adding a `README` to the `tests` directory that gathers some useful insights on how the tests work and what goes where? We could also make it a wiki page (for easier editing) and have the readme point there. The contrib guide could also point to that file.

Yeah that's a better idea, I like it
I really like the approach of having a request and non request class to be fair.

I can see the point about this being a lot of work to do for all tests at once, I neither see the point about more scrolling (I have to scroll a lot now anyway, and I usually do all the non request parts first before others for new Types in API updates), nor about "needing to remember", right now I need to remember to add flaky and nothing warns me if I forget it. Having this split up in two classes with one decorator will decrease repetition and make it way easier to catch if someone put a request test where it doesn't belong.

+1 from me for implementing this.

> What would you instead think of adding a `README` to the `tests` directory that gathers some useful insights on how the tests work and what goes where? We could also make it a wiki page (for easier editing) and have the readme point there. The contrib guide could also point to that file.

I like this idea. It's funny coming from me because I have never looked for a `README` in a `tests` dir before 😆 But it could work especially if there is a link from the contrib guide.

Commit message: Feat: Make some tests run concurrently via asyncio.gather/as_completed/create_task

let's take full advantage of the lib now being async

Patch to review:
diff --git a/requirements-dev.txt b/requirements-dev.txt
index c886b6f540d..b06bf6bc29d 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -2,7 +2,6 @@ pre-commit
 
 pytest==7.2.0
 pytest-asyncio==0.20.3
-pytest-timeout==2.1.0 # used to timeout tests
 pytest-xdist==3.1.0  # xdist runs tests in parallel
 
 flaky  # Used for flaky tests (flaky decorator)
diff --git a/setup.cfg b/setup.cfg
index a0e0eb8561b..60c2cf57478 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -36,7 +36,10 @@ filterwarnings =
 ;    Unfortunately due to https://github.com/pytest-dev/pytest/issues/8343 we can't have this here
 ;    and instead do a trick directly in tests/conftest.py
 ;    ignore::telegram.utils.deprecate.TelegramDeprecationWarning
-markers = dev: If you want to test a specific test, use this
+markers =
+    dev: If you want to test a specific test, use this
+    no_req
+    req
 asyncio_mode = auto
 
 [coverage:run]
diff --git a/tests/conftest.py b/tests/conftest.py
index 06e12e98c4e..c817c02d239 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -22,7 +22,7 @@
 import re
 import sys
 from pathlib import Path
-from typing import Callable, Optional
+from typing import Callable, List, Optional
 
 import pytest
 from httpx import AsyncClient, Response
@@ -52,12 +52,37 @@
 
 
 # This is here instead of in setup.cfg due to https://github.com/pytest-dev/pytest/issues/8343
-def pytest_runtestloop(session):
+def pytest_runtestloop(session: pytest.Session):
     session.add_marker(
         pytest.mark.filterwarnings("ignore::telegram.warnings.PTBDeprecationWarning")
     )
 
 
+def pytest_collection_modifyitems(items: List[pytest.Item]):
+    """Here we add a flaky marker to all request making tests and the no_req marker to the rest."""
+    for item in items:
+        parent = item.parent
+        if parent is None:
+            return
+        if (
+            "NoReq" not in parent.name
+            and parent.name.endswith("Req")
+            and not parent.get_closest_marker(name="flaky")
+        ):
+            parent.add_marker(pytest.mark.flaky(3, 1, rerun_filter=no_rerun_after_xfail_or_flood))
+        elif parent.name.endswith("NoReq") and not parent.get_closest_marker(name="no_req"):
+            parent.add_marker(pytest.mark.no_req)
+
+
+def no_rerun_after_xfail_or_flood(error, name, test: pytest.Function, plugin):
+    """Don't rerun tests that have xfailed when marked with xfail, or when we hit a flood limit."""
+    xfail_present = test.get_closest_marker(name="xfail")
+    did_we_flood = "flood" in getattr(error[1], "msg", "")  # _pytest.outcomes.XFailed has 'msg'
+    if xfail_present or did_we_flood:
+        return False
+    return True
+
+
 GITHUB_ACTION = os.getenv("GITHUB_ACTION", False)
 
 if GITHUB_ACTION:
@@ -86,19 +111,12 @@ def event_loop(request):
     # loop.close() # instead of closing here, do that at the every end of the test session
 
 
-# Related to the above, see https://stackoverflow.com/a/67307042/10606962
-def pytest_sessionfinish(session, exitstatus):
-    asyncio.get_event_loop().close()
-
-
 @pytest.fixture(scope="session")
 def bot_info():
     return get_bot()
 
 
 # Below classes are used to monkeypatch attributes since parent classes don't have __dict__
-
-
 class TestHttpxRequest(HTTPXRequest):
     async def _request_wrapper(
         self,
@@ -132,6 +150,12 @@ def __init__(self, *args, **kwargs):
         # Makes it easier to work with the bot in tests
         self._unfreeze()
 
+    # Here we override get_me for caching because we don't want to call the API repeatedly in tests
+    async def get_me(self, *args, **kwargs):
+        if self._bot_user is None:
+            self._bot_user = make_mock_user(self.token)
+        return self._bot_user
+
 
 class DictBot(Bot):
     def __init__(self, *args, **kwargs):
@@ -139,11 +163,34 @@ def __init__(self, *args, **kwargs):
         # Makes it easier to work with the bot in tests
         self._unfreeze()
 
+    # Here we override get_me for caching because we don't want to call the API repeatedly in tests
+    async def get_me(self, *args, **kwargs):
+        if self._bot_user is None:
+            self._bot_user = make_mock_user(self.token)
+        return self._bot_user
+
 
 class DictApplication(Application):
     pass
 
 
+def make_mock_user(token: str) -> User:
+    """Used to return a mock user in bot.get_me(). This saves API calls on every init."""
+    bot_info = get_bot()
+    user_id = int(token.split(":")[0] or bot_info["token"].split(":")[0])
+    first_name = bot_info.get("bot_name") or bot_info.get("name")
+    username = (bot_info.get("bot_username") or bot_info.get("username")).strip("@")
+    return User(
+        user_id,
+        first_name,
+        is_bot=True,
+        username=username,
+        can_join_groups=True,
+        can_read_all_group_messages=False,
+        supports_inline_queries=True,
+    )
+
+
 @pytest.fixture(scope="session")
 async def bot(bot_info):
     """Makes an ExtBot instance with the given bot_info"""
@@ -170,20 +217,35 @@ async def raw_bot(bot_info):
         yield _bot
 
 
-@pytest.fixture(scope="function")
+default_bots = {}
+
+
+@pytest.fixture(scope="session")
 async def default_bot(request, bot_info):
     param = request.param if hasattr(request, "param") else {}
+    defaults = Defaults(**param)
 
-    default_bot = make_bot(bot_info, defaults=Defaults(**param))
-    async with default_bot:
-        yield default_bot
+    # If the bot is already created, return it. Else make a new one.
+    default_bot = default_bots.get(defaults, None)
+    if default_bot is None:
+        default_bot = make_bot(bot_info, defaults=defaults)
+        await default_bot.initialize()
+        default_bots[defaults] = default_bot  # Defaults object is hashable
+    return default_bot
 
 
-@pytest.fixture(scope="function")
+tz_bots = {}
+
+
+@pytest.fixture(scope="session")
 async def tz_bot(timezone, bot_info):
-    default_bot = make_bot(bot_info, defaults=Defaults(tzinfo=timezone))
-    async with default_bot:
-        yield default_bot
+    try:  # If the bot is already created, return it. Saves time since get_me is not called again.
+        return tz_bots[timezone]
+    except KeyError:
+        default_bot = make_bot(bot_info, defaults=Defaults(tzinfo=timezone))
+        await default_bot.initialize()
+        tz_bots[timezone] = default_bot
+        return default_bot
 
 
 @pytest.fixture(scope="session")
@@ -243,16 +305,14 @@ def data_file(filename: str) -> Path:
 
 @pytest.fixture(scope="function")
 def thumb_file():
-    f = data_file("thumb.jpg").open("rb")
-    yield f
-    f.close()
+    with data_file("thumb.jpg").open("rb") as f:
+        yield f
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def class_thumb_file():
-    f = data_file("thumb.jpg").open("rb")
-    yield f
-    f.close()
+    with data_file("thumb.jpg").open("rb") as f:
+        yield f
 
 
 def make_bot(bot_info=None, **kwargs):
@@ -401,7 +461,7 @@ def dst(self, dt):
         return datetime.timedelta(0)
 
 
-@pytest.fixture(params=["Europe/Berlin", "Asia/Singapore", "UTC"])
+@pytest.fixture(scope="session", params=["Europe/Berlin", "Asia/Singapore", "UTC"])
 def tzinfo(request):
     if TEST_WITH_OPT_DEPS:
         return pytz.timezone(request.param)
@@ -410,7 +470,7 @@ def tzinfo(request):
         return BasicTimezone(offset=datetime.timedelta(hours=hours_offset), name=request.param)
 
 
-@pytest.fixture()
+@pytest.fixture(scope="session")
 def timezone(tzinfo):
     return tzinfo
 
diff --git a/tests/test_animation.py b/tests/test_animation.py
index 98c2184eaba..76b3544b711 100644
--- a/tests/test_animation.py
+++ b/tests/test_animation.py
@@ -16,6 +16,7 @@
 #
 # You should have received a copy of the GNU Lesser Public License
 # along with this program.  If not, see [http://www.gnu.org/licenses/].
+import asyncio
 import os
 from pathlib import Path
 
@@ -35,21 +36,19 @@
 
 @pytest.fixture(scope="function")
 def animation_file():
-    f = data_file("game.gif").open("rb")
-    yield f
-    f.close()
+    with data_file("game.gif").open("rb") as f:
+        yield f
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 async def animation(bot, chat_id):
-    with data_file("game.gif").open("rb") as f:
-        thumb = data_file("thumb.jpg")
+    with data_file("game.gif").open("rb") as f, data_file("thumb.jpg").open("rb") as thumb:
         return (
-            await bot.send_animation(chat_id, animation=f, read_timeout=50, thumb=thumb.open("rb"))
+            await bot.send_animation(chat_id, animation=f, read_timeout=50, thumb=thumb)
         ).animation
 
 
-class TestAnimation:
+class Space:
     animation_file_id = "CgADAQADngIAAuyVeEez0xRovKi9VAI"
     animation_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
     width = 320
@@ -63,6 +62,8 @@ class TestAnimation:
     file_size = 5859
     caption = "Test *animation*"
 
+
+class TestAnimationNoReq:
     def test_slot_behaviour(self, animation, mro_slots):
         for attr in animation.__slots__:
             assert getattr(animation, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -76,19 +77,131 @@ def test_creation(self, animation):
         assert animation.file_unique_id != ""
 
     def test_expected_values(self, animation):
-        assert animation.mime_type == self.mime_type
-        assert animation.file_name.startswith("game.gif") == self.file_name.startswith("game.gif")
+        assert animation.mime_type == Space.mime_type
+        assert animation.file_name.startswith("game.gif") == Space.file_name.startswith("game.gif")
         assert isinstance(animation.thumb, PhotoSize)
 
-    @pytest.mark.flaky(3, 1)
+    async def test_send_animation_custom_filename(self, bot, chat_id, animation_file, monkeypatch):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            return list(request_data.multipart_data.values())[0][0] == "custom_filename"
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+
+        assert await bot.send_animation(chat_id, animation_file, filename="custom_filename")
+        monkeypatch.delattr(bot.request, "post")
+
+    @pytest.mark.parametrize("local_mode", [True, False])
+    async def test_send_animation_local_files(self, monkeypatch, bot, chat_id, local_mode):
+        try:
+            bot._local_mode = local_mode
+            # For just test that the correct paths are passed as we have no local bot API set up
+            test_flag = False
+            file = data_file("telegram.jpg")
+            expected = file.as_uri()
+
+            async def make_assertion(_, data, *args, **kwargs):
+                nonlocal test_flag
+                if local_mode:
+                    test_flag = data.get("animation") == expected and data.get("thumb") == expected
+                else:
+                    test_flag = isinstance(data.get("animation"), InputFile) and isinstance(
+                        data.get("thumb"), InputFile
+                    )
+
+            monkeypatch.setattr(bot, "_post", make_assertion)
+            await bot.send_animation(chat_id, file, thumb=file)
+            assert test_flag
+            monkeypatch.delattr(bot, "_post")
+        finally:
+            bot._local_mode = False
+
+    async def test_send_with_animation(self, monkeypatch, bot, chat_id, animation):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            return request_data.json_parameters["animation"] == animation.file_id
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+        message = await bot.send_animation(animation=animation, chat_id=chat_id)
+        assert message
+
+    def test_de_json(self, bot, animation):
+        json_dict = {
+            "file_id": Space.animation_file_id,
+            "file_unique_id": Space.animation_file_unique_id,
+            "width": Space.width,
+            "height": Space.height,
+            "duration": Space.duration,
+            "thumb": animation.thumb.to_dict(),
+            "file_name": Space.file_name,
+            "mime_type": Space.mime_type,
+            "file_size": Space.file_size,
+        }
+        animation = Animation.de_json(json_dict, bot)
+        assert animation.api_kwargs == {}
+        assert animation.file_id == Space.animation_file_id
+        assert animation.file_unique_id == Space.animation_file_unique_id
+        assert animation.file_name == Space.file_name
+        assert animation.mime_type == Space.mime_type
+        assert animation.file_size == Space.file_size
+
+    def test_to_dict(self, animation):
+        animation_dict = animation.to_dict()
+
+        assert isinstance(animation_dict, dict)
+        assert animation_dict["file_id"] == animation.file_id
+        assert animation_dict["file_unique_id"] == animation.file_unique_id
+        assert animation_dict["width"] == animation.width
+        assert animation_dict["height"] == animation.height
+        assert animation_dict["duration"] == animation.duration
+        assert animation_dict["thumb"] == animation.thumb.to_dict()
+        assert animation_dict["file_name"] == animation.file_name
+        assert animation_dict["mime_type"] == animation.mime_type
+        assert animation_dict["file_size"] == animation.file_size
+
+    async def test_get_file_instance_method(self, monkeypatch, animation):
+        async def make_assertion(*_, **kwargs):
+            return kwargs["file_id"] == animation.file_id
+
+        assert check_shortcut_signature(Animation.get_file, Bot.get_file, ["file_id"], [])
+        assert await check_shortcut_call(animation.get_file, animation.get_bot(), "get_file")
+        assert await check_defaults_handling(animation.get_file, animation.get_bot())
+
+        monkeypatch.setattr(animation.get_bot(), "get_file", make_assertion)
+        assert await animation.get_file()
+
+    def test_equality(self):
+        a = Animation(
+            Space.animation_file_id,
+            Space.animation_file_unique_id,
+            Space.height,
+            Space.width,
+            Space.duration,
+        )
+        b = Animation(
+            "", Space.animation_file_unique_id, Space.height, Space.width, Space.duration
+        )
+        d = Animation("", "", 0, 0, 0)
+        e = Voice(Space.animation_file_id, Space.animation_file_unique_id, 0)
+
+        assert a == b
+        assert hash(a) == hash(b)
+        assert a is not b
+
+        assert a != d
+        assert hash(a) != hash(d)
+
+        assert a != e
+        assert hash(a) != hash(e)
+
+
+class TestAnimationReq:
     async def test_send_all_args(self, bot, chat_id, animation_file, animation, thumb_file):
         message = await bot.send_animation(
             chat_id,
             animation_file,
-            duration=self.duration,
-            width=self.width,
-            height=self.height,
-            caption=self.caption,
+            duration=Space.duration,
+            width=Space.width,
+            height=Space.height,
+            caption=Space.caption,
             parse_mode="Markdown",
             disable_notification=False,
             protect_content=True,
@@ -103,21 +216,10 @@ async def test_send_all_args(self, bot, chat_id, animation_file, animation, thum
         assert message.animation.file_name == animation.file_name
         assert message.animation.mime_type == animation.mime_type
         assert message.animation.file_size == animation.file_size
-        assert message.animation.thumb.width == self.width
-        assert message.animation.thumb.height == self.height
+        assert message.animation.thumb.width == Space.width
+        assert message.animation.thumb.height == Space.height
         assert message.has_protected_content
 
-    @pytest.mark.flaky(3, 1)
-    async def test_send_animation_custom_filename(self, bot, chat_id, animation_file, monkeypatch):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            return list(request_data.multipart_data.values())[0][0] == "custom_filename"
-
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-
-        assert await bot.send_animation(chat_id, animation_file, filename="custom_filename")
-        monkeypatch.delattr(bot.request, "post")
-
-    @pytest.mark.flaky(3, 1)
     async def test_get_and_download(self, bot, animation):
         path = Path("game.gif")
         if path.is_file():
@@ -132,13 +234,12 @@ async def test_get_and_download(self, bot, animation):
 
         assert new_filepath.is_file()
 
-    @pytest.mark.flaky(3, 1)
     async def test_send_animation_url_file(self, bot, chat_id, animation):
         message = await bot.send_animation(
-            chat_id=chat_id, animation=self.animation_file_url, caption=self.caption
+            chat_id=chat_id, animation=Space.animation_file_url, caption=Space.caption
         )
 
-        assert message.caption == self.caption
+        assert message.caption == Space.caption
 
         assert isinstance(message.animation, Animation)
         assert isinstance(message.animation.file_id, str)
@@ -152,7 +253,6 @@ async def test_send_animation_url_file(self, bot, chat_id, animation):
         ) == animation.file_name.startswith("game.gif")
         assert message.animation.mime_type == animation.mime_type
 
-    @pytest.mark.flaky(3, 1)
     async def test_send_animation_caption_entities(self, bot, chat_id, animation):
         test_string = "Italic Bold Code"
         entities = [
@@ -167,7 +267,6 @@ async def test_send_animation_caption_entities(self, bot, chat_id, animation):
         assert message.caption == test_string
         assert message.caption_entities == tuple(entities)
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_send_animation_default_parse_mode_1(self, default_bot, chat_id, animation_file):
         test_string = "Italic Bold Code"
@@ -179,7 +278,6 @@ async def test_send_animation_default_parse_mode_1(self, default_bot, chat_id, a
         assert message.caption_markdown == test_markdown_string
         assert message.caption == test_string
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_send_animation_default_parse_mode_2(self, default_bot, chat_id, animation_file):
         test_markdown_string = "_Italic_ *Bold* `Code`"
@@ -190,7 +288,6 @@ async def test_send_animation_default_parse_mode_2(self, default_bot, chat_id, a
         assert message.caption == test_markdown_string
         assert message.caption_markdown == escape_markdown(test_markdown_string)
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_send_animation_default_parse_mode_3(self, default_bot, chat_id, animation_file):
         test_markdown_string = "_Italic_ *Bold* `Code`"
@@ -201,32 +298,6 @@ async def test_send_animation_default_parse_mode_3(self, default_bot, chat_id, a
         assert message.caption == test_markdown_string
         assert message.caption_markdown == escape_markdown(test_markdown_string)
 
-    @pytest.mark.parametrize("local_mode", [True, False])
-    async def test_send_animation_local_files(self, monkeypatch, bot, chat_id, local_mode):
-        try:
-            bot._local_mode = local_mode
-            # For just test that the correct paths are passed as we have no local bot API set up
-            test_flag = False
-            file = data_file("telegram.jpg")
-            expected = file.as_uri()
-
-            async def make_assertion(_, data, *args, **kwargs):
-                nonlocal test_flag
-                if local_mode:
-                    test_flag = data.get("animation") == expected and data.get("thumb") == expected
-                else:
-                    test_flag = isinstance(data.get("animation"), InputFile) and isinstance(
-                        data.get("thumb"), InputFile
-                    )
-
-            monkeypatch.setattr(bot, "_post", make_assertion)
-            await bot.send_animation(chat_id, file, thumb=file)
-            assert test_flag
-            monkeypatch.delattr(bot, "_post")
-        finally:
-            bot._local_mode = False
-
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize(
         "default_bot,custom",
         [
@@ -260,72 +331,27 @@ async def test_send_animation_default_allow_sending_without_reply(
                     chat_id, animation, reply_to_message_id=reply_to_message.message_id
                 )
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
     async def test_send_animation_default_protect_content(self, default_bot, chat_id, animation):
-        animation_protected = await default_bot.send_animation(chat_id, animation)
-        assert animation_protected.has_protected_content
-        ani_unprotected = await default_bot.send_animation(
-            chat_id, animation, protect_content=False
+        tasks = asyncio.gather(
+            default_bot.send_animation(chat_id, animation),
+            default_bot.send_animation(chat_id, animation, protect_content=False),
         )
-        assert not ani_unprotected.has_protected_content
+        anim_protected, anim_unprotected = await tasks
+        assert anim_protected.has_protected_content
+        assert not anim_unprotected.has_protected_content
 
-    @pytest.mark.flaky(3, 1)
     async def test_resend(self, bot, chat_id, animation):
         message = await bot.send_animation(chat_id, animation.file_id)
 
         assert message.animation == animation
 
-    async def test_send_with_animation(self, monkeypatch, bot, chat_id, animation):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            return request_data.json_parameters["animation"] == animation.file_id
-
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-        message = await bot.send_animation(animation=animation, chat_id=chat_id)
-        assert message
-
-    def test_de_json(self, bot, animation):
-        json_dict = {
-            "file_id": self.animation_file_id,
-            "file_unique_id": self.animation_file_unique_id,
-            "width": self.width,
-            "height": self.height,
-            "duration": self.duration,
-            "thumb": animation.thumb.to_dict(),
-            "file_name": self.file_name,
-            "mime_type": self.mime_type,
-            "file_size": self.file_size,
-        }
-        animation = Animation.de_json(json_dict, bot)
-        assert animation.api_kwargs == {}
-        assert animation.file_id == self.animation_file_id
-        assert animation.file_unique_id == self.animation_file_unique_id
-        assert animation.file_name == self.file_name
-        assert animation.mime_type == self.mime_type
-        assert animation.file_size == self.file_size
-
-    def test_to_dict(self, animation):
-        animation_dict = animation.to_dict()
-
-        assert isinstance(animation_dict, dict)
-        assert animation_dict["file_id"] == animation.file_id
-        assert animation_dict["file_unique_id"] == animation.file_unique_id
-        assert animation_dict["width"] == animation.width
-        assert animation_dict["height"] == animation.height
-        assert animation_dict["duration"] == animation.duration
-        assert animation_dict["thumb"] == animation.thumb.to_dict()
-        assert animation_dict["file_name"] == animation.file_name
-        assert animation_dict["mime_type"] == animation.mime_type
-        assert animation_dict["file_size"] == animation.file_size
-
-    @pytest.mark.flaky(3, 1)
     async def test_error_send_empty_file(self, bot, chat_id):
         animation_file = open(os.devnull, "rb")
 
         with pytest.raises(TelegramError):
             await bot.send_animation(chat_id=chat_id, animation=animation_file)
 
-    @pytest.mark.flaky(3, 1)
     async def test_error_send_empty_file_id(self, bot, chat_id):
         with pytest.raises(TelegramError):
             await bot.send_animation(chat_id=chat_id, animation="")
@@ -333,36 +359,3 @@ async def test_error_send_empty_file_id(self, bot, chat_id):
     async def test_error_send_without_required_args(self, bot, chat_id):
         with pytest.raises(TypeError):
             await bot.send_animation(chat_id=chat_id)
-
-    async def test_get_file_instance_method(self, monkeypatch, animation):
-        async def make_assertion(*_, **kwargs):
-            return kwargs["file_id"] == animation.file_id
-
-        assert check_shortcut_signature(Animation.get_file, Bot.get_file, ["file_id"], [])
-        assert await check_shortcut_call(animation.get_file, animation.get_bot(), "get_file")
-        assert await check_defaults_handling(animation.get_file, animation.get_bot())
-
-        monkeypatch.setattr(animation.get_bot(), "get_file", make_assertion)
-        assert await animation.get_file()
-
-    def test_equality(self):
-        a = Animation(
-            self.animation_file_id,
-            self.animation_file_unique_id,
-            self.height,
-            self.width,
-            self.duration,
-        )
-        b = Animation("", self.animation_file_unique_id, self.height, self.width, self.duration)
-        d = Animation("", "", 0, 0, 0)
-        e = Voice(self.animation_file_id, self.animation_file_unique_id, 0)
-
-        assert a == b
-        assert hash(a) == hash(b)
-        assert a is not b
-
-        assert a != d
-        assert hash(a) != hash(d)
-
-        assert a != e
-        assert hash(a) != hash(e)
diff --git a/tests/test_application.py b/tests/test_application.py
index 698c40bbc09..a2659d8eab6 100644
--- a/tests/test_application.py
+++ b/tests/test_application.py
@@ -53,7 +53,18 @@
     filters,
 )
 from telegram.warnings import PTBUserWarning
-from tests.conftest import PROJECT_ROOT_PATH, call_after, make_message_update, send_webhook_message
+from tests.conftest import (
+    PROJECT_ROOT_PATH,
+    call_after,
+    make_bot,
+    make_message_update,
+    send_webhook_message,
+)
+
+
+@pytest.fixture(scope="function")
+def test_bot(bot_info):  # was needed since we get HTTPXRequest not initialized after app tests
+    return make_bot(bot_info)
 
 
 class CustomContext(CallbackContext):
@@ -113,8 +124,8 @@ async def callback_context(self, update, context):
         ):
             self.received = context.error.message
 
-    async def test_slot_behaviour(self, bot, mro_slots):
-        async with ApplicationBuilder().token(bot.token).build() as app:
+    async def test_slot_behaviour(self, test_bot, mro_slots):
+        async with ApplicationBuilder().bot(test_bot).build() as app:
             for at in app.__slots__:
                 at = f"_Application{at}" if at.startswith("__") and not at.endswith("__") else at
                 assert getattr(app, at, "err") != "err", f"got extra slot '{at}'"
@@ -143,12 +154,12 @@ def test_manual_init_warning(self, recwarn, updater):
         "concurrent_updates, expected", [(0, 0), (4, 4), (False, 0), (True, 256)]
     )
     @pytest.mark.filterwarnings("ignore: `Application` instances should")
-    def test_init(self, bot, concurrent_updates, expected):
+    def test_init(self, test_bot, concurrent_updates, expected):
         update_queue = asyncio.Queue()
         job_queue = JobQueue()
         persistence = PicklePersistence("file_path")
         context_types = ContextTypes()
-        updater = Updater(bot=bot, update_queue=update_queue)
+        updater = Updater(bot=test_bot, update_queue=update_queue)
 
         async def post_init(application: Application) -> None:
             pass
@@ -157,7 +168,7 @@ async def post_shutdown(application: Application) -> None:
             pass
 
         app = Application(
-            bot=bot,
+            bot=test_bot,
             update_queue=update_queue,
             job_queue=job_queue,
             persistence=persistence,
@@ -167,7 +178,7 @@ async def post_shutdown(application: Application) -> None:
             post_init=post_init,
             post_shutdown=post_shutdown,
         )
-        assert app.bot is bot
+        assert app.bot is test_bot
         assert app.update_queue is update_queue
         assert app.job_queue is job_queue
         assert app.persistence is persistence
@@ -190,7 +201,7 @@ async def post_shutdown(application: Application) -> None:
 
         with pytest.raises(ValueError, match="must be a non-negative"):
             Application(
-                bot=bot,
+                bot=test_bot,
                 update_queue=update_queue,
                 job_queue=job_queue,
                 persistence=persistence,
@@ -201,13 +212,13 @@ async def post_shutdown(application: Application) -> None:
                 post_shutdown=None,
             )
 
-    def test_job_queue(self, bot, app, recwarn):
+    def test_job_queue(self, test_bot, app, recwarn):
         expected_warning = (
             "No `JobQueue` set up. To use `JobQueue`, you must install PTB via "
             "`pip install python-telegram-bot[job_queue]`."
         )
         assert app.job_queue is app._job_queue
-        application = ApplicationBuilder().token(bot.token).job_queue(None).build()
+        application = ApplicationBuilder().bot(test_bot).job_queue(None).build()
         assert application.job_queue is None
         assert len(recwarn) == 1
         assert str(recwarn[0].message) == expected_warning
@@ -221,14 +232,14 @@ def test_custom_context_init(self, bot):
             bot_data=complex,
         )
 
-        application = ApplicationBuilder().token(bot.token).context_types(cc).build()
+        application = ApplicationBuilder().bot(test_bot).context_types(cc).build()
 
         assert isinstance(application.user_data[1], int)
         assert isinstance(application.chat_data[1], float)
         assert isinstance(application.bot_data, complex)
 
     @pytest.mark.parametrize("updater", (True, False))
-    async def test_initialize(self, bot, monkeypatch, updater):
+    async def test_initialize(self, test_bot, monkeypatch, updater):
         """Initialization of persistence is tested test_basepersistence"""
         self.test_flag = set()
 
@@ -244,18 +255,18 @@ async def after_initialize_updater(*args, **kwargs):
         )
 
         if updater:
-            app = ApplicationBuilder().token(bot.token).build()
+            app = ApplicationBuilder().bot(test_bot).build()
             await app.initialize()
             assert self.test_flag == {"bot", "updater"}
             await app.shutdown()
         else:
-            app = ApplicationBuilder().token(bot.token).updater(None).build()
+            app = ApplicationBuilder().bot(test_bot).updater(None).build()
             await app.initialize()
             assert self.test_flag == {"bot"}
             await app.shutdown()
 
     @pytest.mark.parametrize("updater", (True, False))
-    async def test_shutdown(self, bot, monkeypatch, updater):
+    async def test_shutdown(self, test_bot, monkeypatch, updater):
         """Shutdown of persistence is tested in test_basepersistence"""
         self.test_flag = set()
 
@@ -271,11 +282,11 @@ def after_updater_shutdown(*args, **kwargs):
         )
 
         if updater:
-            async with ApplicationBuilder().token(bot.token).build():
+            async with ApplicationBuilder().bot(test_bot).build():
                 pass
             assert self.test_flag == {"bot", "updater"}
         else:
-            async with ApplicationBuilder().token(bot.token).updater(None).build():
+            async with ApplicationBuilder().bot(test_bot).updater(None).build():
                 pass
             assert self.test_flag == {"bot"}
 
@@ -322,12 +333,12 @@ async def test_shutdown_while_running(self, app):
                 await app.shutdown()
             await app.stop()
 
-    async def test_start_not_running_after_failure(self, bot, monkeypatch):
+    async def test_start_not_running_after_failure(self, test_bot, monkeypatch):
         def start(_):
             raise Exception("Test Exception")
 
         monkeypatch.setattr(JobQueue, "start", start)
-        app = ApplicationBuilder().token(bot.token).job_queue(JobQueue()).build()
+        app = ApplicationBuilder().bot(test_bot).job_queue(JobQueue()).build()
 
         async with app:
             with pytest.raises(Exception, match="Test Exception"):
@@ -398,12 +409,12 @@ def test_builder(self, app):
 
     @pytest.mark.parametrize("job_queue", (True, False))
     @pytest.mark.filterwarnings("ignore::telegram.warnings.PTBUserWarning")
-    async def test_start_stop_processing_updates(self, bot, job_queue):
+    async def test_start_stop_processing_updates(self, test_bot, job_queue):
         # TODO: repeat a similar test for create_task, persistence processing and job queue
         if job_queue:
-            app = ApplicationBuilder().token(bot.token).build()
+            app = ApplicationBuilder().bot(test_bot).build()
         else:
-            app = ApplicationBuilder().token(bot.token).job_queue(None).build()
+            app = ApplicationBuilder().bot(test_bot).job_queue(None).build()
 
         async def callback(u, c):
             self.received = u
@@ -433,9 +444,10 @@ async def callback(u, c):
             await asyncio.sleep(0.05)
             assert app.update_queue.empty()
             assert self.received == 1
-
-            await app.updater.start_polling()
-            await app.stop()
+            try:  # just in case start_polling times out
+                await app.updater.start_polling()
+            finally:  # stop the app so it doesn't crash on shutdown
+                await app.stop()
             assert not app.running
             # app.stop() should not stop the updater!
             assert app.updater.running
@@ -469,7 +481,7 @@ async def test_one_context_per_update(self, app):
         async def one(update, context):
             self.received = context
 
-        def two(update, context):
+        async def two(update, context):
             if update.message.text == "test":
                 if context is not self.received:
                     pytest.fail("Expected same context object, got different")
@@ -636,7 +648,7 @@ def handle_update(
             await asyncio.sleep(0.05)
             await app.stop()
 
-    async def test_flow_stop(self, app, bot):
+    async def test_flow_stop(self, app, test_bot):
         passed = []
 
         async def start1(b, u):
@@ -661,7 +673,8 @@ async def start3(b, u):
                 ],
             ),
         )
-        update.message.set_bot(bot)
+        await test_bot.initialize()
+        update.message.set_bot(test_bot)
 
         async with app:
             # If ApplicationHandlerStop raised handlers in other groups should not be called.
@@ -672,7 +685,7 @@ async def start3(b, u):
             await app.process_update(update)
             assert passed == ["start1"]
 
-    async def test_flow_stop_by_error_handler(self, app, bot):
+    async def test_flow_stop_by_error_handler(self, app):
         passed = []
         exception = Exception("General excepition")
 
@@ -721,7 +734,7 @@ async def test_error_in_handler_part_1(self, app):
         # Higher groups should still be called
         assert self.count == 42
 
-    async def test_error_in_handler_part_2(self, app, bot):
+    async def test_error_in_handler_part_2(self, app, test_bot):
         passed = []
         err = Exception("General exception")
 
@@ -751,7 +764,8 @@ async def error(u, c):
                 ],
             ),
         )
-        update.message.set_bot(bot)
+        await test_bot.initialize()
+        update.message.set_bot(test_bot)
 
         async with app:
             # If an unhandled exception was caught, no further handlers from the same group should
@@ -830,7 +844,7 @@ async def test_error_handler_that_raises_errors(self, app, caplog):
 
                 await app.stop()
 
-    async def test_custom_context_error_handler(self, bot):
+    async def test_custom_context_error_handler(self, test_bot):
         async def error_handler(_, context):
             self.received = (
                 type(context),
@@ -841,7 +855,7 @@ async def error_handler(_, context):
 
         application = (
             ApplicationBuilder()
-            .token(bot.token)
+            .bot(test_bot)
             .context_types(
                 ContextTypes(
                     context=CustomContext, bot_data=int, user_data=float, chat_data=complex
@@ -859,8 +873,8 @@ async def error_handler(_, context):
             await asyncio.sleep(0.05)
             assert self.received == (CustomContext, float, complex, int)
 
-    async def test_custom_context_handler_callback(self, bot):
-        def callback(_, context):
+    async def test_custom_context_handler_callback(self, test_bot):
+        async def callback(_, context):
             self.received = (
                 type(context),
                 type(context.user_data),
@@ -870,7 +884,7 @@ def callback(_, context):
 
         application = (
             ApplicationBuilder()
-            .token(bot.token)
+            .bot(test_bot)
             .context_types(
                 ContextTypes(
                     context=CustomContext, bot_data=int, user_data=float, chat_data=complex
@@ -1034,12 +1048,13 @@ async def error_handler(update, context):
         ), "incorrect stacklevel!"
 
     @pytest.mark.parametrize(["block", "expected_output"], [(False, 0), (True, 5)])
-    async def test_default_block_error_handler(self, bot, block, expected_output):
+    async def test_default_block_error_handler(self, bot_info, block, expected_output):
         async def error_handler(*args, **kwargs):
             await asyncio.sleep(0.1)
             self.count = 5
 
-        app = Application.builder().token(bot.token).defaults(Defaults(block=block)).build()
+        bot = make_bot(bot_info, defaults=Defaults(block=block))
+        app = Application.builder().bot(bot).build()
         async with app:
             app.add_handler(TypeHandler(object, self.callback_raise_error))
             app.add_error_handler(error_handler)
@@ -1050,8 +1065,9 @@ async def error_handler(*args, **kwargs):
             assert self.count == 5
 
     @pytest.mark.parametrize(["block", "expected_output"], [(False, 0), (True, 5)])
-    async def test_default_block_handler(self, bot, block, expected_output):
-        app = Application.builder().token(bot.token).defaults(Defaults(block=block)).build()
+    async def test_default_block_handler(self, bot_info, block, expected_output):
+        bot = make_bot(bot_info, defaults=Defaults(block=block))
+        app = Application.builder().bot(bot).build()
         async with app:
             app.add_handler(TypeHandler(object, self.callback_set_count(5, sleep=0.1)))
             await app.process_update(1)
@@ -1296,10 +1312,10 @@ async def callback(u, c):
             await app.stop()
 
     @pytest.mark.parametrize("concurrent_updates", (15, 50, 100))
-    async def test_concurrent_updates(self, bot, concurrent_updates):
+    async def test_concurrent_updates(self, test_bot, concurrent_updates):
         # We don't test with `True` since the large number of parallel coroutines quickly leads
         # to test instabilities
-        app = Application.builder().token(bot.token).concurrent_updates(concurrent_updates).build()
+        app = Application.builder().bot(test_bot).concurrent_updates(concurrent_updates).build()
         events = {i: asyncio.Event() for i in range(app.concurrent_updates + 10)}
         queue = asyncio.Queue()
         for event in events.values():
@@ -1330,8 +1346,8 @@ async def callback(u, c):
 
             await app.stop()
 
-    async def test_concurrent_updates_done_on_shutdown(self, bot):
-        app = Application.builder().token(bot.token).concurrent_updates(True).build()
+    async def test_concurrent_updates_done_on_shutdown(self, test_bot):
+        app = Application.builder().bot(test_bot).concurrent_updates(True).build()
         event = asyncio.Event()
 
         async def callback(update, context):
@@ -1415,7 +1431,7 @@ def thread_target():
         platform.system() == "Windows",
         reason="Can't send signals without stopping whole process on windows",
     )
-    def test_run_polling_post_init(self, bot, monkeypatch):
+    def test_run_polling_post_init(self, test_bot, monkeypatch):
         events = []
 
         async def get_updates(*args, **kwargs):
@@ -1436,7 +1452,7 @@ def thread_target():
         async def post_init(app: Application) -> None:
             events.append("post_init")
 
-        app = Application.builder().token(bot.token).post_init(post_init).build()
+        app = Application.builder().bot(test_bot).post_init(post_init).build()
         app.bot._unfreeze()
         monkeypatch.setattr(app.bot, "get_updates", get_updates)
         monkeypatch.setattr(
@@ -1458,7 +1474,7 @@ async def post_init(app: Application) -> None:
         platform.system() == "Windows",
         reason="Can't send signals without stopping whole process on windows",
     )
-    def test_run_polling_post_shutdown(self, bot, monkeypatch):
+    def test_run_polling_post_shutdown(self, test_bot, monkeypatch):
         events = []
 
         async def get_updates(*args, **kwargs):
@@ -1479,7 +1495,7 @@ def thread_target():
         async def post_shutdown(app: Application) -> None:
             events.append("post_shutdown")
 
-        app = Application.builder().token(bot.token).post_shutdown(post_shutdown).build()
+        app = Application.builder().bot(test_bot).post_shutdown(post_shutdown).build()
         app.bot._unfreeze()
         monkeypatch.setattr(app.bot, "get_updates", get_updates)
         monkeypatch.setattr(
@@ -1633,7 +1649,7 @@ def thread_target():
         platform.system() == "Windows",
         reason="Can't send signals without stopping whole process on windows",
     )
-    def test_run_webhook_post_init(self, bot, monkeypatch):
+    def test_run_webhook_post_init(self, test_bot, monkeypatch):
         events = []
 
         async def delete_webhook(*args, **kwargs):
@@ -1660,7 +1676,7 @@ def thread_target():
         async def post_init(app: Application) -> None:
             events.append("post_init")
 
-        app = Application.builder().token(bot.token).post_init(post_init).build()
+        app = Application.builder().bot(test_bot).post_init(post_init).build()
         app.bot._unfreeze()
         monkeypatch.setattr(app.bot, "set_webhook", set_webhook)
         monkeypatch.setattr(app.bot, "delete_webhook", delete_webhook)
@@ -1693,7 +1709,7 @@ async def post_init(app: Application) -> None:
         platform.system() == "Windows",
         reason="Can't send signals without stopping whole process on windows",
     )
-    def test_run_webhook_post_shutdown(self, bot, monkeypatch):
+    def test_run_webhook_post_shutdown(self, test_bot, monkeypatch):
         events = []
 
         async def delete_webhook(*args, **kwargs):
@@ -1720,7 +1736,7 @@ def thread_target():
         async def post_shutdown(app: Application) -> None:
             events.append("post_shutdown")
 
-        app = Application.builder().token(bot.token).post_shutdown(post_shutdown).build()
+        app = Application.builder().bot(test_bot).post_shutdown(post_shutdown).build()
         app.bot._unfreeze()
         monkeypatch.setattr(app.bot, "set_webhook", set_webhook)
         monkeypatch.setattr(app.bot, "delete_webhook", delete_webhook)
@@ -1757,7 +1773,7 @@ async def post_shutdown(app: Application) -> None:
         platform.system() == "Windows",
         reason="Can't send signals without stopping whole process on windows",
     )
-    def test_run_webhook_parameters_passing(self, bot, monkeypatch):
+    def test_run_webhook_parameters_passing(self, test_bot, monkeypatch):
         # Check that we pass them correctly
 
         async def start_webhook(_, **kwargs):
@@ -1772,7 +1788,7 @@ async def stop(_, **kwargs):
 
         monkeypatch.setattr(Updater, "start_webhook", start_webhook)
         monkeypatch.setattr(Updater, "stop", stop)
-        app = ApplicationBuilder().token(bot.token).build()
+        app = ApplicationBuilder().bot(test_bot).build()
         app_signature = inspect.signature(app.run_webhook)
 
         for name, param in updater_signature.parameters.items():
@@ -1813,8 +1829,8 @@ def thread_target():
         assert set(self.received.keys()) == set(expected.keys())
         assert self.received == expected
 
-    def test_run_without_updater(self, bot):
-        app = ApplicationBuilder().token(bot.token).updater(None).build()
+    def test_run_without_updater(self, test_bot):
+        app = ApplicationBuilder().bot(test_bot).updater(None).build()
 
         with pytest.raises(RuntimeError, match="only available if the application has an Updater"):
             app.run_webhook()
@@ -1824,7 +1840,7 @@ def test_run_without_updater(self, bot):
 
     @pytest.mark.parametrize("method", ["start", "initialize"])
     @pytest.mark.filterwarnings("ignore::telegram.warnings.PTBUserWarning")
-    def test_run_error_in_application(self, bot, monkeypatch, method):
+    def test_run_error_in_application(self, test_bot, monkeypatch, method):
         shutdowns = []
 
         async def raise_method(*args, **kwargs):
@@ -1845,7 +1861,7 @@ def _after_shutdown(*args, **kwargs):
         monkeypatch.setattr(
             Updater, "shutdown", call_after(Updater.shutdown, after_shutdown("updater"))
         )
-        app = ApplicationBuilder().token(bot.token).build()
+        app = ApplicationBuilder().bot(test_bot).build()
         with pytest.raises(RuntimeError, match="Test Exception"):
             app.run_polling(close_loop=False)
 
@@ -1860,7 +1876,7 @@ def _after_shutdown(*args, **kwargs):
 
     @pytest.mark.parametrize("method", ["start_polling", "start_webhook"])
     @pytest.mark.filterwarnings("ignore::telegram.warnings.PTBUserWarning")
-    def test_run_error_in_updater(self, bot, monkeypatch, method):
+    def test_run_error_in_updater(self, test_bot, monkeypatch, method):
         shutdowns = []
 
         async def raise_method(*args, **kwargs):
@@ -1881,7 +1897,7 @@ def _after_shutdown(*args, **kwargs):
         monkeypatch.setattr(
             Updater, "shutdown", call_after(Updater.shutdown, after_shutdown("updater"))
         )
-        app = ApplicationBuilder().token(bot.token).build()
+        app = ApplicationBuilder().bot(test_bot).build()
         with pytest.raises(RuntimeError, match="Test Exception"):
             if "polling" in method:
                 app.run_polling(close_loop=False)
@@ -1897,12 +1913,12 @@ def _after_shutdown(*args, **kwargs):
         reason="Only really relevant on windows",
     )
     @pytest.mark.parametrize("method", ["start_polling", "start_webhook"])
-    def test_run_stop_signal_warning_windows(self, bot, method, recwarn, monkeypatch):
+    def test_run_stop_signal_warning_windows(self, test_bot, method, recwarn, monkeypatch):
         async def raise_method(*args, **kwargs):
             raise RuntimeError("Prevent Actually Running")
 
         monkeypatch.setattr(Application, "initialize", raise_method)
-        app = ApplicationBuilder().token(bot.token).build()
+        app = ApplicationBuilder().bot(test_bot).build()
 
         with pytest.raises(RuntimeError, match="Prevent Actually Running"):
             if "polling" in method:
@@ -1928,7 +1944,6 @@ async def raise_method(*args, **kwargs):
 
         assert len(recwarn) == 0
 
-    @pytest.mark.timeout(6)
     def test_signal_handlers(self, app, monkeypatch):
         # this test should make sure that signal handlers are set by default on Linux + Mac,
         # and not on Windows.
@@ -1942,11 +1957,10 @@ def signal_handler_test(*args, **kwargs):
         loop = asyncio.get_event_loop()
         monkeypatch.setattr(loop, "add_signal_handler", signal_handler_test)
 
-        async def abort_app():
-            await asyncio.sleep(2)
+        def abort_app():
             raise SystemExit
 
-        loop.create_task(abort_app())
+        loop.call_later(0.5, abort_app)
 
         app.run_polling(close_loop=False)
 
@@ -1956,7 +1970,7 @@ async def abort_app():
             assert received_signals == [signal.SIGINT, signal.SIGTERM, signal.SIGABRT]
 
         received_signals.clear()
-        loop.create_task(abort_app())
+        loop.call_later(0.5, abort_app)
         app.run_webhook(port=49152, webhook_url="example.com", close_loop=False)
 
         if platform.system() == "Windows":
diff --git a/tests/test_applicationbuilder.py b/tests/test_applicationbuilder.py
index 148a28a0464..b884102c9fe 100644
--- a/tests/test_applicationbuilder.py
+++ b/tests/test_applicationbuilder.py
@@ -17,7 +17,6 @@
 # You should have received a copy of the GNU Lesser Public License
 # along with this program.  If not, see [http://www.gnu.org/licenses/].
 import asyncio
-import os
 from dataclasses import dataclass
 
 import httpx
@@ -38,10 +37,7 @@
 from telegram.ext._applicationbuilder import _BOT_CHECKS
 from telegram.request import HTTPXRequest
 
-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))
+from .conftest import PRIVATE_KEY, TEST_WITH_OPT_DEPS
 
 
 @pytest.fixture(scope="function")
diff --git a/tests/test_audio.py b/tests/test_audio.py
index 9619e7ef5a1..187694b2245 100644
--- a/tests/test_audio.py
+++ b/tests/test_audio.py
@@ -16,6 +16,7 @@
 #
 # You should have received a copy of the GNU Lesser Public License
 # along with this program.  If not, see [http://www.gnu.org/licenses/].
+import asyncio
 import os
 from pathlib import Path
 
@@ -35,20 +36,17 @@
 
 @pytest.fixture(scope="function")
 def audio_file():
-    with open(data_file("telegram.mp3"), "rb") as f:
+    with data_file("telegram.mp3").open("rb") as f:
         yield f
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 async def audio(bot, chat_id):
-    with data_file("telegram.mp3").open("rb") as f:
-        thumb = data_file("thumb.jpg")
-        return (
-            await bot.send_audio(chat_id, audio=f, read_timeout=50, thumb=thumb.open("rb"))
-        ).audio
+    with data_file("telegram.mp3").open("rb") as f, data_file("thumb.jpg").open("rb") as thumb:
+        return (await bot.send_audio(chat_id, audio=f, read_timeout=50, thumb=thumb)).audio
 
 
-class TestAudio:
+class Space:
     caption = "Test *audio*"
     performer = "Leandro Toledo"
     title = "Teste"
@@ -65,6 +63,8 @@ class TestAudio:
     audio_file_id = "5a3128a4d2a04750b5b58397f3b5e812"
     audio_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
 
+
+class TestAudioNoReq:
     def test_slot_behaviour(self, audio, mro_slots):
         for attr in audio.__slots__:
             assert getattr(audio, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -79,58 +79,157 @@ def test_creation(self, audio):
         assert audio.file_unique_id != ""
 
     def test_expected_values(self, audio):
-        assert audio.duration == self.duration
+        assert audio.duration == Space.duration
         assert audio.performer is None
         assert audio.title is None
-        assert audio.mime_type == self.mime_type
-        assert audio.file_size == self.file_size
-        assert audio.thumb.file_size == self.thumb_file_size
-        assert audio.thumb.width == self.thumb_width
-        assert audio.thumb.height == self.thumb_height
+        assert audio.mime_type == Space.mime_type
+        assert audio.file_size == Space.file_size
+        assert audio.thumb.file_size == Space.thumb_file_size
+        assert audio.thumb.width == Space.thumb_width
+        assert audio.thumb.height == Space.thumb_height
+
+    async def test_send_audio_custom_filename(self, bot, chat_id, audio_file, monkeypatch):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            return list(request_data.multipart_data.values())[0][0] == "custom_filename"
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+
+        assert await bot.send_audio(chat_id, audio_file, filename="custom_filename")
+
+    async def test_send_with_audio(self, monkeypatch, bot, chat_id, audio):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            return request_data.json_parameters["audio"] == audio.file_id
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+        message = await bot.send_audio(audio=audio, chat_id=chat_id)
+        assert message
+
+    @pytest.mark.parametrize("local_mode", [True, False])
+    async def test_send_audio_local_files(self, monkeypatch, bot, chat_id, local_mode):
+        try:
+            bot._local_mode = local_mode
+            # For just test that the correct paths are passed as we have no local bot API set up
+            test_flag = False
+            file = data_file("telegram.jpg")
+            expected = file.as_uri()
+
+            async def make_assertion(_, data, *args, **kwargs):
+                nonlocal test_flag
+                if local_mode:
+                    test_flag = data.get("audio") == expected and data.get("thumb") == expected
+                else:
+                    test_flag = isinstance(data.get("audio"), InputFile) and isinstance(
+                        data.get("thumb"), InputFile
+                    )
+
+            monkeypatch.setattr(bot, "_post", make_assertion)
+            await bot.send_audio(chat_id, file, thumb=file)
+            assert test_flag
+            monkeypatch.delattr(bot, "_post")
+        finally:
+            bot._local_mode = False
+
+    def test_de_json(self, bot, audio):
+        json_dict = {
+            "file_id": Space.audio_file_id,
+            "file_unique_id": Space.audio_file_unique_id,
+            "duration": Space.duration,
+            "performer": Space.performer,
+            "title": Space.title,
+            "file_name": Space.file_name,
+            "mime_type": Space.mime_type,
+            "file_size": Space.file_size,
+            "thumb": audio.thumb.to_dict(),
+        }
+        json_audio = Audio.de_json(json_dict, bot)
+        assert json_audio.api_kwargs == {}
+
+        assert json_audio.file_id == Space.audio_file_id
+        assert json_audio.file_unique_id == Space.audio_file_unique_id
+        assert json_audio.duration == Space.duration
+        assert json_audio.performer == Space.performer
+        assert json_audio.title == Space.title
+        assert json_audio.file_name == Space.file_name
+        assert json_audio.mime_type == Space.mime_type
+        assert json_audio.file_size == Space.file_size
+        assert json_audio.thumb == audio.thumb
+
+    def test_to_dict(self, audio):
+        audio_dict = audio.to_dict()
+
+        assert isinstance(audio_dict, dict)
+        assert audio_dict["file_id"] == audio.file_id
+        assert audio_dict["file_unique_id"] == audio.file_unique_id
+        assert audio_dict["duration"] == audio.duration
+        assert audio_dict["mime_type"] == audio.mime_type
+        assert audio_dict["file_size"] == audio.file_size
+        assert audio_dict["file_name"] == audio.file_name
+
+    async def test_get_file_instance_method(self, monkeypatch, audio):
+        async def make_assertion(*_, **kwargs):
+            return kwargs["file_id"] == audio.file_id
+
+        assert check_shortcut_signature(Audio.get_file, Bot.get_file, ["file_id"], [])
+        assert await check_shortcut_call(audio.get_file, audio.get_bot(), "get_file")
+        assert await check_defaults_handling(audio.get_file, audio.get_bot())
+
+        monkeypatch.setattr(audio._bot, "get_file", make_assertion)
+        assert await audio.get_file()
+
+    def test_equality(self, audio):
+        a = Audio(audio.file_id, audio.file_unique_id, audio.duration)
+        b = Audio("", audio.file_unique_id, audio.duration)
+        c = Audio(audio.file_id, audio.file_unique_id, 0)
+        d = Audio("", "", audio.duration)
+        e = Voice(audio.file_id, audio.file_unique_id, audio.duration)
+
+        assert a == b
+        assert hash(a) == hash(b)
+        assert a is not b
+
+        assert a == c
+        assert hash(a) == hash(c)
+
+        assert a != d
+        assert hash(a) != hash(d)
+
+        assert a != e
+        assert hash(a) != hash(e)
 
-    @pytest.mark.flaky(3, 1)
+
+class TestAudioReq:
     async def test_send_all_args(self, bot, chat_id, audio_file, thumb_file):
         message = await bot.send_audio(
             chat_id,
             audio=audio_file,
-            caption=self.caption,
-            duration=self.duration,
-            performer=self.performer,
-            title=self.title,
+            caption=Space.caption,
+            duration=Space.duration,
+            performer=Space.performer,
+            title=Space.title,
             disable_notification=False,
             protect_content=True,
             parse_mode="Markdown",
             thumb=thumb_file,
         )
 
-        assert message.caption == self.caption.replace("*", "")
+        assert message.caption == Space.caption.replace("*", "")
 
         assert isinstance(message.audio, Audio)
         assert isinstance(message.audio.file_id, str)
         assert isinstance(message.audio.file_unique_id, str)
         assert message.audio.file_unique_id is not None
         assert message.audio.file_id is not None
-        assert message.audio.duration == self.duration
-        assert message.audio.performer == self.performer
-        assert message.audio.title == self.title
-        assert message.audio.file_name == self.file_name
-        assert message.audio.mime_type == self.mime_type
-        assert message.audio.file_size == self.file_size
-        assert message.audio.thumb.file_size == self.thumb_file_size
-        assert message.audio.thumb.width == self.thumb_width
-        assert message.audio.thumb.height == self.thumb_height
+        assert message.audio.duration == Space.duration
+        assert message.audio.performer == Space.performer
+        assert message.audio.title == Space.title
+        assert message.audio.file_name == Space.file_name
+        assert message.audio.mime_type == Space.mime_type
+        assert message.audio.file_size == Space.file_size
+        assert message.audio.thumb.file_size == Space.thumb_file_size
+        assert message.audio.thumb.width == Space.thumb_width
+        assert message.audio.thumb.height == Space.thumb_height
         assert message.has_protected_content
 
-    @pytest.mark.flaky(3, 1)
-    async def test_send_audio_custom_filename(self, bot, chat_id, audio_file, monkeypatch):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            return list(request_data.multipart_data.values())[0][0] == "custom_filename"
-
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-
-        assert await bot.send_audio(chat_id, audio_file, filename="custom_filename")
-
-    @pytest.mark.flaky(3, 1)
     async def test_get_and_download(self, bot, audio):
         path = Path("telegram.mp3")
         if path.is_file():
@@ -138,7 +237,7 @@ async def test_get_and_download(self, bot, audio):
 
         new_file = await bot.get_file(audio.file_id)
 
-        assert new_file.file_size == self.file_size
+        assert new_file.file_size == Space.file_size
         assert new_file.file_id == audio.file_id
         assert new_file.file_unique_id == audio.file_unique_id
         assert str(new_file.file_path).startswith("https://")
@@ -147,13 +246,12 @@ async def test_get_and_download(self, bot, audio):
 
         assert path.is_file()
 
-    @pytest.mark.flaky(3, 1)
     async def test_send_mp3_url_file(self, bot, chat_id, audio):
         message = await bot.send_audio(
-            chat_id=chat_id, audio=self.audio_file_url, caption=self.caption
+            chat_id=chat_id, audio=Space.audio_file_url, caption=Space.caption
         )
 
-        assert message.caption == self.caption
+        assert message.caption == Space.caption
 
         assert isinstance(message.audio, Audio)
         assert isinstance(message.audio.file_id, str)
@@ -164,21 +262,11 @@ async def test_send_mp3_url_file(self, bot, chat_id, audio):
         assert message.audio.mime_type == audio.mime_type
         assert message.audio.file_size == audio.file_size
 
-    @pytest.mark.flaky(3, 1)
     async def test_resend(self, bot, chat_id, audio):
         message = await bot.send_audio(chat_id=chat_id, audio=audio.file_id)
 
         assert message.audio == audio
 
-    async def test_send_with_audio(self, monkeypatch, bot, chat_id, audio):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            return request_data.json_parameters["audio"] == audio.file_id
-
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-        message = await bot.send_audio(audio=audio, chat_id=chat_id)
-        assert message
-
-    @pytest.mark.flaky(3, 1)
     async def test_send_audio_caption_entities(self, bot, chat_id, audio):
         test_string = "Italic Bold Code"
         entities = [
@@ -193,7 +281,6 @@ async def test_send_audio_caption_entities(self, bot, chat_id, audio):
         assert message.caption == test_string
         assert message.caption_entities == tuple(entities)
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_send_audio_default_parse_mode_1(self, default_bot, chat_id, audio_file):
         test_string = "Italic Bold Code"
@@ -203,7 +290,6 @@ async def test_send_audio_default_parse_mode_1(self, default_bot, chat_id, audio
         assert message.caption_markdown == test_markdown_string
         assert message.caption == test_string
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_send_audio_default_parse_mode_2(self, default_bot, chat_id, audio_file):
         test_markdown_string = "_Italic_ *Bold* `Code`"
@@ -214,7 +300,6 @@ async def test_send_audio_default_parse_mode_2(self, default_bot, chat_id, audio
         assert message.caption == test_markdown_string
         assert message.caption_markdown == escape_markdown(test_markdown_string)
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_send_audio_default_parse_mode_3(self, default_bot, chat_id, audio_file):
         test_markdown_string = "_Italic_ *Bold* `Code`"
@@ -225,83 +310,22 @@ async def test_send_audio_default_parse_mode_3(self, default_bot, chat_id, audio
         assert message.caption == test_markdown_string
         assert message.caption_markdown == escape_markdown(test_markdown_string)
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
     async def test_send_audio_default_protect_content(self, default_bot, chat_id, audio):
-        protected_audio = await default_bot.send_audio(chat_id, audio)
-        assert protected_audio.has_protected_content
-        unprotected = await default_bot.send_audio(chat_id, audio, protect_content=False)
+        tasks = asyncio.gather(
+            default_bot.send_audio(chat_id, audio),
+            default_bot.send_audio(chat_id, audio, protect_content=False),
+        )
+        protected, unprotected = await tasks
+        assert protected.has_protected_content
         assert not unprotected.has_protected_content
 
-    @pytest.mark.parametrize("local_mode", [True, False])
-    async def test_send_audio_local_files(self, monkeypatch, bot, chat_id, local_mode):
-        try:
-            bot._local_mode = local_mode
-            # For just test that the correct paths are passed as we have no local bot API set up
-            test_flag = False
-            file = data_file("telegram.jpg")
-            expected = file.as_uri()
-
-            async def make_assertion(_, data, *args, **kwargs):
-                nonlocal test_flag
-                if local_mode:
-                    test_flag = data.get("audio") == expected and data.get("thumb") == expected
-                else:
-                    test_flag = isinstance(data.get("audio"), InputFile) and isinstance(
-                        data.get("thumb"), InputFile
-                    )
-
-            monkeypatch.setattr(bot, "_post", make_assertion)
-            await bot.send_audio(chat_id, file, thumb=file)
-            assert test_flag
-            monkeypatch.delattr(bot, "_post")
-        finally:
-            bot._local_mode = False
-
-    def test_de_json(self, bot, audio):
-        json_dict = {
-            "file_id": self.audio_file_id,
-            "file_unique_id": self.audio_file_unique_id,
-            "duration": self.duration,
-            "performer": self.performer,
-            "title": self.title,
-            "file_name": self.file_name,
-            "mime_type": self.mime_type,
-            "file_size": self.file_size,
-            "thumb": audio.thumb.to_dict(),
-        }
-        json_audio = Audio.de_json(json_dict, bot)
-        assert json_audio.api_kwargs == {}
-
-        assert json_audio.file_id == self.audio_file_id
-        assert json_audio.file_unique_id == self.audio_file_unique_id
-        assert json_audio.duration == self.duration
-        assert json_audio.performer == self.performer
-        assert json_audio.title == self.title
-        assert json_audio.file_name == self.file_name
-        assert json_audio.mime_type == self.mime_type
-        assert json_audio.file_size == self.file_size
-        assert json_audio.thumb == audio.thumb
-
-    def test_to_dict(self, audio):
-        audio_dict = audio.to_dict()
-
-        assert isinstance(audio_dict, dict)
-        assert audio_dict["file_id"] == audio.file_id
-        assert audio_dict["file_unique_id"] == audio.file_unique_id
-        assert audio_dict["duration"] == audio.duration
-        assert audio_dict["mime_type"] == audio.mime_type
-        assert audio_dict["file_size"] == audio.file_size
-        assert audio_dict["file_name"] == audio.file_name
-
-    @pytest.mark.flaky(3, 1)
     async def test_error_send_empty_file(self, bot, chat_id):
         audio_file = open(os.devnull, "rb")
 
         with pytest.raises(TelegramError):
             await bot.send_audio(chat_id=chat_id, audio=audio_file)
 
-    @pytest.mark.flaky(3, 1)
     async def test_error_send_empty_file_id(self, bot, chat_id):
         with pytest.raises(TelegramError):
             await bot.send_audio(chat_id=chat_id, audio="")
@@ -309,34 +333,3 @@ async def test_error_send_empty_file_id(self, bot, chat_id):
     async def test_error_send_without_required_args(self, bot, chat_id):
         with pytest.raises(TypeError):
             await bot.send_audio(chat_id=chat_id)
-
-    async def test_get_file_instance_method(self, monkeypatch, audio):
-        async def make_assertion(*_, **kwargs):
-            return kwargs["file_id"] == audio.file_id
-
-        assert check_shortcut_signature(Audio.get_file, Bot.get_file, ["file_id"], [])
-        assert await check_shortcut_call(audio.get_file, audio.get_bot(), "get_file")
-        assert await check_defaults_handling(audio.get_file, audio.get_bot())
-
-        monkeypatch.setattr(audio._bot, "get_file", make_assertion)
-        assert await audio.get_file()
-
-    def test_equality(self, audio):
-        a = Audio(audio.file_id, audio.file_unique_id, audio.duration)
-        b = Audio("", audio.file_unique_id, audio.duration)
-        c = Audio(audio.file_id, audio.file_unique_id, 0)
-        d = Audio("", "", audio.duration)
-        e = Voice(audio.file_id, audio.file_unique_id, audio.duration)
-
-        assert a == b
-        assert hash(a) == hash(b)
-        assert a is not b
-
-        assert a == c
-        assert hash(a) == hash(c)
-
-        assert a != d
-        assert hash(a) != hash(d)
-
-        assert a != e
-        assert hash(a) != hash(e)
diff --git a/tests/test_basepersistence.py b/tests/test_basepersistence.py
index 781c1583d1d..8885371d459 100644
--- a/tests/test_basepersistence.py
+++ b/tests/test_basepersistence.py
@@ -43,7 +43,7 @@
     filters,
 )
 from telegram.warnings import PTBUserWarning
-from tests.conftest import DictApplication, make_message_update
+from tests.conftest import DictApplication, make_bot, make_message_update
 
 
 class HandlerStates(int, enum.Enum):
@@ -227,7 +227,11 @@ class PappInput(NamedTuple):
 
 
 def build_papp(
-    token: str, store_data: dict = None, update_interval: float = None, fill_data: bool = False
+    bot_info: dict = None,
+    token: str = None,
+    store_data: dict = None,
+    update_interval: float = None,
+    fill_data: bool = False,
 ) -> Application:
     store_data = PersistenceInput(**(store_data or {}))
     if update_interval is not None:
@@ -237,12 +241,15 @@ def build_papp(
     else:
         persistence = TrackingPersistence(store_data=store_data, fill_data=fill_data)
 
+    if bot_info is not None:
+        bot = make_bot(bot_info, arbitrary_callback_data=True)
+    else:
+        bot = make_bot(token=token, arbitrary_callback_data=True)
     return (
         ApplicationBuilder()
-        .token(token)
+        .bot(bot)
         .persistence(persistence)
         .application_class(DictApplication)
-        .arbitrary_callback_data(True)
         .build()
     )
 
@@ -252,7 +259,7 @@ def build_conversation_handler(name: str, persistent: bool = True) -> BaseHandle
 
 
 @pytest.fixture(scope="function")
-def papp(request, bot) -> Application:
+def papp(request, bot_info) -> Application:
     papp_input = request.param
     store_data = {}
     if papp_input.bot_data is not None:
@@ -265,7 +272,7 @@ def papp(request, bot) -> Application:
         store_data["callback_data"] = papp_input.callback_data
 
     app = build_papp(
-        bot.token,
+        bot_info=bot_info,
         store_data=store_data,
         update_interval=papp_input.update_interval,
         fill_data=papp_input.fill_data,
@@ -998,7 +1005,7 @@ async def test_migrate_chat_data(self, papp: Application):
             assert papp.persistence.dropped_chat_ids == {1: 1}
             assert papp.persistence.updated_chat_ids == {2: 1}
 
-    async def test_errors_while_persisting(self, bot, caplog):
+    async def test_errors_while_persisting(self, bot_info, caplog):
         class ErrorPersistence(TrackingPersistence):
             def raise_error(self):
                 raise Exception("PersistenceError")
@@ -1032,8 +1039,7 @@ async def error(update, context):
 
         app = (
             ApplicationBuilder()
-            .token(bot.token)
-            .arbitrary_callback_data(True)
+            .bot(make_bot(bot_info, arbitrary_callback_data=True))
             .persistence(ErrorPersistence())
             .build()
         )
diff --git a/tests/test_bot.py b/tests/test_bot.py
index f8489bbd03c..30cdb64b32f 100644
--- a/tests/test_bot.py
+++ b/tests/test_bot.py
@@ -23,7 +23,6 @@
 import logging
 import pickle
 import socket
-import sys
 import time
 from collections import defaultdict
 
@@ -76,7 +75,15 @@
 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, data_file, expect_bad_request, make_bot
+from tests.conftest import (
+    GITHUB_ACTION,
+    TEST_WITH_OPT_DEPS,
+    DictBot,
+    DictExtBot,
+    data_file,
+    expect_bad_request,
+    make_bot,
+)
 
 
 def to_camel_case(snake_str):
@@ -103,13 +110,13 @@ async def message(bot, chat_id):
     return out
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 async def media_message(bot, chat_id):
     with data_file("telegram.ogg").open("rb") as f:
         return await bot.send_voice(chat_id, voice=f, caption="my caption", read_timeout=10)
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def chat_permissions():
     return ChatPermissions(can_send_messages=False, can_change_info=False, can_invite_users=False)
 
@@ -125,7 +132,7 @@ def inline_results_callback(page=None):
     return None
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_results():
     return inline_results_callback()
 
@@ -139,7 +146,7 @@ def inline_results():
 )
 
 
-def bot_methods(ext_bot=True):
+def bot_methods(ext_bot=True, include_camel_case=False):
     arg_values = []
     ids = []
     non_api_methods = [
@@ -159,6 +166,8 @@ def bot_methods(ext_bot=True):
         for name, attribute in inspect.getmembers(cls, predicate=inspect.isfunction):
             if name.startswith("_") or name in non_api_methods:
                 continue
+            if not include_camel_case and any(x.isupper() for x in name):
+                continue
             arg_values.append((cls, name, attribute))
             ids.append(f"{cls.__name__}.{name}")
 
@@ -188,30 +197,7 @@ def __init__(
         self.disable_web_page_preview = disable_web_page_preview
 
 
-class TestBot:
-    """
-    Most are executed on tg.ext.ExtBot, as that class only extends the functionality of tg.bot
-
-    Behavior for init of ExtBot with missing optional dependency cachetools (for CallbackDataCache)
-    is tested in `test_callbackdatacache`
-    """
-
-    @staticmethod
-    def localize(dt, tzinfo):
-        try:
-            return tzinfo.localize(dt)
-        except AttributeError:
-            # We get here if tzinfo is not a pytz timezone but a datetime.timezone class
-            # This test class should never be run in if pytz is not installed, we intentionally
-            # fail if this branch is ever reached.
-            sys.exit(1)
-
-    test_flag = None
-
-    @pytest.fixture(scope="function", autouse=True)
-    def reset(self):
-        self.test_flag = None
-
+class TestBotNoReq:
     @pytest.mark.parametrize("bot_class", [Bot, ExtBot])
     def test_slot_behaviour(self, bot_class, bot, mro_slots):
         inst = bot_class(bot.token)
@@ -219,25 +205,29 @@ def test_slot_behaviour(self, bot_class, bot, mro_slots):
             assert getattr(inst, attr, "err") != "err", f"got extra slot '{attr}'"
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
-    async def test_initialize_and_shutdown(self, bot, monkeypatch):
+    async def test_initialize_and_shutdown(self, bot: DictExtBot, monkeypatch):
+        test_flag = []
+
         async def initialize(*args, **kwargs):
-            self.test_flag = ["initialize"]
+            nonlocal test_flag
+            test_flag = ["initialize"]
 
         async def stop(*args, **kwargs):
-            self.test_flag.append("stop")
+            nonlocal test_flag
+            test_flag.append("stop")
 
-        temp_bot = Bot(token=bot.token)
+        temp_bot = DictBot(token=bot.token)
         orig_stop = temp_bot.request.shutdown
 
         try:
             monkeypatch.setattr(temp_bot.request, "initialize", initialize)
             monkeypatch.setattr(temp_bot.request, "shutdown", stop)
             await temp_bot.initialize()
-            assert self.test_flag == ["initialize"]
+            assert test_flag == ["initialize"]
             assert temp_bot.bot == bot.bot
 
             await temp_bot.shutdown()
-            assert self.test_flag == ["initialize", "stop"]
+            assert test_flag == ["initialize", "stop"]
         finally:
             await orig_stop()
 
@@ -253,7 +243,7 @@ async def shutdown(*args, **kwargs):
         monkeypatch.setattr(HTTPXRequest, "initialize", initialize)
         monkeypatch.setattr(HTTPXRequest, "shutdown", shutdown)
 
-        test_bot = Bot(bot.token)
+        test_bot = DictBot(bot.token)
         await test_bot.initialize()
         await test_bot.initialize()
         await test_bot.initialize()
@@ -265,20 +255,16 @@ async def shutdown(*args, **kwargs):
         assert self.received["init"] == 2
         assert self.received["shutdown"] == 2
 
-    async def test_multiple_init_cycles(self, bot):
-        # nothing really to assert - this should just not fail
-        test_bot = Bot(bot.token)
-        async with test_bot:
-            await test_bot.get_me()
-        async with test_bot:
-            await test_bot.get_me()
-
     async def test_context_manager(self, monkeypatch, bot):
+        test_flag = []
+
         async def initialize():
-            self.test_flag = ["initialize"]
+            nonlocal test_flag
+            test_flag = ["initialize"]
 
         async def shutdown(*args):
-            self.test_flag.append("stop")
+            nonlocal test_flag
+            test_flag.append("stop")
 
         monkeypatch.setattr(bot, "initialize", initialize)
         monkeypatch.setattr(bot, "shutdown", shutdown)
@@ -286,14 +272,17 @@ async def shutdown(*args):
         async with bot:
             pass
 
-        assert self.test_flag == ["initialize", "stop"]
+        assert test_flag == ["initialize", "stop"]
 
     async def test_context_manager_exception_on_init(self, monkeypatch, bot):
+        test_flag = []
+
         async def initialize():
             raise RuntimeError("initialize")
 
         async def shutdown():
-            self.test_flag = "stop"
+            nonlocal test_flag
+            test_flag = "stop"
 
         monkeypatch.setattr(bot, "initialize", initialize)
         monkeypatch.setattr(bot, "shutdown", shutdown)
@@ -302,12 +291,12 @@ async def shutdown():
             async with bot:
                 pass
 
-        assert self.test_flag == "stop"
+        assert test_flag == "stop"
 
-    async def test_log_decorator(self, bot, caplog):
+    async def test_log_decorator(self, bot: DictExtBot, caplog):
         # Second argument makes sure that we ignore logs from e.g. httpx
         with caplog.at_level(logging.DEBUG, logger="telegram"):
-            await bot.get_me()
+            await super(bot.__class__, bot).get_me()  # call original get_me instead of overriden
             # Only for stabilizing this test-
             if len(caplog.records) == 4:
                 for idx, record in enumerate(caplog.records):
@@ -324,8 +313,8 @@ async def test_log_decorator(self, bot, caplog):
         "acd_in,maxsize",
         [(True, 1024), (False, 1024), (0, 0), (None, None)],
     )
-    async def test_callback_data_maxsize(self, bot, acd_in, maxsize):
-        async with ExtBot(bot.token, arbitrary_callback_data=acd_in) as acd_bot:
+    async def test_callback_data_maxsize(self, bot_info, acd_in, maxsize):
+        async with make_bot(bot_info, arbitrary_callback_data=acd_in) as acd_bot:
             if acd_in is not False:
                 assert acd_bot.callback_data_cache.maxsize == maxsize
             else:
@@ -335,11 +324,6 @@ async def test_no_token_passed(self):
         with pytest.raises(InvalidToken, match="You must pass the token"):
             Bot("")
 
-    async def test_invalid_token_server_response(self):
-        with pytest.raises(InvalidToken, match="The token `12` was rejected by the server."):
-            async with make_bot(token="12"):
-                pass
-
     async def test_unknown_kwargs(self, bot, monkeypatch):
         async def post(url, request_data: RequestData, *args, **kwargs):
             data = request_data.json_parameters
@@ -352,21 +336,6 @@ async def post(url, request_data: RequestData, *args, **kwargs):
             123, "text", api_kwargs={"unknown_kwarg_1": 7, "unknown_kwarg_2": 5}
         )
 
-    @pytest.mark.flaky(3, 1)
-    async def test_get_me_and_properties(self, bot: Bot):
-        get_me_bot = await bot.get_me()
-
-        assert isinstance(get_me_bot, User)
-        assert get_me_bot.id == bot.id
-        assert get_me_bot.username == bot.username
-        assert get_me_bot.first_name == bot.first_name
-        assert get_me_bot.last_name == bot.last_name
-        assert get_me_bot.name == bot.name
-        assert get_me_bot.can_join_groups == bot.can_join_groups
-        assert get_me_bot.can_read_all_group_messages == bot.can_read_all_group_messages
-        assert get_me_bot.supports_inline_queries == bot.supports_inline_queries
-        assert f"https://t.me/{get_me_bot.username}" == bot.link
-
     @pytest.mark.parametrize(
         "attribute",
         [
@@ -389,6 +358,25 @@ async def test_get_me_and_properties_not_initialized(self, bot: Bot, attribute):
         finally:
             await bot.shutdown()
 
+    async def test_get_me_and_properties(self, bot):
+        mocked = "mocked"
+        with bot._bot_user._unfrozen():
+            bot._bot_user.username = mocked  # set the attribute to a mocked value
+        assert bot.username == mocked  # To test we are using the mocked bot
+        # call the parent class get_me method instead of the overriden get_me method
+        get_me_bot = await super(bot.__class__, bot).get_me()
+
+        assert isinstance(get_me_bot, User)
+        assert get_me_bot.id == bot.id
+        assert get_me_bot.username == bot.username != mocked  # will be the real bot
+        assert get_me_bot.first_name == bot.first_name
+        assert get_me_bot.last_name == bot.last_name
+        assert get_me_bot.name == bot.name
+        assert get_me_bot.can_join_groups == bot.can_join_groups
+        assert get_me_bot.can_read_all_group_messages == bot.can_read_all_group_messages
+        assert get_me_bot.supports_inline_queries == bot.supports_inline_queries
+        assert f"https://t.me/{get_me_bot.username}" == bot.link
+
     async def test_equality(self):
         async with make_bot(token=FALLBACKS[0]["token"]) as a, make_bot(
             token=FALLBACKS[0]["token"]
@@ -408,7 +396,6 @@ async def test_equality(self):
             assert a != e
             assert hash(a) != hash(e)
 
-    @pytest.mark.flaky(3, 1)
     async def test_to_dict(self, bot):
         to_dict_bot = bot.to_dict()
 
@@ -425,7 +412,13 @@ def test_bot_pickling_error(self, bot):
 
     @bot_methods(ext_bot=False)
     async def test_defaults_handling(
-        self, bot_class, bot_method_name, bot_method, bot, raw_bot, monkeypatch
+        self,
+        bot_class,
+        bot_method_name: str,
+        bot_method,
+        bot: DictExtBot,
+        raw_bot: DictBot,
+        monkeypatch,
     ):
         """
         Here we check that the bot methods handle tg.ext.Defaults correctly. This has two parts:
@@ -495,1101 +488,1452 @@ def test_ext_bot_signature(self):
                     param.kind == ext_signature.parameters[param_name].kind
                 ), f"Wrong parameter kind for parameter {param_name} of method {name}"
 
-    @pytest.mark.flaky(3, 1)
-    async def test_forward_message(self, bot, chat_id, message):
-        forward_message = await bot.forward_message(
-            chat_id, from_chat_id=chat_id, message_id=message.message_id
-        )
-
-        assert forward_message.text == message.text
-        assert forward_message.forward_from.username == message.from_user.username
-        assert isinstance(forward_message.forward_date, dtm.datetime)
-
-    async def test_forward_protected_message(self, bot, message, chat_id):
-        to_forward_protected = await bot.send_message(
-            chat_id, "cant forward me", protect_content=True
-        )
-        assert to_forward_protected.has_protected_content
+    async def test_answer_web_app_query(self, bot, raw_bot, monkeypatch):
+        params = False
 
-        with pytest.raises(BadRequest, match="can't be forwarded"):
-            await to_forward_protected.forward(chat_id)
+        # For now just test that our internals pass the correct data
 
-        to_forward_unprotected = await bot.send_message(
-            chat_id, "forward me", protect_content=False
-        )
-        assert not to_forward_unprotected.has_protected_content
-        forwarded_but_now_protected = await to_forward_unprotected.forward(
-            chat_id, protect_content=True
-        )
-        assert forwarded_but_now_protected.has_protected_content
-        with pytest.raises(BadRequest, match="can't be forwarded"):
-            await forwarded_but_now_protected.forward(chat_id)
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            nonlocal params
+            params = request_data.parameters == {
+                "web_app_query_id": "12345",
+                "result": {
+                    "title": "title",
+                    "input_message_content": {
+                        "message_text": "text",
+                    },
+                    "type": InlineQueryResultType.ARTICLE,
+                    "id": "1",
+                },
+            }
+            web_app_msg = SentWebAppMessage("321").to_dict()
+            return web_app_msg
 
-    @pytest.mark.flaky(3, 1)
-    async def test_delete_message(self, bot, chat_id):
-        message = await bot.send_message(chat_id, text="will be deleted")
-        await asyncio.sleep(2)
+        # We test different result types more thoroughly for answer_inline_query, so we just
+        # use the one type here
+        result = InlineQueryResultArticle("1", "title", InputTextMessageContent("text"))
+        copied_result = copy.copy(result)
 
-        assert await bot.delete_message(chat_id=chat_id, message_id=message.message_id) is True
+        ext_bot = bot
+        for bot in (ext_bot, raw_bot):
+            # We need to test 1) below both the bot and raw_bot and setting this up with
+            # pytest.parametrize appears to be difficult ...
+            monkeypatch.setattr(bot.request, "post", make_assertion)
+            web_app_msg = await bot.answer_web_app_query("12345", result)
+            assert params, "something went wrong with passing arguments to the request"
+            assert isinstance(web_app_msg, SentWebAppMessage)
+            assert web_app_msg.inline_message_id == "321"
 
-    @pytest.mark.flaky(3, 1)
-    async def test_delete_message_old_message(self, bot, chat_id):
-        with pytest.raises(BadRequest):
-            # Considering that the first message is old enough
-            await bot.delete_message(chat_id=chat_id, message_id=1)
+            # 1)
+            # make sure that the results were not edited in-place
+            assert result == copied_result
+            assert (
+                result.input_message_content.parse_mode
+                == copied_result.input_message_content.parse_mode
+            )
 
-    # send_photo, send_audio, send_document, send_sticker, send_video, send_voice, send_video_note,
-    # send_media_group and send_animation are tested in their respective test modules. No need to
-    # duplicate here.
+    @pytest.mark.parametrize(
+        "default_bot",
+        [{"parse_mode": "Markdown", "disable_web_page_preview": True}],
+        indirect=True,
+    )
+    @pytest.mark.parametrize(
+        "ilq_result,expected_params",
+        [
+            (
+                InlineQueryResultArticle("1", "title", InputTextMessageContent("text")),
+                {
+                    "web_app_query_id": "12345",
+                    "result": {
+                        "title": "title",
+                        "input_message_content": {
+                            "message_text": "text",
+                            "parse_mode": "Markdown",
+                            "disable_web_page_preview": True,
+                        },
+                        "type": InlineQueryResultType.ARTICLE,
+                        "id": "1",
+                    },
+                },
+            ),
+            (
+                InlineQueryResultArticle(
+                    "1",
+                    "title",
+                    InputTextMessageContent(
+                        "text", parse_mode="HTML", disable_web_page_preview=False
+                    ),
+                ),
+                {
+                    "web_app_query_id": "12345",
+                    "result": {
+                        "title": "title",
+                        "input_message_content": {
+                            "message_text": "text",
+                            "parse_mode": "HTML",
+                            "disable_web_page_preview": False,
+                        },
+                        "type": InlineQueryResultType.ARTICLE,
+                        "id": "1",
+                    },
+                },
+            ),
+            (
+                InlineQueryResultArticle(
+                    "1",
+                    "title",
+                    InputTextMessageContent(
+                        "text", parse_mode=None, disable_web_page_preview="False"
+                    ),
+                ),
+                {
+                    "web_app_query_id": "12345",
+                    "result": {
+                        "title": "title",
+                        "input_message_content": {
+                            "message_text": "text",
+                            "disable_web_page_preview": "False",
+                        },
+                        "type": InlineQueryResultType.ARTICLE,
+                        "id": "1",
+                    },
+                },
+            ),
+        ],
+    )
+    async def test_answer_web_app_query_defaults(
+        self, default_bot, ilq_result, expected_params, monkeypatch
+    ):
+        bot = default_bot
+        params = False
 
-    @pytest.mark.flaky(3, 1)
-    async def test_send_venue(self, bot, chat_id):
-        longitude = -46.788279
-        latitude = -23.691288
-        title = "title"
-        address = "address"
-        foursquare_id = "foursquare id"
-        foursquare_type = "foursquare type"
-        google_place_id = "google_place id"
-        google_place_type = "google_place type"
+        # For now just test that our internals pass the correct data
 
-        message = await bot.send_venue(
-            chat_id=chat_id,
-            title=title,
-            address=address,
-            latitude=latitude,
-            longitude=longitude,
-            foursquare_id=foursquare_id,
-            foursquare_type=foursquare_type,
-            protect_content=True,
-        )
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            nonlocal params
+            params = request_data.parameters == expected_params
+            web_app_msg = SentWebAppMessage("321").to_dict()
+            return web_app_msg
 
-        assert message.venue
-        assert message.venue.title == title
-        assert message.venue.address == address
-        assert message.venue.location.latitude == latitude
-        assert message.venue.location.longitude == longitude
-        assert message.venue.foursquare_id == foursquare_id
-        assert message.venue.foursquare_type == foursquare_type
-        assert message.venue.google_place_id is None
-        assert message.venue.google_place_type is None
-        assert message.has_protected_content
+        monkeypatch.setattr(bot.request, "post", make_assertion)
 
-        message = await bot.send_venue(
-            chat_id=chat_id,
-            title=title,
-            address=address,
-            latitude=latitude,
-            longitude=longitude,
-            google_place_id=google_place_id,
-            google_place_type=google_place_type,
-            protect_content=True,
-        )
+        # We test different result types more thoroughly for answer_inline_query, so we just
+        # use the one type here
+        copied_result = copy.copy(ilq_result)
 
-        assert message.venue
-        assert message.venue.title == title
-        assert message.venue.address == address
-        assert message.venue.location.latitude == latitude
-        assert message.venue.location.longitude == longitude
-        assert message.venue.google_place_id == google_place_id
-        assert message.venue.google_place_type == google_place_type
-        assert message.venue.foursquare_id is None
-        assert message.venue.foursquare_type is None
-        assert message.has_protected_content
+        web_app_msg = await bot.answer_web_app_query("12345", ilq_result)
+        assert params, "something went wrong with passing arguments to the request"
+        assert isinstance(web_app_msg, SentWebAppMessage)
+        assert web_app_msg.inline_message_id == "321"
 
-    @pytest.mark.flaky(3, 1)
-    async def test_send_contact(self, bot, chat_id):
-        phone_number = "+11234567890"
-        first_name = "Leandro"
-        last_name = "Toledo"
-        message = await bot.send_contact(
-            chat_id=chat_id,
-            phone_number=phone_number,
-            first_name=first_name,
-            last_name=last_name,
-            protect_content=True,
+        # make sure that the results were not edited in-place
+        assert ilq_result == copied_result
+        assert (
+            ilq_result.input_message_content.parse_mode
+            == copied_result.input_message_content.parse_mode
         )
 
-        assert message.contact
-        assert message.contact.phone_number == phone_number
-        assert message.contact.first_name == first_name
-        assert message.contact.last_name == last_name
-        assert message.has_protected_content
+    # TODO: Needs improvement. We need incoming inline query to test answer.
+    async def test_answer_inline_query(self, monkeypatch, bot, raw_bot):
+        # For now just test that our internals pass the correct data
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            return request_data.parameters == {
+                "cache_time": 300,
+                "results": [
+                    {
+                        "title": "first",
+                        "id": "11",
+                        "type": "article",
+                        "input_message_content": {"message_text": "first"},
+                    },
+                    {
+                        "title": "second",
+                        "id": "12",
+                        "type": "article",
+                        "input_message_content": {"message_text": "second"},
+                    },
+                    {
+                        "title": "test_result",
+                        "id": "123",
+                        "type": "document",
+                        "document_url": "https://raw.githubusercontent.com/python-telegram-bot"
+                        "/logos/master/logo/png/ptb-logo_240.png",
+                        "mime_type": "image/png",
+                        "caption": "ptb_logo",
+                        "input_message_content": {"message_text": "imc"},
+                    },
+                ],
+                "next_offset": "42",
+                "switch_pm_parameter": "start_pm",
+                "inline_query_id": 1234,
+                "is_personal": True,
+                "switch_pm_text": "switch pm",
+            }
 
-    # TODO: Add bot to group to test polls too
+        results = [
+            InlineQueryResultArticle("11", "first", InputTextMessageContent("first")),
+            InlineQueryResultArticle("12", "second", InputMessageContentDWPP("second")),
+            InlineQueryResultDocument(
+                id="123",
+                document_url="https://raw.githubusercontent.com/python-telegram-bot/logos/master/"
+                "logo/png/ptb-logo_240.png",
+                title="test_result",
+                mime_type="image/png",
+                caption="ptb_logo",
+                input_message_content=InputMessageContentDWPP("imc"),
+            ),
+        ]
 
-    @pytest.mark.flaky(3, 1)
-    @pytest.mark.parametrize(
-        "reply_markup",
-        [
-            None,
-            InlineKeyboardMarkup.from_button(
-                InlineKeyboardButton(text="text", callback_data="data")
+        copied_results = copy.copy(results)
+        ext_bot = bot
+        for bot in (ext_bot, raw_bot):
+            # We need to test 1) below both the bot and raw_bot and setting this up with
+            # pytest.parametrize appears to be difficult ...
+            monkeypatch.setattr(bot.request, "post", make_assertion)
+            assert await bot.answer_inline_query(
+                1234,
+                results=results,
+                cache_time=300,
+                is_personal=True,
+                next_offset="42",
+                switch_pm_text="switch pm",
+                switch_pm_parameter="start_pm",
+            )
+
+            # 1)
+            # make sure that the results were not edited in-place
+            assert results == copied_results
+            for idx, result in enumerate(results):
+                if hasattr(result, "parse_mode"):
+                    assert result.parse_mode == copied_results[idx].parse_mode
+                if hasattr(result, "input_message_content"):
+                    assert getattr(result.input_message_content, "parse_mode", None) == getattr(
+                        copied_results[idx].input_message_content, "parse_mode", None
+                    )
+                    assert getattr(
+                        result.input_message_content, "disable_web_page_preview", None
+                    ) == getattr(
+                        copied_results[idx].input_message_content, "disable_web_page_preview", None
+                    )
+
+            monkeypatch.delattr(bot.request, "post")
+
+    async def test_answer_inline_query_no_default_parse_mode(self, monkeypatch, bot):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            return request_data.parameters == {
+                "cache_time": 300,
+                "results": [
+                    {
+                        "title": "first",
+                        "id": "11",
+                        "type": "article",
+                        "input_message_content": {"message_text": "first"},
+                    },
+                    {
+                        "title": "second",
+                        "id": "12",
+                        "type": "article",
+                        "input_message_content": {"message_text": "second"},
+                    },
+                    {
+                        "title": "test_result",
+                        "id": "123",
+                        "type": "document",
+                        "document_url": "https://raw.githubusercontent.com/"
+                        "python-telegram-bot/logos/master/logo/png/"
+                        "ptb-logo_240.png",
+                        "mime_type": "image/png",
+                        "caption": "ptb_logo",
+                        "input_message_content": {"message_text": "imc"},
+                    },
+                ],
+                "next_offset": "42",
+                "switch_pm_parameter": "start_pm",
+                "inline_query_id": 1234,
+                "is_personal": True,
+                "switch_pm_text": "switch pm",
+            }
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+        results = [
+            InlineQueryResultArticle("11", "first", InputTextMessageContent("first")),
+            InlineQueryResultArticle("12", "second", InputMessageContentDWPP("second")),
+            InlineQueryResultDocument(
+                id="123",
+                document_url="https://raw.githubusercontent.com/python-telegram-bot/logos/master/"
+                "logo/png/ptb-logo_240.png",
+                title="test_result",
+                mime_type="image/png",
+                caption="ptb_logo",
+                input_message_content=InputMessageContentDWPP("imc"),
             ),
-            InlineKeyboardMarkup.from_button(
-                InlineKeyboardButton(text="text", callback_data="data")
-            ).to_dict(),
-        ],
-    )
-    async def test_send_and_stop_poll(self, bot, super_group_id, reply_markup):
-        question = "Is this a test?"
-        answers = ["Yes", "No", "Maybe"]
-        message = await bot.send_poll(
-            chat_id=super_group_id,
-            question=question,
-            options=answers,
-            is_anonymous=False,
-            allows_multiple_answers=True,
-            read_timeout=60,
-            protect_content=True,
+        ]
+
+        copied_results = copy.copy(results)
+        assert await bot.answer_inline_query(
+            1234,
+            results=results,
+            cache_time=300,
+            is_personal=True,
+            next_offset="42",
+            switch_pm_text="switch pm",
+            switch_pm_parameter="start_pm",
         )
+        # make sure that the results were not edited in-place
+        assert results == copied_results
+        for idx, result in enumerate(results):
+            if hasattr(result, "parse_mode"):
+                assert result.parse_mode == copied_results[idx].parse_mode
+            if hasattr(result, "input_message_content"):
+                assert getattr(result.input_message_content, "parse_mode", None) == getattr(
+                    copied_results[idx].input_message_content, "parse_mode", None
+                )
+                assert getattr(
+                    result.input_message_content, "disable_web_page_preview", None
+                ) == getattr(
+                    copied_results[idx].input_message_content, "disable_web_page_preview", None
+                )
 
-        assert message.poll
-        assert message.poll.question == question
-        assert message.poll.options[0].text == answers[0]
-        assert message.poll.options[1].text == answers[1]
-        assert message.poll.options[2].text == answers[2]
-        assert not message.poll.is_anonymous
-        assert message.poll.allows_multiple_answers
-        assert not message.poll.is_closed
-        assert message.poll.type == Poll.REGULAR
-        assert message.has_protected_content
+    @pytest.mark.parametrize(
+        "default_bot",
+        [{"parse_mode": "Markdown", "disable_web_page_preview": True}],
+        indirect=True,
+    )
+    async def test_answer_inline_query_default_parse_mode(self, monkeypatch, default_bot):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            return request_data.parameters == {
+                "cache_time": 300,
+                "results": [
+                    {
+                        "title": "first",
+                        "id": "11",
+                        "type": "article",
+                        "input_message_content": {
+                            "message_text": "first",
+                            "parse_mode": "Markdown",
+                            "disable_web_page_preview": True,
+                        },
+                    },
+                    {
+                        "title": "second",
+                        "id": "12",
+                        "type": "article",
+                        "input_message_content": {
+                            "message_text": "second",
+                            "disable_web_page_preview": True,
+                        },
+                    },
+                    {
+                        "title": "test_result",
+                        "id": "123",
+                        "type": "document",
+                        "document_url": "https://raw.githubusercontent.com/"
+                        "python-telegram-bot/logos/master/logo/png/"
+                        "ptb-logo_240.png",
+                        "mime_type": "image/png",
+                        "caption": "ptb_logo",
+                        "parse_mode": "Markdown",
+                        "input_message_content": {
+                            "message_text": "imc",
+                            "disable_web_page_preview": True,
+                            "parse_mode": "Markdown",
+                        },
+                    },
+                ],
+                "next_offset": "42",
+                "switch_pm_parameter": "start_pm",
+                "inline_query_id": 1234,
+                "is_personal": True,
+                "switch_pm_text": "switch pm",
+            }
+
+        monkeypatch.setattr(default_bot.request, "post", make_assertion)
+        results = [
+            InlineQueryResultArticle("11", "first", InputTextMessageContent("first")),
+            InlineQueryResultArticle("12", "second", InputMessageContentDWPP("second")),
+            InlineQueryResultDocument(
+                id="123",
+                document_url="https://raw.githubusercontent.com/python-telegram-bot/logos/master/"
+                "logo/png/ptb-logo_240.png",
+                title="test_result",
+                mime_type="image/png",
+                caption="ptb_logo",
+                input_message_content=InputTextMessageContent("imc"),
+            ),
+        ]
+
+        copied_results = copy.copy(results)
+        assert await default_bot.answer_inline_query(
+            1234,
+            results=results,
+            cache_time=300,
+            is_personal=True,
+            next_offset="42",
+            switch_pm_text="switch pm",
+            switch_pm_parameter="start_pm",
+        )
+        # make sure that the results were not edited in-place
+        assert results == copied_results
+        for idx, result in enumerate(results):
+            if hasattr(result, "parse_mode"):
+                assert result.parse_mode == copied_results[idx].parse_mode
+            if hasattr(result, "input_message_content"):
+                assert getattr(result.input_message_content, "parse_mode", None) == getattr(
+                    copied_results[idx].input_message_content, "parse_mode", None
+                )
+                assert getattr(
+                    result.input_message_content, "disable_web_page_preview", None
+                ) == getattr(
+                    copied_results[idx].input_message_content, "disable_web_page_preview", None
+                )
+
+    @pytest.mark.parametrize(
+        "current_offset,num_results,id_offset,expected_next_offset",
+        [
+            ("", InlineQueryLimit.RESULTS, 1, 1),
+            (1, InlineQueryLimit.RESULTS, 51, 2),
+            (5, 3, 251, ""),
+        ],
+    )
+    async def test_answer_inline_query_current_offset_1(
+        self,
+        monkeypatch,
+        bot,
+        inline_results,
+        current_offset,
+        num_results,
+        id_offset,
+        expected_next_offset,
+    ):
+        # For now just test that our internals pass the correct data
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            data = request_data.parameters
+            results = data["results"]
+            length_matches = len(results) == num_results
+            ids_match = all(int(res["id"]) == id_offset + i for i, res in enumerate(results))
+            next_offset_matches = data["next_offset"] == str(expected_next_offset)
+            return length_matches and ids_match and next_offset_matches
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+
+        assert await bot.answer_inline_query(
+            1234, results=inline_results, current_offset=current_offset
+        )
+
+    async def test_answer_inline_query_current_offset_2(self, monkeypatch, bot, inline_results):
+        # For now just test that our internals pass the correct data
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            data = request_data.parameters
+            results = data["results"]
+            length_matches = len(results) == InlineQueryLimit.RESULTS
+            ids_match = all(int(res["id"]) == 1 + i for i, res in enumerate(results))
+            next_offset_matches = data["next_offset"] == "1"
+            return length_matches and ids_match and next_offset_matches
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+
+        assert await bot.answer_inline_query(1234, results=inline_results, current_offset=0)
+
+        inline_results = inline_results[:30]
+
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            data = request_data.parameters
+            results = data["results"]
+            length_matches = len(results) == 30
+            ids_match = all(int(res["id"]) == 1 + i for i, res in enumerate(results))
+            next_offset_matches = data["next_offset"] == ""
+            return length_matches and ids_match and next_offset_matches
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+
+        assert await bot.answer_inline_query(1234, results=inline_results, current_offset=0)
+
+    async def test_answer_inline_query_current_offset_callback(self, monkeypatch, bot, caplog):
+        # For now just test that our internals pass the correct data
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            data = request_data.parameters
+            results = data["results"]
+            length = len(results) == 5
+            ids = all(int(res["id"]) == 6 + i for i, res in enumerate(results))
+            next_offset = data["next_offset"] == "2"
+            return length and ids and next_offset
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+
+        assert await bot.answer_inline_query(
+            1234, results=inline_results_callback, current_offset=1
+        )
+
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            data = request_data.parameters
+            results = data["results"]
+            length = results == []
+            next_offset = data["next_offset"] == ""
+            return length and next_offset
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+
+        assert await bot.answer_inline_query(
+            1234, results=inline_results_callback, current_offset=6
+        )
+
+    # get_file is tested multiple times in the test_*media* modules.
+    # Here we only test the behaviour for bot apis in local mode
+    async def test_get_file_local_mode(self, bot, monkeypatch):
+        path = str(data_file("game.gif"))
+
+        async def _post(*args, **kwargs):
+            return {
+                "file_id": None,
+                "file_unique_id": None,
+                "file_size": None,
+                "file_path": path,
+            }
+
+        monkeypatch.setattr(bot, "_post", _post)
+
+        resulting_path = (await bot.get_file("file_id")).file_path
+        assert bot.token not in resulting_path
+        assert resulting_path == path
+        monkeypatch.delattr(bot, "_post")
+
+    # TODO: Needs improvement. No feasible way to test until bots can add members.
+    async def test_ban_chat_member(self, monkeypatch, bot):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            data = request_data.json_parameters
+            chat_id = data["chat_id"] == "2"
+            user_id = data["user_id"] == "32"
+            until_date = data.get("until_date", "1577887200") == "1577887200"
+            revoke_msgs = data.get("revoke_messages", "true") == "true"
+            return chat_id and user_id and until_date and revoke_msgs
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+        until = from_timestamp(1577887200)
+
+        assert await bot.ban_chat_member(2, 32)
+        assert await bot.ban_chat_member(2, 32, until_date=until)
+        assert await bot.ban_chat_member(2, 32, until_date=1577887200)
+        assert await bot.ban_chat_member(2, 32, revoke_messages=True)
+        monkeypatch.delattr(bot.request, "post")
+
+    async def test_ban_chat_member_default_tz(self, monkeypatch, tz_bot):
+        until = dtm.datetime(2020, 1, 11, 16, 13)
+        until_timestamp = to_timestamp(until, tzinfo=tz_bot.defaults.tzinfo)
+
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            data = request_data.parameters
+            chat_id = data["chat_id"] == 2
+            user_id = data["user_id"] == 32
+            until_date = data.get("until_date", until_timestamp) == until_timestamp
+            return chat_id and user_id and until_date
+
+        monkeypatch.setattr(tz_bot.request, "post", make_assertion)
+
+        assert await tz_bot.ban_chat_member(2, 32)
+        assert await tz_bot.ban_chat_member(2, 32, until_date=until)
+        assert await tz_bot.ban_chat_member(2, 32, until_date=until_timestamp)
+
+    async def test_ban_chat_sender_chat(self, monkeypatch, bot):
+        # For now, we just test that we pass the correct data to TG
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            data = request_data.parameters
+            chat_id = data["chat_id"] == 2
+            sender_chat_id = data["sender_chat_id"] == 32
+            return chat_id and sender_chat_id
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+        assert await bot.ban_chat_sender_chat(2, 32)
+        monkeypatch.delattr(bot.request, "post")
+
+    # TODO: Needs improvement.
+    @pytest.mark.parametrize("only_if_banned", [True, False, None])
+    async def test_unban_chat_member(self, monkeypatch, bot, only_if_banned):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            data = request_data.parameters
+            chat_id = data["chat_id"] == 2
+            user_id = data["user_id"] == 32
+            o_i_b = data.get("only_if_banned", None) == only_if_banned
+            return chat_id and user_id and o_i_b
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+
+        assert await bot.unban_chat_member(2, 32, only_if_banned=only_if_banned)
+
+    async def test_unban_chat_sender_chat(self, monkeypatch, bot):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            data = request_data.json_parameters
+            chat_id = data["chat_id"] == "2"
+            sender_chat_id = data["sender_chat_id"] == "32"
+            return chat_id and sender_chat_id
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+        assert await bot.unban_chat_sender_chat(2, 32)
+
+    async def test_set_chat_permissions(self, monkeypatch, bot, chat_permissions):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            data = request_data.json_parameters
+            chat_id = data["chat_id"] == "2"
+            permissions = data["permissions"] == chat_permissions.to_json()
+            return chat_id and permissions
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+
+        assert await bot.set_chat_permissions(2, chat_permissions)
+
+    async def test_set_chat_administrator_custom_title(self, monkeypatch, bot):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            data = request_data.parameters
+            chat_id = data["chat_id"] == 2
+            user_id = data["user_id"] == 32
+            custom_title = data["custom_title"] == "custom_title"
+            return chat_id and user_id and custom_title
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+        assert await bot.set_chat_administrator_custom_title(2, 32, "custom_title")
+
+    # TODO: Needs improvement. Need an incoming callbackquery to test
+    async def test_answer_callback_query(self, monkeypatch, bot):
+        # For now just test that our internals pass the correct data
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            return request_data.parameters == {
+                "callback_query_id": 23,
+                "show_alert": True,
+                "url": "no_url",
+                "cache_time": 1,
+                "text": "answer",
+            }
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+
+        assert await bot.answer_callback_query(
+            23, text="answer", show_alert=True, url="no_url", cache_time=1
+        )
+
+    @pytest.mark.parametrize("drop_pending_updates", [True, False])
+    async def test_set_webhook_delete_webhook_drop_pending_updates(
+        self, bot, drop_pending_updates, monkeypatch
+    ):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            data = request_data.parameters
+            return data.get("drop_pending_updates") == drop_pending_updates
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+
+        assert await bot.set_webhook("", drop_pending_updates=drop_pending_updates)
+        assert await bot.delete_webhook(drop_pending_updates=drop_pending_updates)
+
+    @pytest.mark.parametrize("local_file", ["str", "Path", False])
+    async def test_set_webhook_params(self, bot, monkeypatch, local_file):
+        # actually making calls to TG is done in
+        # test_set_webhook_get_webhook_info_and_delete_webhook. Sadly secret_token can't be tested
+        # there so we have this function \o/
+        async def make_assertion(*args, **_):
+            kwargs = args[1]
+
+            if local_file is False:
+                cert_assertion = (
+                    kwargs["certificate"].input_file_content
+                    == data_file("sslcert.pem").read_bytes()
+                )
+            else:
+                cert_assertion = data_file("sslcert.pem").as_uri()
+
+            return (
+                kwargs["url"] == "example.com"
+                and cert_assertion
+                and kwargs["max_connections"] == 7
+                and kwargs["allowed_updates"] == ["messages"]
+                and kwargs["ip_address"] == "127.0.0.1"
+                and kwargs["drop_pending_updates"]
+                and kwargs["secret_token"] == "SoSecretToken"
+            )
 
-        # Since only the poll and not the complete message is returned, we can't check that the
-        # reply_markup is correct. So we just test that sending doesn't give an error.
-        poll = await bot.stop_poll(
-            chat_id=super_group_id,
-            message_id=message.message_id,
-            reply_markup=reply_markup,
-            read_timeout=60,
-        )
-        assert isinstance(poll, Poll)
-        assert poll.is_closed
-        assert poll.options[0].text == answers[0]
-        assert poll.options[0].voter_count == 0
-        assert poll.options[1].text == answers[1]
-        assert poll.options[1].voter_count == 0
-        assert poll.options[2].text == answers[2]
-        assert poll.options[2].voter_count == 0
-        assert poll.question == question
-        assert poll.total_voter_count == 0
+        monkeypatch.setattr(bot, "_post", make_assertion)
 
-        explanation = "[Here is a link](https://google.com)"
-        explanation_entities = [
-            MessageEntity(MessageEntity.TEXT_LINK, 0, 14, url="https://google.com")
-        ]
-        message_quiz = await bot.send_poll(
-            chat_id=super_group_id,
-            question=question,
-            options=answers,
-            type=Poll.QUIZ,
-            correct_option_id=2,
-            is_closed=True,
-            explanation=explanation,
-            explanation_parse_mode=ParseMode.MARKDOWN_V2,
-        )
-        assert message_quiz.poll.correct_option_id == 2
-        assert message_quiz.poll.type == Poll.QUIZ
-        assert message_quiz.poll.is_closed
-        assert message_quiz.poll.explanation == "Here is a link"
-        assert message_quiz.poll.explanation_entities == tuple(explanation_entities)
+        cert_path = data_file("sslcert.pem")
+        if local_file == "str":
+            certificate = str(cert_path)
+        elif local_file == "Path":
+            certificate = cert_path
+        else:
+            certificate = cert_path.read_bytes()
 
-    @pytest.mark.flaky(3, 1)
-    @pytest.mark.parametrize(
-        ["open_period", "close_date"], [(5, None), (None, True)], ids=["open_period", "close_date"]
-    )
-    async def test_send_open_period(self, bot, super_group_id, open_period, close_date):
-        question = "Is this a test?"
-        answers = ["Yes", "No", "Maybe"]
-        reply_markup = InlineKeyboardMarkup.from_button(
-            InlineKeyboardButton(text="text", callback_data="data")
+        assert await bot.set_webhook(
+            "example.com",
+            certificate,
+            7,
+            ["messages"],
+            "127.0.0.1",
+            True,
+            "SoSecretToken",
         )
 
-        if close_date:
-            close_date = dtm.datetime.utcnow() + dtm.timedelta(seconds=5.05)
+    # TODO: Needs improvement. Need incoming shipping queries to test
+    async def test_answer_shipping_query_ok(self, monkeypatch, bot):
+        # For now just test that our internals pass the correct data
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            return request_data.parameters == {
+                "shipping_query_id": 1,
+                "ok": True,
+                "shipping_options": [
+                    {"title": "option1", "prices": [{"label": "price", "amount": 100}], "id": 1}
+                ],
+            }
 
-        message = await bot.send_poll(
-            chat_id=super_group_id,
-            question=question,
-            options=answers,
-            is_anonymous=False,
-            allows_multiple_answers=True,
-            read_timeout=60,
-            open_period=open_period,
-            close_date=close_date,
-        )
-        await asyncio.sleep(5.1)
-        new_message = await bot.edit_message_reply_markup(
-            chat_id=super_group_id,
-            message_id=message.message_id,
-            reply_markup=reply_markup,
-            read_timeout=60,
-        )
-        assert new_message.poll.id == message.poll.id
-        assert new_message.poll.is_closed
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+        shipping_options = ShippingOption(1, "option1", [LabeledPrice("price", 100)])
+        assert await bot.answer_shipping_query(1, True, shipping_options=[shipping_options])
 
-    @pytest.mark.flaky(3, 1)
-    async def test_send_close_date_default_tz(self, tz_bot, super_group_id):
-        question = "Is this a test?"
-        answers = ["Yes", "No", "Maybe"]
-        reply_markup = InlineKeyboardMarkup.from_button(
-            InlineKeyboardButton(text="text", callback_data="data")
-        )
+    async def test_answer_shipping_query_error_message(self, monkeypatch, bot):
+        # For now just test that our internals pass the correct data
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            return request_data.parameters == {
+                "shipping_query_id": 1,
+                "error_message": "Not enough fish",
+                "ok": False,
+            }
 
-        aware_close_date = dtm.datetime.now(tz=tz_bot.defaults.tzinfo) + dtm.timedelta(seconds=5)
-        close_date = aware_close_date.replace(tzinfo=None)
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+        assert await bot.answer_shipping_query(1, False, error_message="Not enough fish")
 
-        msg = await tz_bot.send_poll(  # The timezone returned from this is always converted to UTC
-            chat_id=super_group_id,
-            question=question,
-            options=answers,
-            close_date=close_date,
-            read_timeout=60,
-        )
-        msg.poll._unfreeze()
-        # Sometimes there can be a few seconds delay, so don't let the test fail due to that-
-        msg.poll.close_date = msg.poll.close_date.astimezone(aware_close_date.tzinfo)
-        assert abs(msg.poll.close_date - aware_close_date) <= dtm.timedelta(seconds=5)
+    # TODO: Needs improvement. Need incoming pre checkout queries to test
+    async def test_answer_pre_checkout_query_ok(self, monkeypatch, bot):
+        # For now just test that our internals pass the correct data
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            return request_data.parameters == {"pre_checkout_query_id": 1, "ok": True}
 
-        await asyncio.sleep(5.1)
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+        assert await bot.answer_pre_checkout_query(1, True)
 
-        new_message = await tz_bot.edit_message_reply_markup(
-            chat_id=super_group_id,
-            message_id=msg.message_id,
-            reply_markup=reply_markup,
-            read_timeout=60,
-        )
-        assert new_message.poll.id == msg.poll.id
-        assert new_message.poll.is_closed
+    async def test_answer_pre_checkout_query_error_message(self, monkeypatch, bot):
+        # For now just test that our internals pass the correct data
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            return request_data.parameters == {
+                "pre_checkout_query_id": 1,
+                "error_message": "Not enough fish",
+                "ok": False,
+            }
 
-    @pytest.mark.flaky(3, 1)
-    async def test_send_poll_explanation_entities(self, bot, chat_id):
-        test_string = "Italic Bold Code"
-        entities = [
-            MessageEntity(MessageEntity.ITALIC, 0, 6),
-            MessageEntity(MessageEntity.ITALIC, 7, 4),
-            MessageEntity(MessageEntity.ITALIC, 12, 4),
-        ]
-        message = await bot.send_poll(
-            chat_id,
-            "question",
-            options=["a", "b"],
-            correct_option_id=0,
-            type=Poll.QUIZ,
-            explanation=test_string,
-            explanation_entities=entities,
-        )
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+        assert await bot.answer_pre_checkout_query(1, False, error_message="Not enough fish")
 
-        assert message.poll.explanation == test_string
-        assert message.poll.explanation_entities == tuple(entities)
+    async def test_restrict_chat_member_default_tz(
+        self, monkeypatch, tz_bot, channel_id, chat_permissions
+    ):
+        until = dtm.datetime(2020, 1, 11, 16, 13)
+        until_timestamp = to_timestamp(until, tzinfo=tz_bot.defaults.tzinfo)
 
-    @pytest.mark.flaky(3, 1)
-    @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
-    async def test_send_poll_default_parse_mode(self, default_bot, super_group_id):
-        explanation = "Italic Bold Code"
-        explanation_markdown = "_Italic_ *Bold* `Code`"
-        question = "Is this a test?"
-        answers = ["Yes", "No", "Maybe"]
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            return request_data.parameters.get("until_date", until_timestamp) == until_timestamp
 
-        message = await default_bot.send_poll(
-            chat_id=super_group_id,
-            question=question,
-            options=answers,
-            type=Poll.QUIZ,
-            correct_option_id=2,
-            is_closed=True,
-            explanation=explanation_markdown,
+        monkeypatch.setattr(tz_bot.request, "post", make_assertion)
+
+        assert await tz_bot.restrict_chat_member(channel_id, 95205500, chat_permissions)
+        assert await tz_bot.restrict_chat_member(
+            channel_id, 95205500, chat_permissions, until_date=until
         )
-        assert message.poll.explanation == explanation
-        assert message.poll.explanation_entities == (
-            MessageEntity(MessageEntity.ITALIC, 0, 6),
-            MessageEntity(MessageEntity.BOLD, 7, 4),
-            MessageEntity(MessageEntity.CODE, 12, 4),
+        assert await tz_bot.restrict_chat_member(
+            channel_id, 95205500, chat_permissions, until_date=until_timestamp
         )
 
-        message = await default_bot.send_poll(
-            chat_id=super_group_id,
-            question=question,
-            options=answers,
-            type=Poll.QUIZ,
-            correct_option_id=2,
-            is_closed=True,
-            explanation=explanation_markdown,
-            explanation_parse_mode=None,
-        )
-        assert message.poll.explanation == explanation_markdown
-        assert message.poll.explanation_entities == ()
+    @pytest.mark.parametrize("local_mode", [True, False])
+    async def test_set_chat_photo_local_files(self, monkeypatch, bot, chat_id, local_mode):
+        try:
+            bot._local_mode = local_mode
+            # For just test that the correct paths are passed as we have no local bot API set up
+            test_flag = False
+            file = data_file("telegram.jpg")
+            expected = file.as_uri()
 
-        message = await default_bot.send_poll(
-            chat_id=super_group_id,
-            question=question,
-            options=answers,
-            type=Poll.QUIZ,
-            correct_option_id=2,
-            is_closed=True,
-            explanation=explanation_markdown,
-            explanation_parse_mode="HTML",
-        )
-        assert message.poll.explanation == explanation_markdown
-        assert message.poll.explanation_entities == ()
+            async def make_assertion(_, data, *args, **kwargs):
+                nonlocal test_flag
+                if local_mode:
+                    test_flag = data.get("photo") == expected
+                else:
+                    test_flag = isinstance(data.get("photo"), InputFile)
 
-    @pytest.mark.flaky(3, 1)
-    @pytest.mark.parametrize(
-        "default_bot,custom",
-        [
-            ({"allow_sending_without_reply": True}, None),
-            ({"allow_sending_without_reply": False}, None),
-            ({"allow_sending_without_reply": False}, True),
-        ],
-        indirect=["default_bot"],
-    )
-    async def test_send_poll_default_allow_sending_without_reply(
-        self, default_bot, chat_id, custom
-    ):
-        question = "Is this a test?"
-        answers = ["Yes", "No", "Maybe"]
-        reply_to_message = await default_bot.send_message(chat_id, "test")
-        await reply_to_message.delete()
-        if custom is not None:
-            message = await default_bot.send_poll(
-                chat_id,
-                question=question,
-                options=answers,
-                allow_sending_without_reply=custom,
-                reply_to_message_id=reply_to_message.message_id,
-            )
-            assert message.reply_to_message is None
-        elif default_bot.defaults.allow_sending_without_reply:
-            message = await default_bot.send_poll(
-                chat_id,
-                question=question,
-                options=answers,
-                reply_to_message_id=reply_to_message.message_id,
-            )
-            assert message.reply_to_message is None
-        else:
-            with pytest.raises(BadRequest, match="message not found"):
-                await default_bot.send_poll(
-                    chat_id,
-                    question=question,
-                    options=answers,
-                    reply_to_message_id=reply_to_message.message_id,
-                )
+            monkeypatch.setattr(bot, "_post", make_assertion)
+            await bot.set_chat_photo(chat_id, file)
+            assert test_flag
+        finally:
+            bot._local_mode = False
 
-    @pytest.mark.flaky(3, 1)
-    @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
-    async def test_send_poll_default_protect_content(self, chat_id, default_bot):
-        protected_poll = await default_bot.send_poll(chat_id, "Test", ["1", "2"])
-        assert protected_poll.has_protected_content
-        unprotect_poll = await default_bot.send_poll(
-            chat_id, "test", ["1", "2"], protect_content=False
-        )
-        assert not unprotect_poll.has_protected_content
+    async def test_timeout_propagation_explicit(self, monkeypatch, bot, chat_id):
+        # Use BaseException that's not a subclass of Exception such that
+        # OkException should not be caught anywhere
+        class OkException(BaseException):
+            pass
 
-    @pytest.mark.flaky(3, 1)
-    @pytest.mark.parametrize("emoji", Dice.ALL_EMOJI + [None])
-    async def test_send_dice(self, bot, chat_id, emoji):
-        message = await bot.send_dice(chat_id, emoji=emoji, protect_content=True)
+        timeout = 42
 
-        assert message.dice
-        assert message.has_protected_content
-        if emoji is None:
-            assert message.dice.emoji == Dice.DICE
-        else:
-            assert message.dice.emoji == emoji
+        async def do_request(*args, **kwargs):
+            obj = kwargs.get("read_timeout")
+            if obj == timeout:
+                raise OkException
 
-    @pytest.mark.flaky(3, 1)
-    @pytest.mark.parametrize(
-        "default_bot,custom",
-        [
-            ({"allow_sending_without_reply": True}, None),
-            ({"allow_sending_without_reply": False}, None),
-            ({"allow_sending_without_reply": False}, True),
-        ],
-        indirect=["default_bot"],
-    )
-    async def test_send_dice_default_allow_sending_without_reply(
-        self, default_bot, chat_id, custom
-    ):
-        reply_to_message = await default_bot.send_message(chat_id, "test")
-        await reply_to_message.delete()
-        if custom is not None:
-            message = await default_bot.send_dice(
-                chat_id,
-                allow_sending_without_reply=custom,
-                reply_to_message_id=reply_to_message.message_id,
-            )
-            assert message.reply_to_message is None
-        elif default_bot.defaults.allow_sending_without_reply:
-            message = await default_bot.send_dice(
-                chat_id,
-                reply_to_message_id=reply_to_message.message_id,
-            )
-            assert message.reply_to_message is None
-        else:
-            with pytest.raises(BadRequest, match="message not found"):
-                await default_bot.send_dice(
-                    chat_id, reply_to_message_id=reply_to_message.message_id
-                )
+            return 200, b'{"ok": true, "result": []}'
 
-    @pytest.mark.flaky(3, 1)
-    @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
-    async def test_send_dice_default_protect_content(self, chat_id, default_bot):
-        protected_dice = await default_bot.send_dice(chat_id)
-        assert protected_dice.has_protected_content
-        unprotected_dice = await default_bot.send_dice(chat_id, protect_content=False)
-        assert not unprotected_dice.has_protected_content
+        monkeypatch.setattr(bot.request, "do_request", do_request)
 
-    @pytest.mark.flaky(3, 1)
-    @pytest.mark.parametrize("chat_action", list(ChatAction))
-    async def test_send_chat_action(self, bot, chat_id, chat_action):
-        assert await bot.send_chat_action(chat_id, chat_action)
+        # Test file uploading
+        with pytest.raises(OkException):
+            await bot.send_photo(
+                chat_id, data_file("telegram.jpg").open("rb"), read_timeout=timeout
+            )
 
-    async def test_wrong_chat_action(self, bot, chat_id):
-        with pytest.raises(BadRequest, match="Wrong parameter action"):
-            await bot.send_chat_action(chat_id, "unknown action")
+        # Test JSON submission
+        with pytest.raises(OkException):
+            await bot.get_chat_administrators(chat_id, read_timeout=timeout)
 
-    @pytest.mark.asyncio
-    async def test_answer_web_app_query(self, bot, raw_bot, monkeypatch):
-        params = False
+    async def test_timeout_propagation_implicit(self, monkeypatch, bot, chat_id):
+        # Use BaseException that's not a subclass of Exception such that
+        # OkException should not be caught anywhere
+        class OkException(BaseException):
+            pass
 
-        # For now just test that our internals pass the correct data
+        async def do_request(*args, **kwargs):
+            obj = kwargs.get("write_timeout")
+            if obj == 20:
+                raise OkException
 
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            nonlocal params
-            params = request_data.parameters == {
-                "web_app_query_id": "12345",
-                "result": {
-                    "title": "title",
-                    "input_message_content": {
-                        "message_text": "text",
-                    },
-                    "type": InlineQueryResultType.ARTICLE,
-                    "id": "1",
-                },
-            }
-            web_app_msg = SentWebAppMessage("321").to_dict()
-            return web_app_msg
+            return 200, b'{"ok": true, "result": []}'
 
-        # We test different result types more thoroughly for answer_inline_query, so we just
-        # use the one type here
-        result = InlineQueryResultArticle("1", "title", InputTextMessageContent("text"))
-        copied_result = copy.copy(result)
+        monkeypatch.setattr(bot.request, "do_request", do_request)
 
-        ext_bot = bot
-        for bot in (ext_bot, raw_bot):
-            # We need to test 1) below both the bot and raw_bot and setting this up with
-            # pytest.parametrize appears to be difficult ...
-            monkeypatch.setattr(bot.request, "post", make_assertion)
-            web_app_msg = await bot.answer_web_app_query("12345", result)
-            assert params, "something went wrong with passing arguments to the request"
-            assert isinstance(web_app_msg, SentWebAppMessage)
-            assert web_app_msg.inline_message_id == "321"
+        # Test file uploading
+        with pytest.raises(OkException):
+            await bot.send_photo(chat_id, data_file("telegram.jpg").open("rb"))
 
-            # 1)
-            # make sure that the results were not edited in-place
-            assert result == copied_result
-            assert (
-                result.input_message_content.parse_mode
-                == copied_result.input_message_content.parse_mode
-            )
+    async def test_log_out(self, monkeypatch, bot):
+        # We don't actually make a request as to not break the test setup
+        async def assertion(url, request_data: RequestData, *args, **kwargs):
+            return request_data.json_parameters == {} and url.split("/")[-1] == "logOut"
 
-    @pytest.mark.asyncio
-    @pytest.mark.parametrize(
-        "default_bot",
-        [{"parse_mode": "Markdown", "disable_web_page_preview": True}],
-        indirect=True,
-    )
-    @pytest.mark.parametrize(
-        "ilq_result,expected_params",
-        [
-            (
-                InlineQueryResultArticle("1", "title", InputTextMessageContent("text")),
-                {
-                    "web_app_query_id": "12345",
-                    "result": {
-                        "title": "title",
-                        "input_message_content": {
-                            "message_text": "text",
-                            "parse_mode": "Markdown",
-                            "disable_web_page_preview": True,
-                        },
-                        "type": InlineQueryResultType.ARTICLE,
-                        "id": "1",
-                    },
-                },
-            ),
-            (
-                InlineQueryResultArticle(
-                    "1",
-                    "title",
-                    InputTextMessageContent(
-                        "text", parse_mode="HTML", disable_web_page_preview=False
-                    ),
-                ),
-                {
-                    "web_app_query_id": "12345",
-                    "result": {
-                        "title": "title",
-                        "input_message_content": {
-                            "message_text": "text",
-                            "parse_mode": "HTML",
-                            "disable_web_page_preview": False,
-                        },
-                        "type": InlineQueryResultType.ARTICLE,
-                        "id": "1",
-                    },
-                },
-            ),
-            (
-                InlineQueryResultArticle(
-                    "1",
-                    "title",
-                    InputTextMessageContent(
-                        "text", parse_mode=None, disable_web_page_preview="False"
-                    ),
-                ),
-                {
-                    "web_app_query_id": "12345",
-                    "result": {
-                        "title": "title",
-                        "input_message_content": {
-                            "message_text": "text",
-                            "disable_web_page_preview": "False",
-                        },
-                        "type": InlineQueryResultType.ARTICLE,
-                        "id": "1",
-                    },
-                },
-            ),
-        ],
-    )
-    async def test_answer_web_app_query_defaults(
-        self, default_bot, ilq_result, expected_params, monkeypatch
-    ):
-        bot = default_bot
-        params = False
+        monkeypatch.setattr(bot.request, "post", assertion)
 
-        # For now just test that our internals pass the correct data
+        assert await bot.log_out()
 
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            nonlocal params
-            params = request_data.parameters == expected_params
-            web_app_msg = SentWebAppMessage("321").to_dict()
-            return web_app_msg
+    async def test_close(self, monkeypatch, bot):
+        # We don't actually make a request as to not break the test setup
+        async def assertion(url, request_data: RequestData, *args, **kwargs):
+            return request_data.json_parameters == {} and url.split("/")[-1] == "close"
 
-        monkeypatch.setattr(bot.request, "post", make_assertion)
+        monkeypatch.setattr(bot.request, "post", assertion)
 
-        # We test different result types more thoroughly for answer_inline_query, so we just
-        # use the one type here
-        copied_result = copy.copy(ilq_result)
+        assert await bot.close()
 
-        web_app_msg = await bot.answer_web_app_query("12345", ilq_result)
-        assert params, "something went wrong with passing arguments to the request"
-        assert isinstance(web_app_msg, SentWebAppMessage)
-        assert web_app_msg.inline_message_id == "321"
+    @pytest.mark.parametrize("json_keyboard", [True, False])
+    @pytest.mark.parametrize("caption", ["<b>Test</b>", "", None])
+    async def test_copy_message(
+        self, monkeypatch, bot, chat_id, media_message, json_keyboard, caption
+    ):
+        keyboard = InlineKeyboardMarkup(
+            [[InlineKeyboardButton(text="test", callback_data="test2")]]
+        )
+
+        async def post(url, request_data: RequestData, *args, **kwargs):
+            data = request_data.parameters
+            if not all(
+                [
+                    data["chat_id"] == chat_id,
+                    data["from_chat_id"] == chat_id,
+                    data["message_id"] == media_message.message_id,
+                    data.get("caption") == caption,
+                    data["parse_mode"] == ParseMode.HTML,
+                    data["reply_to_message_id"] == media_message.message_id,
+                    data["reply_markup"] == keyboard.to_json()
+                    if json_keyboard
+                    else keyboard.to_dict(),
+                    data["disable_notification"] is True,
+                    data["caption_entities"]
+                    == [MessageEntity(MessageEntity.BOLD, 0, 4).to_dict()],
+                    data["protect_content"] is True,
+                    data["message_thread_id"] == 1,
+                ]
+            ):
+                pytest.fail("I got wrong parameters in post")
+            return data
 
-        # make sure that the results were not edited in-place
-        assert ilq_result == copied_result
-        assert (
-            ilq_result.input_message_content.parse_mode
-            == copied_result.input_message_content.parse_mode
+        monkeypatch.setattr(bot.request, "post", post)
+        await bot.copy_message(
+            chat_id,
+            from_chat_id=chat_id,
+            message_id=media_message.message_id,
+            caption=caption,
+            caption_entities=[MessageEntity(MessageEntity.BOLD, 0, 4)],
+            parse_mode=ParseMode.HTML,
+            reply_to_message_id=media_message.message_id,
+            reply_markup=keyboard.to_json() if json_keyboard else keyboard,
+            disable_notification=True,
+            protect_content=True,
+            message_thread_id=1,
         )
 
     # TODO: Needs improvement. We need incoming inline query to test answer.
-    async def test_answer_inline_query(self, monkeypatch, bot, raw_bot):
-        # For now just test that our internals pass the correct data
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            return request_data.parameters == {
-                "cache_time": 300,
-                "results": [
-                    {
-                        "title": "first",
-                        "id": "11",
-                        "type": "article",
-                        "input_message_content": {"message_text": "first"},
-                    },
-                    {
-                        "title": "second",
-                        "id": "12",
-                        "type": "article",
-                        "input_message_content": {"message_text": "second"},
-                    },
-                    {
-                        "title": "test_result",
-                        "id": "123",
-                        "type": "document",
-                        "document_url": "https://raw.githubusercontent.com/python-telegram-bot"
-                        "/logos/master/logo/png/ptb-logo_240.png",
-                        "mime_type": "image/png",
-                        "caption": "ptb_logo",
-                        "input_message_content": {"message_text": "imc"},
-                    },
-                ],
-                "next_offset": "42",
-                "switch_pm_parameter": "start_pm",
-                "inline_query_id": 1234,
-                "is_personal": True,
-                "switch_pm_text": "switch pm",
-            }
+    async def test_replace_callback_data_answer_inline_query(self, monkeypatch, cdc_bot, chat_id):
+        bot = cdc_bot
 
-        results = [
-            InlineQueryResultArticle("11", "first", InputTextMessageContent("first")),
-            InlineQueryResultArticle("12", "second", InputMessageContentDWPP("second")),
-            InlineQueryResultDocument(
-                id="123",
-                document_url="https://raw.githubusercontent.com/python-telegram-bot/logos/master/"
-                "logo/png/ptb-logo_240.png",
-                title="test_result",
-                mime_type="image/png",
-                caption="ptb_logo",
-                input_message_content=InputMessageContentDWPP("imc"),
-            ),
-        ]
+        # For now just test that our internals pass the correct data
+        async def make_assertion(
+            endpoint,
+            data=None,
+            *args,
+            **kwargs,
+        ):
+            inline_keyboard = data["results"][0]["reply_markup"].inline_keyboard
+            assertion_1 = inline_keyboard[0][1] == no_replace_button
+            assertion_2 = inline_keyboard[0][0] != replace_button
+            keyboard, button = (
+                inline_keyboard[0][0].callback_data[:32],
+                inline_keyboard[0][0].callback_data[32:],
+            )
+            assertion_3 = (
+                bot.callback_data_cache._keyboard_data[keyboard].button_data[button]
+                == "replace_test"
+            )
+            assertion_4 = data["results"][1].reply_markup is None
+            return assertion_1 and assertion_2 and assertion_3 and assertion_4
 
-        copied_results = copy.copy(results)
-        ext_bot = bot
-        for bot in (ext_bot, raw_bot):
-            # We need to test 1) below both the bot and raw_bot and setting this up with
-            # pytest.parametrize appears to be difficult ...
-            monkeypatch.setattr(bot.request, "post", make_assertion)
-            assert await bot.answer_inline_query(
-                1234,
-                results=results,
-                cache_time=300,
-                is_personal=True,
-                next_offset="42",
-                switch_pm_text="switch pm",
-                switch_pm_parameter="start_pm",
+        try:
+            replace_button = InlineKeyboardButton(text="replace", callback_data="replace_test")
+            no_replace_button = InlineKeyboardButton(
+                text="no_replace", url="http://python-telegram-bot.org/"
+            )
+            reply_markup = InlineKeyboardMarkup.from_row(
+                [
+                    replace_button,
+                    no_replace_button,
+                ]
             )
 
-            # 1)
-            # make sure that the results were not edited in-place
-            assert results == copied_results
-            for idx, result in enumerate(results):
-                if hasattr(result, "parse_mode"):
-                    assert result.parse_mode == copied_results[idx].parse_mode
-                if hasattr(result, "input_message_content"):
-                    assert getattr(result.input_message_content, "parse_mode", None) == getattr(
-                        copied_results[idx].input_message_content, "parse_mode", None
-                    )
-                    assert getattr(
-                        result.input_message_content, "disable_web_page_preview", None
-                    ) == getattr(
-                        copied_results[idx].input_message_content, "disable_web_page_preview", None
-                    )
+            bot.username  # call this here so `bot.get_me()` won't be called after mocking
+            monkeypatch.setattr(bot, "_post", make_assertion)
+            results = [
+                InlineQueryResultArticle(
+                    "11", "first", InputTextMessageContent("first"), reply_markup=reply_markup
+                ),
+                InlineQueryResultVoice(
+                    "22",
+                    "https://python-telegram-bot.org/static/testfiles/telegram.ogg",
+                    title="second",
+                ),
+            ]
 
-            monkeypatch.delattr(bot.request, "post")
+            assert await bot.answer_inline_query(chat_id, results=results)
 
-    async def test_answer_inline_query_no_default_parse_mode(self, monkeypatch, bot):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            return request_data.parameters == {
-                "cache_time": 300,
-                "results": [
-                    {
-                        "title": "first",
-                        "id": "11",
-                        "type": "article",
-                        "input_message_content": {"message_text": "first"},
-                    },
-                    {
-                        "title": "second",
-                        "id": "12",
-                        "type": "article",
-                        "input_message_content": {"message_text": "second"},
-                    },
-                    {
-                        "title": "test_result",
-                        "id": "123",
-                        "type": "document",
-                        "document_url": "https://raw.githubusercontent.com/"
-                        "python-telegram-bot/logos/master/logo/png/"
-                        "ptb-logo_240.png",
-                        "mime_type": "image/png",
-                        "caption": "ptb_logo",
-                        "input_message_content": {"message_text": "imc"},
-                    },
-                ],
-                "next_offset": "42",
-                "switch_pm_parameter": "start_pm",
-                "inline_query_id": 1234,
-                "is_personal": True,
-                "switch_pm_text": "switch pm",
-            }
+        finally:
+            bot.callback_data_cache.clear_callback_data()
+            bot.callback_data_cache.clear_callback_queries()
 
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-        results = [
-            InlineQueryResultArticle("11", "first", InputTextMessageContent("first")),
-            InlineQueryResultArticle("12", "second", InputMessageContentDWPP("second")),
-            InlineQueryResultDocument(
-                id="123",
-                document_url="https://raw.githubusercontent.com/python-telegram-bot/logos/master/"
-                "logo/png/ptb-logo_240.png",
-                title="test_result",
-                mime_type="image/png",
-                caption="ptb_logo",
-                input_message_content=InputMessageContentDWPP("imc"),
-            ),
-        ]
+    @bot_methods()
+    def test_camel_case_aliases(self, bot_class, bot_method_name, bot_method):
+        camel_case_name = to_camel_case(bot_method_name)
+        camel_case_function = getattr(bot_class, camel_case_name, False)
+        assert camel_case_function is not False, f"{camel_case_name} not found"
+        assert camel_case_function is bot_method, f"{camel_case_name} is not {bot_method}"
 
-        copied_results = copy.copy(results)
-        assert await bot.answer_inline_query(
-            1234,
-            results=results,
-            cache_time=300,
-            is_personal=True,
-            next_offset="42",
-            switch_pm_text="switch pm",
-            switch_pm_parameter="start_pm",
-        )
-        # make sure that the results were not edited in-place
-        assert results == copied_results
-        for idx, result in enumerate(results):
-            if hasattr(result, "parse_mode"):
-                assert result.parse_mode == copied_results[idx].parse_mode
-            if hasattr(result, "input_message_content"):
-                assert getattr(result.input_message_content, "parse_mode", None) == getattr(
-                    copied_results[idx].input_message_content, "parse_mode", None
-                )
-                assert getattr(
-                    result.input_message_content, "disable_web_page_preview", None
-                ) == getattr(
-                    copied_results[idx].input_message_content, "disable_web_page_preview", None
-                )
+    @bot_methods()
+    def test_coroutine_functions(self, bot_class, bot_method_name, bot_method, monkeypatch):
+        """Check that all bot methods are defined as async def  ..."""
+        meth = getattr(bot_method, "__wrapped__", bot_method)
+        assert inspect.iscoroutinefunction(meth), f"{bot_method_name} must be a coroutine function"
+
+    @bot_methods()
+    def test_api_kwargs_and_timeouts_present(self, bot_class, bot_method_name, bot_method):
+        """Check that all bot methods have `api_kwargs` and timeout params."""
+        param_names = inspect.signature(bot_method).parameters.keys()
+        assert (
+            "pool_timeout" in param_names
+        ), f"{bot_method_name} is missing the parameter `pool_timeout`"
+        assert (
+            "read_timeout" in param_names
+        ), f"{bot_method_name} is missing the parameter `read_timeout`"
+        assert (
+            "connect_timeout" in param_names
+        ), f"{bot_method_name} is missing the parameter `connect_timeout`"
+        assert (
+            "write_timeout" in param_names
+        ), f"{bot_method_name} is missing the parameter `write_timeout`"
+        assert (
+            "api_kwargs" in param_names
+        ), f"{bot_method_name} is missing the parameter `api_kwargs`"
+
+        if bot_class is ExtBot and bot_method_name.replace("_", "").lower() != "getupdates":
+            assert (
+                "rate_limit_args" in param_names
+            ), f"{bot_method_name} of ExtBot is missing the parameter `rate_limit_args`"
 
-    @pytest.mark.parametrize(
-        "default_bot",
-        [{"parse_mode": "Markdown", "disable_web_page_preview": True}],
-        indirect=True,
-    )
-    async def test_answer_inline_query_default_parse_mode(self, monkeypatch, default_bot):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            return request_data.parameters == {
-                "cache_time": 300,
-                "results": [
-                    {
-                        "title": "first",
-                        "id": "11",
-                        "type": "article",
-                        "input_message_content": {
-                            "message_text": "first",
-                            "parse_mode": "Markdown",
-                            "disable_web_page_preview": True,
-                        },
-                    },
-                    {
-                        "title": "second",
-                        "id": "12",
-                        "type": "article",
-                        "input_message_content": {
-                            "message_text": "second",
-                            "disable_web_page_preview": True,
-                        },
-                    },
-                    {
-                        "title": "test_result",
-                        "id": "123",
-                        "type": "document",
-                        "document_url": "https://raw.githubusercontent.com/"
-                        "python-telegram-bot/logos/master/logo/png/"
-                        "ptb-logo_240.png",
-                        "mime_type": "image/png",
-                        "caption": "ptb_logo",
-                        "parse_mode": "Markdown",
-                        "input_message_content": {
-                            "message_text": "imc",
-                            "disable_web_page_preview": True,
-                            "parse_mode": "Markdown",
-                        },
-                    },
-                ],
-                "next_offset": "42",
-                "switch_pm_parameter": "start_pm",
-                "inline_query_id": 1234,
-                "is_personal": True,
-                "switch_pm_text": "switch pm",
-            }
 
-        monkeypatch.setattr(default_bot.request, "post", make_assertion)
-        results = [
-            InlineQueryResultArticle("11", "first", InputTextMessageContent("first")),
-            InlineQueryResultArticle("12", "second", InputMessageContentDWPP("second")),
-            InlineQueryResultDocument(
-                id="123",
-                document_url="https://raw.githubusercontent.com/python-telegram-bot/logos/master/"
-                "logo/png/ptb-logo_240.png",
-                title="test_result",
-                mime_type="image/png",
-                caption="ptb_logo",
-                input_message_content=InputTextMessageContent("imc"),
-            ),
-        ]
+class TestBotReq:
+    """
+    Most are executed on tg.ext.ExtBot, as that class only extends the functionality of tg.bot
 
-        copied_results = copy.copy(results)
-        assert await default_bot.answer_inline_query(
-            1234,
-            results=results,
-            cache_time=300,
-            is_personal=True,
-            next_offset="42",
-            switch_pm_text="switch pm",
-            switch_pm_parameter="start_pm",
+    Behavior for init of ExtBot with missing optional dependency cachetools (for CallbackDataCache)
+    is tested in `test_callbackdatacache`
+    """
+
+    async def test_invalid_token_server_response(self):
+        with pytest.raises(InvalidToken, match="The token `12` was rejected by the server."):
+            async with ExtBot(token="12"):
+                pass
+
+    async def test_multiple_init_cycles(self, bot):
+        # nothing really to assert - this should just not fail
+        test_bot = Bot(bot.token)
+        async with test_bot:
+            await test_bot.get_me()
+        async with test_bot:
+            await test_bot.get_me()
+
+    async def test_forward_message(self, bot, chat_id, message):
+        forward_message = await bot.forward_message(
+            chat_id, from_chat_id=chat_id, message_id=message.message_id
         )
-        # make sure that the results were not edited in-place
-        assert results == copied_results
-        for idx, result in enumerate(results):
-            if hasattr(result, "parse_mode"):
-                assert result.parse_mode == copied_results[idx].parse_mode
-            if hasattr(result, "input_message_content"):
-                assert getattr(result.input_message_content, "parse_mode", None) == getattr(
-                    copied_results[idx].input_message_content, "parse_mode", None
-                )
-                assert getattr(
-                    result.input_message_content, "disable_web_page_preview", None
-                ) == getattr(
-                    copied_results[idx].input_message_content, "disable_web_page_preview", None
-                )
 
-    async def test_answer_inline_query_current_offset_error(self, bot, inline_results):
-        with pytest.raises(ValueError, match=("`current_offset` and `next_offset`")):
-            await bot.answer_inline_query(
-                1234, results=inline_results, next_offset=42, current_offset=51
-            )
+        assert forward_message.text == message.text
+        assert forward_message.forward_from.username == message.from_user.username
+        assert isinstance(forward_message.forward_date, dtm.datetime)
 
-    @pytest.mark.parametrize(
-        "current_offset,num_results,id_offset,expected_next_offset",
-        [
-            ("", InlineQueryLimit.RESULTS, 1, 1),
-            (1, InlineQueryLimit.RESULTS, 51, 2),
-            (5, 3, 251, ""),
-        ],
-    )
-    async def test_answer_inline_query_current_offset_1(
-        self,
-        monkeypatch,
-        bot,
-        inline_results,
-        current_offset,
-        num_results,
-        id_offset,
-        expected_next_offset,
-    ):
-        # For now just test that our internals pass the correct data
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            data = request_data.parameters
-            results = data["results"]
-            length_matches = len(results) == num_results
-            ids_match = all(int(res["id"]) == id_offset + i for i, res in enumerate(results))
-            next_offset_matches = data["next_offset"] == str(expected_next_offset)
-            return length_matches and ids_match and next_offset_matches
+    async def test_forward_protected_message(self, bot, chat_id):
+        tasks = asyncio.gather(
+            bot.send_message(chat_id, "cant forward me", protect_content=True),
+            bot.send_message(chat_id, "forward me", protect_content=False),
+        )
+        to_forward_protected, to_forward_unprotected = await tasks
 
-        monkeypatch.setattr(bot.request, "post", make_assertion)
+        assert to_forward_protected.has_protected_content
+        assert not to_forward_unprotected.has_protected_content
 
-        assert await bot.answer_inline_query(
-            1234, results=inline_results, current_offset=current_offset
+        forwarded_but_now_protected = await to_forward_unprotected.forward(
+            chat_id, protect_content=True
         )
+        assert forwarded_but_now_protected.has_protected_content
 
-    async def test_answer_inline_query_current_offset_2(self, monkeypatch, bot, inline_results):
-        # For now just test that our internals pass the correct data
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            data = request_data.parameters
-            results = data["results"]
-            length_matches = len(results) == InlineQueryLimit.RESULTS
-            ids_match = all(int(res["id"]) == 1 + i for i, res in enumerate(results))
-            next_offset_matches = data["next_offset"] == "1"
-            return length_matches and ids_match and next_offset_matches
+        tasks = asyncio.gather(
+            to_forward_protected.forward(chat_id),
+            forwarded_but_now_protected.forward(chat_id),
+            return_exceptions=True,
+        )
+        result = await tasks
+        assert all("can't be forwarded" in str(exc) for exc in result)
 
-        monkeypatch.setattr(bot.request, "post", make_assertion)
+    async def test_delete_message(self, bot, chat_id):
+        message = await bot.send_message(chat_id, text="will be deleted")
+        await asyncio.sleep(2)
 
-        assert await bot.answer_inline_query(1234, results=inline_results, current_offset=0)
+        assert await bot.delete_message(chat_id=chat_id, message_id=message.message_id) is True
 
-        inline_results = inline_results[:30]
+    async def test_delete_message_old_message(self, bot, chat_id):
+        with pytest.raises(BadRequest):
+            # Considering that the first message is old enough
+            await bot.delete_message(chat_id=chat_id, message_id=1)
 
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            data = request_data.parameters
-            results = data["results"]
-            length_matches = len(results) == 30
-            ids_match = all(int(res["id"]) == 1 + i for i, res in enumerate(results))
-            next_offset_matches = data["next_offset"] == ""
-            return length_matches and ids_match and next_offset_matches
+    # send_photo, send_audio, send_document, send_sticker, send_video, send_voice, send_video_note,
+    # send_media_group and send_animation are tested in their respective test modules. No need to
+    # duplicate here.
 
-        monkeypatch.setattr(bot.request, "post", make_assertion)
+    async def test_send_venue(self, bot, chat_id):
+        longitude = -46.788279
+        latitude = -23.691288
+        title = "title"
+        address = "address"
+        foursquare_id = "foursquare id"
+        foursquare_type = "foursquare type"
+        google_place_id = "google_place id"
+        google_place_type = "google_place type"
 
-        assert await bot.answer_inline_query(1234, results=inline_results, current_offset=0)
+        tasks = asyncio.gather(
+            *(
+                bot.send_venue(
+                    chat_id=chat_id,
+                    title=title,
+                    address=address,
+                    latitude=latitude,
+                    longitude=longitude,
+                    protect_content=True,
+                    **i,
+                )
+                for i in (
+                    {"foursquare_id": foursquare_id, "foursquare_type": foursquare_type},
+                    {"google_place_id": google_place_id, "google_place_type": google_place_type},
+                )
+            ),
+        )
 
-    async def test_answer_inline_query_current_offset_callback(self, monkeypatch, bot, caplog):
-        # For now just test that our internals pass the correct data
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            data = request_data.parameters
-            results = data["results"]
-            length = len(results) == 5
-            ids = all(int(res["id"]) == 6 + i for i, res in enumerate(results))
-            next_offset = data["next_offset"] == "2"
-            return length and ids and next_offset
+        message, message2 = await tasks
+        assert message.venue
+        assert message.venue.title == title
+        assert message.venue.address == address
+        assert message.venue.location.latitude == latitude
+        assert message.venue.location.longitude == longitude
+        assert message.venue.foursquare_id == foursquare_id
+        assert message.venue.foursquare_type == foursquare_type
+        assert message.venue.google_place_id is None
+        assert message.venue.google_place_type is None
+        assert message.has_protected_content
 
-        monkeypatch.setattr(bot.request, "post", make_assertion)
+        assert message2.venue
+        assert message2.venue.title == title
+        assert message2.venue.address == address
+        assert message2.venue.location.latitude == latitude
+        assert message2.venue.location.longitude == longitude
+        assert message2.venue.google_place_id == google_place_id
+        assert message2.venue.google_place_type == google_place_type
+        assert message2.venue.foursquare_id is None
+        assert message2.venue.foursquare_type is None
+        assert message2.has_protected_content
 
-        assert await bot.answer_inline_query(
-            1234, results=inline_results_callback, current_offset=1
+    async def test_send_contact(self, bot, chat_id):
+        phone_number = "+11234567890"
+        first_name = "Leandro"
+        last_name = "Toledo"
+        message = await bot.send_contact(
+            chat_id=chat_id,
+            phone_number=phone_number,
+            first_name=first_name,
+            last_name=last_name,
+            protect_content=True,
         )
 
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            data = request_data.parameters
-            results = data["results"]
-            length = results == []
-            next_offset = data["next_offset"] == ""
-            return length and next_offset
+        assert message.contact
+        assert message.contact.phone_number == phone_number
+        assert message.contact.first_name == first_name
+        assert message.contact.last_name == last_name
+        assert message.has_protected_content
 
-        monkeypatch.setattr(bot.request, "post", make_assertion)
+    # TODO: Add bot to group to test polls too
+    @pytest.mark.parametrize(
+        "reply_markup",
+        [
+            None,
+            InlineKeyboardMarkup.from_button(
+                InlineKeyboardButton(text="text", callback_data="data")
+            ),
+            InlineKeyboardMarkup.from_button(
+                InlineKeyboardButton(text="text", callback_data="data")
+            ).to_dict(),
+        ],
+    )
+    async def test_send_and_stop_poll(self, bot, super_group_id, reply_markup):
+        question = "Is this a test?"
+        answers = ["Yes", "No", "Maybe"]
+        explanation = "[Here is a link](https://google.com)"
+        explanation_entities = [
+            MessageEntity(MessageEntity.TEXT_LINK, 0, 14, url="https://google.com")
+        ]
 
-        assert await bot.answer_inline_query(
-            1234, results=inline_results_callback, current_offset=6
+        poll_task = asyncio.create_task(
+            bot.send_poll(
+                chat_id=super_group_id,
+                question=question,
+                options=answers,
+                is_anonymous=False,
+                allows_multiple_answers=True,
+                read_timeout=60,
+                protect_content=True,
+            )
+        )
+        quiz_task = asyncio.create_task(
+            bot.send_poll(
+                chat_id=super_group_id,
+                question=question,
+                options=answers,
+                type=Poll.QUIZ,
+                correct_option_id=2,
+                is_closed=True,
+                explanation=explanation,
+                explanation_parse_mode=ParseMode.MARKDOWN_V2,
+            )
         )
 
-    @pytest.mark.flaky(3, 1)
-    async def test_get_user_profile_photos(self, bot, chat_id):
-        user_profile_photos = await bot.get_user_profile_photos(chat_id)
-
-        assert user_profile_photos.photos[0][0].file_size == 5403
+        message = await poll_task
+        assert message.poll
+        assert message.poll.question == question
+        assert message.poll.options[0].text == answers[0]
+        assert message.poll.options[1].text == answers[1]
+        assert message.poll.options[2].text == answers[2]
+        assert not message.poll.is_anonymous
+        assert message.poll.allows_multiple_answers
+        assert not message.poll.is_closed
+        assert message.poll.type == Poll.REGULAR
+        assert message.has_protected_content
 
-    @pytest.mark.flaky(3, 1)
-    async def test_get_one_user_profile_photo(self, bot, chat_id):
-        user_profile_photos = await bot.get_user_profile_photos(chat_id, offset=0, limit=1)
-        assert user_profile_photos.photos[0][0].file_size == 5403
+        # Since only the poll and not the complete message is returned, we can't check that the
+        # reply_markup is correct. So we just test that sending doesn't give an error.
+        poll = await bot.stop_poll(
+            chat_id=super_group_id,
+            message_id=message.message_id,
+            reply_markup=reply_markup,
+            read_timeout=60,
+        )
+        assert isinstance(poll, Poll)
+        assert poll.is_closed
+        assert poll.options[0].text == answers[0]
+        assert poll.options[0].voter_count == 0
+        assert poll.options[1].text == answers[1]
+        assert poll.options[1].voter_count == 0
+        assert poll.options[2].text == answers[2]
+        assert poll.options[2].voter_count == 0
+        assert poll.question == question
+        assert poll.total_voter_count == 0
 
-    # get_file is tested multiple times in the test_*media* modules.
-    # Here we only test the behaviour for bot apis in local mode
-    async def test_get_file_local_mode(self, bot, monkeypatch):
-        path = str(data_file("game.gif"))
+        message_quiz = await quiz_task
+        assert message_quiz.poll.correct_option_id == 2
+        assert message_quiz.poll.type == Poll.QUIZ
+        assert message_quiz.poll.is_closed
+        assert message_quiz.poll.explanation == "Here is a link"
+        assert message_quiz.poll.explanation_entities == tuple(explanation_entities)
+        assert poll_task.done() and quiz_task.done()
 
-        async def _post(*args, **kwargs):
-            return {
-                "file_id": None,
-                "file_unique_id": None,
-                "file_size": None,
-                "file_path": path,
-            }
+    @pytest.mark.parametrize(
+        ["open_period", "close_date"], [(5, None), (None, True)], ids=["open_period", "close_date"]
+    )
+    async def test_send_open_period(self, bot, super_group_id, open_period, close_date):
+        question = "Is this a test?"
+        answers = ["Yes", "No", "Maybe"]
+        reply_markup = InlineKeyboardMarkup.from_button(
+            InlineKeyboardButton(text="text", callback_data="data")
+        )
 
-        monkeypatch.setattr(bot, "_post", _post)
+        if close_date:
+            close_date = dtm.datetime.utcnow() + dtm.timedelta(seconds=5.05)
 
-        resulting_path = (await bot.get_file("file_id")).file_path
-        assert bot.token not in resulting_path
-        assert resulting_path == path
-        monkeypatch.delattr(bot, "_post")
+        message = await bot.send_poll(
+            chat_id=super_group_id,
+            question=question,
+            options=answers,
+            is_anonymous=False,
+            allows_multiple_answers=True,
+            read_timeout=60,
+            open_period=open_period,
+            close_date=close_date,
+        )
+        await asyncio.sleep(5.1)
+        new_message = await bot.edit_message_reply_markup(
+            chat_id=super_group_id,
+            message_id=message.message_id,
+            reply_markup=reply_markup,
+            read_timeout=60,
+        )
+        assert new_message.poll.id == message.poll.id
+        assert new_message.poll.is_closed
 
-    # TODO: Needs improvement. No feasible way to test until bots can add members.
-    async def test_ban_chat_member(self, monkeypatch, bot):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            data = request_data.json_parameters
-            chat_id = data["chat_id"] == "2"
-            user_id = data["user_id"] == "32"
-            until_date = data.get("until_date", "1577887200") == "1577887200"
-            revoke_msgs = data.get("revoke_messages", "true") == "true"
-            return chat_id and user_id and until_date and revoke_msgs
+    async def test_send_close_date_default_tz(self, tz_bot, super_group_id):
+        question = "Is this a test?"
+        answers = ["Yes", "No", "Maybe"]
+        reply_markup = InlineKeyboardMarkup.from_button(
+            InlineKeyboardButton(text="text", callback_data="data")
+        )
 
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-        until = from_timestamp(1577887200)
+        aware_close_date = dtm.datetime.now(tz=tz_bot.defaults.tzinfo) + dtm.timedelta(seconds=5)
+        close_date = aware_close_date.replace(tzinfo=None)
 
-        assert await bot.ban_chat_member(2, 32)
-        assert await bot.ban_chat_member(2, 32, until_date=until)
-        assert await bot.ban_chat_member(2, 32, until_date=1577887200)
-        assert await bot.ban_chat_member(2, 32, revoke_messages=True)
-        monkeypatch.delattr(bot.request, "post")
+        msg = await tz_bot.send_poll(  # The timezone returned from this is always converted to UTC
+            chat_id=super_group_id,
+            question=question,
+            options=answers,
+            close_date=close_date,
+            read_timeout=60,
+        )
+        msg.poll._unfreeze()
+        # Sometimes there can be a few seconds delay, so don't let the test fail due to that-
+        msg.poll.close_date = msg.poll.close_date.astimezone(aware_close_date.tzinfo)
+        assert abs(msg.poll.close_date - aware_close_date) <= dtm.timedelta(seconds=5)
 
-    async def test_ban_chat_member_default_tz(self, monkeypatch, tz_bot):
-        until = dtm.datetime(2020, 1, 11, 16, 13)
-        until_timestamp = to_timestamp(until, tzinfo=tz_bot.defaults.tzinfo)
+        await asyncio.sleep(5.1)
 
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            data = request_data.parameters
-            chat_id = data["chat_id"] == 2
-            user_id = data["user_id"] == 32
-            until_date = data.get("until_date", until_timestamp) == until_timestamp
-            return chat_id and user_id and until_date
+        new_message = await tz_bot.edit_message_reply_markup(
+            chat_id=super_group_id,
+            message_id=msg.message_id,
+            reply_markup=reply_markup,
+            read_timeout=60,
+        )
+        assert new_message.poll.id == msg.poll.id
+        assert new_message.poll.is_closed
 
-        monkeypatch.setattr(tz_bot.request, "post", make_assertion)
+    async def test_send_poll_explanation_entities(self, bot, chat_id):
+        test_string = "Italic Bold Code"
+        entities = [
+            MessageEntity(MessageEntity.ITALIC, 0, 6),
+            MessageEntity(MessageEntity.ITALIC, 7, 4),
+            MessageEntity(MessageEntity.ITALIC, 12, 4),
+        ]
+        message = await bot.send_poll(
+            chat_id,
+            "question",
+            options=["a", "b"],
+            correct_option_id=0,
+            type=Poll.QUIZ,
+            explanation=test_string,
+            explanation_entities=entities,
+        )
 
-        assert await tz_bot.ban_chat_member(2, 32)
-        assert await tz_bot.ban_chat_member(2, 32, until_date=until)
-        assert await tz_bot.ban_chat_member(2, 32, until_date=until_timestamp)
+        assert message.poll.explanation == test_string
+        assert message.poll.explanation_entities == tuple(entities)
 
-    async def test_ban_chat_sender_chat(self, monkeypatch, bot):
-        # For now, we just test that we pass the correct data to TG
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            data = request_data.parameters
-            chat_id = data["chat_id"] == 2
-            sender_chat_id = data["sender_chat_id"] == 32
-            return chat_id and sender_chat_id
+    @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
+    async def test_send_poll_default_parse_mode(self, default_bot, super_group_id):
+        explanation = "Italic Bold Code"
+        explanation_markdown = "_Italic_ *Bold* `Code`"
+        question = "Is this a test?"
+        answers = ["Yes", "No", "Maybe"]
 
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-        assert await bot.ban_chat_sender_chat(2, 32)
-        monkeypatch.delattr(bot.request, "post")
+        tasks = asyncio.gather(
+            *(
+                default_bot.send_poll(
+                    chat_id=super_group_id,
+                    question=question,
+                    options=answers,
+                    type=Poll.QUIZ,
+                    correct_option_id=2,
+                    is_closed=True,
+                    explanation=explanation_markdown,
+                    **i,
+                )
+                for i in ({}, {"explanation_parse_mode": None}, {"explanation_parse_mode": "HTML"})
+            ),
+        )
+        message1, message2, message3 = await tasks
+        assert message1.poll.explanation == explanation
+        assert message1.poll.explanation_entities == (
+            MessageEntity(MessageEntity.ITALIC, 0, 6),
+            MessageEntity(MessageEntity.BOLD, 7, 4),
+            MessageEntity(MessageEntity.CODE, 12, 4),
+        )
 
-    # TODO: Needs improvement.
-    @pytest.mark.parametrize("only_if_banned", [True, False, None])
-    async def test_unban_chat_member(self, monkeypatch, bot, only_if_banned):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            data = request_data.parameters
-            chat_id = data["chat_id"] == 2
-            user_id = data["user_id"] == 32
-            o_i_b = data.get("only_if_banned", None) == only_if_banned
-            return chat_id and user_id and o_i_b
+        assert message2.poll.explanation == explanation_markdown
+        assert message2.poll.explanation_entities == ()
 
-        monkeypatch.setattr(bot.request, "post", make_assertion)
+        assert message3.poll.explanation == explanation_markdown
+        assert message3.poll.explanation_entities == ()
 
-        assert await bot.unban_chat_member(2, 32, only_if_banned=only_if_banned)
+    @pytest.mark.parametrize(
+        "default_bot,custom",
+        [
+            ({"allow_sending_without_reply": True}, None),
+            ({"allow_sending_without_reply": False}, None),
+            ({"allow_sending_without_reply": False}, True),
+        ],
+        indirect=["default_bot"],
+    )
+    async def test_send_poll_default_allow_sending_without_reply(
+        self, default_bot, chat_id, custom
+    ):
+        question = "Is this a test?"
+        answers = ["Yes", "No", "Maybe"]
+        reply_to_message = await default_bot.send_message(chat_id, "test")
+        await reply_to_message.delete()
+        if custom is not None:
+            message = await default_bot.send_poll(
+                chat_id,
+                question=question,
+                options=answers,
+                allow_sending_without_reply=custom,
+                reply_to_message_id=reply_to_message.message_id,
+            )
+            assert message.reply_to_message is None
+        elif default_bot.defaults.allow_sending_without_reply:
+            message = await default_bot.send_poll(
+                chat_id,
+                question=question,
+                options=answers,
+                reply_to_message_id=reply_to_message.message_id,
+            )
+            assert message.reply_to_message is None
+        else:
+            with pytest.raises(BadRequest, match="message not found"):
+                await default_bot.send_poll(
+                    chat_id,
+                    question=question,
+                    options=answers,
+                    reply_to_message_id=reply_to_message.message_id,
+                )
 
-    async def test_unban_chat_sender_chat(self, monkeypatch, bot):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            data = request_data.json_parameters
-            chat_id = data["chat_id"] == "2"
-            sender_chat_id = data["sender_chat_id"] == "32"
-            return chat_id and sender_chat_id
+    @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
+    async def test_send_poll_default_protect_content(self, chat_id, default_bot):
+        tasks = asyncio.gather(
+            default_bot.send_poll(chat_id, "Test", ["1", "2"]),
+            default_bot.send_poll(chat_id, "test", ["1", "2"], protect_content=False),
+        )
+        protected_poll, unprotect_poll = await tasks
+        assert protected_poll.has_protected_content
+        assert not unprotect_poll.has_protected_content
 
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-        assert await bot.unban_chat_sender_chat(2, 32)
+    @pytest.mark.parametrize("emoji", Dice.ALL_EMOJI + [None])
+    async def test_send_dice(self, bot, chat_id, emoji):
+        message = await bot.send_dice(chat_id, emoji=emoji, protect_content=True)
 
-    async def test_set_chat_permissions(self, monkeypatch, bot, chat_permissions):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            data = request_data.json_parameters
-            chat_id = data["chat_id"] == "2"
-            permissions = data["permissions"] == chat_permissions.to_json()
-            return chat_id and permissions
+        assert message.dice
+        assert message.has_protected_content
+        if emoji is None:
+            assert message.dice.emoji == Dice.DICE
+        else:
+            assert message.dice.emoji == emoji
 
-        monkeypatch.setattr(bot.request, "post", make_assertion)
+    @pytest.mark.parametrize(
+        "default_bot,custom",
+        [
+            ({"allow_sending_without_reply": True}, None),
+            ({"allow_sending_without_reply": False}, None),
+            ({"allow_sending_without_reply": False}, True),
+        ],
+        indirect=["default_bot"],
+    )
+    async def test_send_dice_default_allow_sending_without_reply(
+        self, default_bot, chat_id, custom
+    ):
+        reply_to_message = await default_bot.send_message(chat_id, "test")
+        await reply_to_message.delete()
+        if custom is not None:
+            message = await default_bot.send_dice(
+                chat_id,
+                allow_sending_without_reply=custom,
+                reply_to_message_id=reply_to_message.message_id,
+            )
+            assert message.reply_to_message is None
+        elif default_bot.defaults.allow_sending_without_reply:
+            message = await default_bot.send_dice(
+                chat_id,
+                reply_to_message_id=reply_to_message.message_id,
+            )
+            assert message.reply_to_message is None
+        else:
+            with pytest.raises(BadRequest, match="message not found"):
+                await default_bot.send_dice(
+                    chat_id, reply_to_message_id=reply_to_message.message_id
+                )
 
-        assert await bot.set_chat_permissions(2, chat_permissions)
+    @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
+    async def test_send_dice_default_protect_content(self, chat_id, default_bot):
+        tasks = asyncio.gather(
+            default_bot.send_dice(chat_id), default_bot.send_dice(chat_id, protect_content=False)
+        )
+        protected_dice, unprotected_dice = await tasks
+        assert protected_dice.has_protected_content
+        assert not unprotected_dice.has_protected_content
 
-    async def test_set_chat_administrator_custom_title(self, monkeypatch, bot):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            data = request_data.parameters
-            chat_id = data["chat_id"] == 2
-            user_id = data["user_id"] == 32
-            custom_title = data["custom_title"] == "custom_title"
-            return chat_id and user_id and custom_title
+    @pytest.mark.parametrize("chat_action", list(ChatAction))
+    async def test_send_chat_action(self, bot, chat_id, chat_action):
+        assert await bot.send_chat_action(chat_id, chat_action)
 
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-        assert await bot.set_chat_administrator_custom_title(2, 32, "custom_title")
+    async def test_wrong_chat_action(self, bot, chat_id):
+        with pytest.raises(BadRequest, match="Wrong parameter action"):
+            await bot.send_chat_action(chat_id, "unknown action")
 
-    # TODO: Needs improvement. Need an incoming callbackquery to test
-    async def test_answer_callback_query(self, monkeypatch, bot):
-        # For now just test that our internals pass the correct data
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            return request_data.parameters == {
-                "callback_query_id": 23,
-                "show_alert": True,
-                "url": "no_url",
-                "cache_time": 1,
-                "text": "answer",
-            }
+    async def test_answer_inline_query_current_offset_error(self, bot, inline_results):
+        with pytest.raises(ValueError, match=("`current_offset` and `next_offset`")):
+            await bot.answer_inline_query(
+                1234, results=inline_results, next_offset=42, current_offset=51
+            )
 
-        monkeypatch.setattr(bot.request, "post", make_assertion)
+    async def test_get_user_profile_photos(self, bot, chat_id):
+        user_profile_photos = await bot.get_user_profile_photos(chat_id)
+        assert user_profile_photos.photos[0][0].file_size == 5403
 
-        assert await bot.answer_callback_query(
-            23, text="answer", show_alert=True, url="no_url", cache_time=1
-        )
+    async def test_get_one_user_profile_photo(self, bot, chat_id):
+        user_profile_photos = await bot.get_user_profile_photos(chat_id, offset=0, limit=1)
+        assert user_profile_photos.photos[0][0].file_size == 5403
 
-    @pytest.mark.flaky(3, 1)
     async def test_edit_message_text(self, bot, message):
         message = await bot.edit_message_text(
             text="new_text",
@@ -1601,7 +1945,6 @@ async def test_edit_message_text(self, bot, message):
 
         assert message.text == "new_text"
 
-    @pytest.mark.flaky(3, 1)
     async def test_edit_message_text_entities(self, bot, message):
         test_string = "Italic Bold Code"
         entities = [
@@ -1619,7 +1962,6 @@ async def test_edit_message_text_entities(self, bot, message):
         assert message.text == test_string
         assert message.entities == tuple(entities)
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_edit_message_text_default_parse_mode(self, default_bot, message):
         test_string = "Italic Bold Code"
@@ -1664,7 +2006,6 @@ async def test_edit_message_text_default_parse_mode(self, default_bot, message):
     async def test_edit_message_text_inline(self):
         pass
 
-    @pytest.mark.flaky(3, 1)
     async def test_edit_message_caption(self, bot, media_message):
         message = await bot.edit_message_caption(
             caption="new_caption",
@@ -1674,7 +2015,6 @@ async def test_edit_message_caption(self, bot, media_message):
 
         assert message.caption == "new_caption"
 
-    @pytest.mark.flaky(3, 1)
     async def test_edit_message_caption_entities(self, bot, media_message):
         test_string = "Italic Bold Code"
         entities = [
@@ -1694,7 +2034,6 @@ async def test_edit_message_caption_entities(self, bot, media_message):
 
     # edit_message_media is tested in test_inputmedia
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_edit_message_caption_default_parse_mode(self, default_bot, media_message):
         test_string = "Italic Bold Code"
@@ -1731,7 +2070,6 @@ async def test_edit_message_caption_default_parse_mode(self, default_bot, media_
         assert message.caption == test_markdown_string
         assert message.caption_markdown == escape_markdown(test_markdown_string)
 
-    @pytest.mark.flaky(3, 1)
     async def test_edit_message_caption_with_parse_mode(self, bot, media_message):
         message = await bot.edit_message_caption(
             caption="new *caption*",
@@ -1746,7 +2084,6 @@ async def test_edit_message_caption_with_parse_mode(self, bot, media_message):
     async def test_edit_message_caption_inline(self):
         pass
 
-    @pytest.mark.flaky(3, 1)
     async def test_edit_reply_markup(self, bot, message):
         new_markup = InlineKeyboardMarkup([[InlineKeyboardButton(text="test", callback_data="1")]])
         message = await bot.edit_message_reply_markup(
@@ -1760,7 +2097,6 @@ async def test_edit_reply_markup_inline(self):
         pass
 
     # TODO: Actually send updates to the test bot so this can be tested properly
-    @pytest.mark.flaky(3, 1)
     async def test_get_updates(self, bot):
         await bot.delete_webhook()  # make sure there is no webhook set if webhook tests failed
         updates = await bot.get_updates(timeout=1)
@@ -1806,7 +2142,6 @@ async def post(*args, **kwargs):
             bot.callback_data_cache.clear_callback_data()
             bot.callback_data_cache.clear_callback_queries()
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("use_ip", [True, False])
     # local file path as file_input is tested below in test_set_webhook_params
     @pytest.mark.parametrize("file_input", ["bytes", "file_handle"])
@@ -1844,66 +2179,6 @@ async def test_set_webhook_get_webhook_info_and_delete_webhook(self, bot, use_ip
         assert info.ip_address is None
         assert info.has_custom_certificate is False
 
-    @pytest.mark.parametrize("drop_pending_updates", [True, False])
-    async def test_set_webhook_delete_webhook_drop_pending_updates(
-        self, bot, drop_pending_updates, monkeypatch
-    ):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            data = request_data.parameters
-            return data.get("drop_pending_updates") == drop_pending_updates
-
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-
-        assert await bot.set_webhook("", drop_pending_updates=drop_pending_updates)
-        assert await bot.delete_webhook(drop_pending_updates=drop_pending_updates)
-
-    @pytest.mark.parametrize("local_file", ["str", "Path", False])
-    async def test_set_webhook_params(self, bot, monkeypatch, local_file):
-        # actually making calls to TG is done in
-        # test_set_webhook_get_webhook_info_and_delete_webhook. Sadly secret_token can't be tested
-        # there so we have this function \o/
-        async def make_assertion(*args, **_):
-            kwargs = args[1]
-
-            if local_file is False:
-                cert_assertion = (
-                    kwargs["certificate"].input_file_content
-                    == data_file("sslcert.pem").read_bytes()
-                )
-            else:
-                cert_assertion = data_file("sslcert.pem").as_uri()
-
-            return (
-                kwargs["url"] == "example.com"
-                and cert_assertion
-                and kwargs["max_connections"] == 7
-                and kwargs["allowed_updates"] == ["messages"]
-                and kwargs["ip_address"] == "127.0.0.1"
-                and kwargs["drop_pending_updates"]
-                and kwargs["secret_token"] == "SoSecretToken"
-            )
-
-        monkeypatch.setattr(bot, "_post", make_assertion)
-
-        cert_path = data_file("sslcert.pem")
-        if local_file == "str":
-            certificate = str(cert_path)
-        elif local_file == "Path":
-            certificate = cert_path
-        else:
-            certificate = cert_path.read_bytes()
-
-        assert await bot.set_webhook(
-            "example.com",
-            certificate,
-            7,
-            ["messages"],
-            "127.0.0.1",
-            True,
-            "SoSecretToken",
-        )
-
-    @pytest.mark.flaky(3, 1)
     async def test_leave_chat(self, bot):
         with pytest.raises(BadRequest, match="Chat not found"):
             await bot.leave_chat(-123456)
@@ -1911,15 +2186,12 @@ async def test_leave_chat(self, bot):
         with pytest.raises(NetworkError, match="Chat not found"):
             await bot.leave_chat(-123456)
 
-    @pytest.mark.flaky(3, 1)
     async def test_get_chat(self, bot, super_group_id):
         chat = await bot.get_chat(super_group_id)
-
         assert chat.type == "supergroup"
         assert chat.title == f">>> telegram.Bot(test) @{bot.username}"
         assert chat.id == int(super_group_id)
 
-    @pytest.mark.flaky(3, 1)
     async def test_get_chat_administrators(self, bot, channel_id):
         admins = await bot.get_chat_administrators(channel_id)
         assert isinstance(admins, tuple)
@@ -1927,13 +2199,11 @@ async def test_get_chat_administrators(self, bot, channel_id):
         for a in admins:
             assert a.status in ("administrator", "creator")
 
-    @pytest.mark.flaky(3, 1)
     async def test_get_chat_member_count(self, bot, channel_id):
         count = await bot.get_chat_member_count(channel_id)
         assert isinstance(count, int)
         assert count > 3
 
-    @pytest.mark.flaky(3, 1)
     async def test_get_chat_member(self, bot, channel_id, chat_id):
         chat_member = await bot.get_chat_member(channel_id, chat_id)
 
@@ -1949,7 +2219,6 @@ async def test_set_chat_sticker_set(self):
     async def test_delete_chat_sticker_set(self):
         pass
 
-    @pytest.mark.flaky(3, 1)
     async def test_send_game(self, bot, chat_id):
         game_short_name = "test_game"
         message = await bot.send_game(chat_id, game_short_name, protect_content=True)
@@ -1964,7 +2233,6 @@ async def test_send_game(self, bot, chat_id):
         assert message.game.photo[0].file_size in [851, 4928, 850]
         assert message.has_protected_content
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize(
         "default_bot,custom",
         [
@@ -2001,7 +2269,6 @@ async def test_send_game_default_allow_sending_without_reply(
                     chat_id, game_short_name, reply_to_message_id=reply_to_message.message_id
                 )
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize(
         "default_bot,val",
         [({"protect_content": True}, True), ({"protect_content": False}, None)],
@@ -2104,56 +2371,6 @@ async def test_get_game_high_scores(self, bot, chat_id):
 
     # send_invoice and create_invoice_link is tested in test_invoice
 
-    # TODO: Needs improvement. Need incoming shipping queries to test
-    async def test_answer_shipping_query_ok(self, monkeypatch, bot):
-        # For now just test that our internals pass the correct data
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            return request_data.parameters == {
-                "shipping_query_id": 1,
-                "ok": True,
-                "shipping_options": [
-                    {"title": "option1", "prices": [{"label": "price", "amount": 100}], "id": 1}
-                ],
-            }
-
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-        shipping_options = ShippingOption(1, "option1", [LabeledPrice("price", 100)])
-        assert await bot.answer_shipping_query(1, True, shipping_options=[shipping_options])
-
-    async def test_answer_shipping_query_error_message(self, monkeypatch, bot):
-        # For now just test that our internals pass the correct data
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            return request_data.parameters == {
-                "shipping_query_id": 1,
-                "error_message": "Not enough fish",
-                "ok": False,
-            }
-
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-        assert await bot.answer_shipping_query(1, False, error_message="Not enough fish")
-
-    # TODO: Needs improvement. Need incoming pre checkout queries to test
-    async def test_answer_pre_checkout_query_ok(self, monkeypatch, bot):
-        # For now just test that our internals pass the correct data
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            return request_data.parameters == {"pre_checkout_query_id": 1, "ok": True}
-
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-        assert await bot.answer_pre_checkout_query(1, True)
-
-    async def test_answer_pre_checkout_query_error_message(self, monkeypatch, bot):
-        # For now just test that our internals pass the correct data
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            return request_data.parameters == {
-                "pre_checkout_query_id": 1,
-                "error_message": "Not enough fish",
-                "ok": False,
-            }
-
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-        assert await bot.answer_pre_checkout_query(1, False, error_message="Not enough fish")
-
-    @pytest.mark.flaky(3, 1)
     async def test_restrict_chat_member(self, bot, channel_id, chat_permissions):
         # TODO: Add bot to supergroup so this can be tested properly
         with pytest.raises(BadRequest, match="Method is available only for supergroups"):
@@ -2161,26 +2378,6 @@ async def test_restrict_chat_member(self, bot, channel_id, chat_permissions):
                 channel_id, 95205500, chat_permissions, until_date=dtm.datetime.utcnow()
             )
 
-    async def test_restrict_chat_member_default_tz(
-        self, monkeypatch, tz_bot, channel_id, chat_permissions
-    ):
-        until = dtm.datetime(2020, 1, 11, 16, 13)
-        until_timestamp = to_timestamp(until, tzinfo=tz_bot.defaults.tzinfo)
-
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            return request_data.parameters.get("until_date", until_timestamp) == until_timestamp
-
-        monkeypatch.setattr(tz_bot.request, "post", make_assertion)
-
-        assert await tz_bot.restrict_chat_member(channel_id, 95205500, chat_permissions)
-        assert await tz_bot.restrict_chat_member(
-            channel_id, 95205500, chat_permissions, until_date=until
-        )
-        assert await tz_bot.restrict_chat_member(
-            channel_id, 95205500, chat_permissions, until_date=until_timestamp
-        )
-
-    @pytest.mark.flaky(3, 1)
     async def test_promote_chat_member(self, bot, channel_id, monkeypatch):
         # TODO: Add bot to supergroup so this can be tested properly / give bot perms
         with pytest.raises(BadRequest, match="Not enough rights"):
@@ -2239,14 +2436,12 @@ async def make_assertion(*args, **_):
             can_manage_topics=12,
         )
 
-    @pytest.mark.flaky(3, 1)
     async def test_export_chat_invite_link(self, bot, channel_id):
         # Each link is unique apparently
         invite_link = await bot.export_chat_invite_link(channel_id)
         assert isinstance(invite_link, str)
         assert invite_link != ""
 
-    @pytest.mark.flaky(3, 1)
     async def test_edit_revoke_chat_invite_link_passing_link_objects(self, bot, channel_id):
         invite_link = await bot.create_chat_invite_link(chat_id=channel_id)
         assert invite_link.name is None
@@ -2264,7 +2459,6 @@ async def test_edit_revoke_chat_invite_link_passing_link_objects(self, bot, chan
         assert revoked_link.is_revoked is True
         assert revoked_link.name == "some_name"
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("creates_join_request", [True, False])
     @pytest.mark.parametrize("name", [None, "name"])
     async def test_create_chat_invite_link_basics(
@@ -2287,7 +2481,7 @@ async def test_create_chat_invite_link_basics(
         )
         assert revoked_link.is_revoked
 
-    @pytest.mark.flaky(3, 1)
+    @pytest.mark.skipif(not TEST_WITH_OPT_DEPS, reason="requires pytz")
     @pytest.mark.parametrize("datetime", argvalues=[True, False], ids=["datetime", "integer"])
     async def test_advanced_chat_invite_links(self, bot, channel_id, datetime):
         # we are testing this all in one function in order to save api calls
@@ -2295,7 +2489,7 @@ async def test_advanced_chat_invite_links(self, bot, channel_id, datetime):
         add_seconds = dtm.timedelta(0, 70)
         time_in_future = timestamp + add_seconds
         expire_time = time_in_future if datetime else to_timestamp(time_in_future)
-        aware_time_in_future = self.localize(time_in_future, UTC)
+        aware_time_in_future = UTC.localize(time_in_future)
 
         invite_link = await bot.create_chat_invite_link(
             channel_id, expire_date=expire_time, member_limit=10
@@ -2308,7 +2502,7 @@ async def test_advanced_chat_invite_links(self, bot, channel_id, datetime):
         add_seconds = dtm.timedelta(0, 80)
         time_in_future = timestamp + add_seconds
         expire_time = time_in_future if datetime else to_timestamp(time_in_future)
-        aware_time_in_future = self.localize(time_in_future, UTC)
+        aware_time_in_future = UTC.localize(time_in_future)
 
         edited_invite_link = await bot.edit_chat_invite_link(
             channel_id,
@@ -2342,7 +2536,6 @@ async def test_advanced_chat_invite_links(self, bot, channel_id, datetime):
         assert revoked_invite_link.invite_link == invite_link.invite_link
         assert revoked_invite_link.is_revoked
 
-    @pytest.mark.flaky(3, 1)
     async def test_advanced_chat_invite_links_default_tzinfo(self, tz_bot, channel_id):
         # we are testing this all in one function in order to save api calls
         add_seconds = dtm.timedelta(0, 70)
@@ -2391,7 +2584,6 @@ async def test_advanced_chat_invite_links_default_tzinfo(self, tz_bot, channel_i
         assert revoked_invite_link.invite_link == invite_link.invite_link
         assert revoked_invite_link.is_revoked
 
-    @pytest.mark.flaky(3, 1)
     async def test_approve_chat_join_request(self, bot, chat_id, channel_id):
         # TODO: Need incoming join request to properly test
         # Since we can't create join requests on the fly, we just tests the call to TG
@@ -2399,7 +2591,6 @@ async def test_approve_chat_join_request(self, bot, chat_id, channel_id):
         with pytest.raises(BadRequest, match="User_already_participant"):
             await bot.approve_chat_join_request(chat_id=channel_id, user_id=chat_id)
 
-    @pytest.mark.flaky(3, 1)
     async def test_decline_chat_join_request(self, bot, chat_id, channel_id):
         # TODO: Need incoming join request to properly test
         # Since we can't create join requests on the fly, we just tests the call to TG
@@ -2407,101 +2598,68 @@ async def test_decline_chat_join_request(self, bot, chat_id, channel_id):
         #
         # The error message Hide_requester_missing started showing up instead of
         # User_already_participant. Don't know why …
-        with pytest.raises(BadRequest, match="User_already_participant|Hide_requester_missing"):
-            await bot.decline_chat_join_request(chat_id=channel_id, user_id=chat_id)
-
-    @pytest.mark.flaky(3, 1)
-    async def test_set_chat_photo(self, bot, channel_id):
-        async def func():
-            assert await bot.set_chat_photo(channel_id, f)
-
-        with data_file("telegram_test_channel.jpg").open("rb") as f:
-            await expect_bad_request(
-                func, "Type of file mismatch", "Telegram did not accept the file."
-            )
-
-    @pytest.mark.parametrize("local_mode", [True, False])
-    async def test_set_chat_photo_local_files(self, monkeypatch, bot, chat_id, local_mode):
-        try:
-            bot._local_mode = local_mode
-            # For just test that the correct paths are passed as we have no local bot API set up
-            test_flag = False
-            file = data_file("telegram.jpg")
-            expected = file.as_uri()
+        with pytest.raises(BadRequest, match="User_already_participant|Hide_requester_missing"):
+            await bot.decline_chat_join_request(chat_id=channel_id, user_id=chat_id)
 
-            async def make_assertion(_, data, *args, **kwargs):
-                nonlocal test_flag
-                if local_mode:
-                    test_flag = data.get("photo") == expected
-                else:
-                    test_flag = isinstance(data.get("photo"), InputFile)
+    async def test_set_chat_photo(self, bot, channel_id):
+        async def func():
+            assert await bot.set_chat_photo(channel_id, f)
 
-            monkeypatch.setattr(bot, "_post", make_assertion)
-            await bot.set_chat_photo(chat_id, file)
-            assert test_flag
-        finally:
-            bot._local_mode = False
+        with data_file("telegram_test_channel.jpg").open("rb") as f:
+            await expect_bad_request(
+                func, "Type of file mismatch", "Telegram did not accept the file."
+            )
 
-    @pytest.mark.flaky(3, 1)
     async def test_delete_chat_photo(self, bot, channel_id):
         async def func():
             assert await bot.delete_chat_photo(channel_id)
 
         await expect_bad_request(func, "Chat_not_modified", "Chat photo was not set.")
 
-    @pytest.mark.flaky(3, 1)
     async def test_set_chat_title(self, bot, channel_id):
         assert await bot.set_chat_title(channel_id, ">>> telegram.Bot() - Tests")
 
-    @pytest.mark.flaky(3, 1)
     async def test_set_chat_description(self, bot, channel_id):
         assert await bot.set_chat_description(channel_id, "Time: " + str(time.time()))
 
-    @pytest.mark.flaky(3, 1)
     async def test_pin_and_unpin_message(self, bot, super_group_id):
-        message1 = await bot.send_message(super_group_id, text="test_pin_message_1")
-        message2 = await bot.send_message(super_group_id, text="test_pin_message_2")
-        message3 = await bot.send_message(super_group_id, text="test_pin_message_3")
-
-        assert await bot.pin_chat_message(
-            chat_id=super_group_id,
-            message_id=message1.message_id,
-            disable_notification=True,
-            read_timeout=10,
-        )
-        await asyncio.sleep(1)
-
-        await bot.pin_chat_message(
-            chat_id=super_group_id,
-            message_id=message2.message_id,
-            disable_notification=True,
-            read_timeout=10,
-        )
-        await bot.pin_chat_message(
-            chat_id=super_group_id,
-            message_id=message3.message_id,
-            disable_notification=True,
-            read_timeout=10,
-        )
-        await asyncio.sleep(1)
-
-        chat = await bot.get_chat(super_group_id)
-        assert chat.pinned_message == message3
-
-        assert await bot.unpin_chat_message(
-            super_group_id,
-            message_id=message2.message_id,
-            read_timeout=10,
-        )
-        assert await bot.unpin_chat_message(
-            super_group_id,
-            read_timeout=10,
-        )
-
-        assert await bot.unpin_all_chat_messages(
-            super_group_id,
-            read_timeout=10,
+        messages = []  # contains the Messages we sent
+        pinned_messages_tasks = set()  # contains the asyncio.Tasks that pin the messages
+
+        # Let's send 3 messages so we can pin them
+        awaitables = {bot.send_message(super_group_id, f"test_pin_message_{i}") for i in range(3)}
+
+        # We will pin the messages immediately after sending them
+        for sending_msg in asyncio.as_completed(awaitables):  # as_completed sends the messages
+            msg = await sending_msg
+            coro = bot.pin_chat_message(super_group_id, msg.message_id, True, read_timeout=10)
+            pinned_messages_tasks.add(asyncio.create_task(coro))  # start pinning the message
+            messages.append(msg)
+
+        assert len(messages) == 3  # Check if we sent 3 messages
+
+        assert all([await i for i in pinned_messages_tasks])  # Check if we pinned 3 messages
+        assert all([i.done() for i in pinned_messages_tasks])  # Check if all tasks are done
+
+        chat = await bot.get_chat(super_group_id)  # get the chat to check the pinned message
+        assert chat.pinned_message in messages
+
+        # Determine which message is not the most recently pinned
+        for old_pin_msg in messages:
+            if chat.pinned_message != old_pin_msg:
+                break
+
+        # Test unpinning our messages
+        tasks = asyncio.gather(
+            bot.unpin_chat_message(  # unpins any message except the most recent
+                chat_id=super_group_id,  # because we don't want to accidentally unpin the same msg
+                message_id=old_pin_msg.message_id,  # twice
+                read_timeout=10,
+            ),
+            bot.unpin_chat_message(chat_id=super_group_id, read_timeout=10),  # unpins most recent
         )
+        assert all(await tasks)
+        assert await bot.unpin_all_chat_messages(super_group_id, read_timeout=10)
 
     # get_sticker_set, upload_sticker_file, create_new_sticker_set, add_sticker_to_set,
     # set_sticker_position_in_set, delete_sticker_from_set and get_custom_emoji_stickers
@@ -2510,53 +2668,6 @@ async def test_pin_and_unpin_message(self, bot, super_group_id):
     # get_forum_topic_icon_stickers, edit_forum_topic, etc...
     # are tested in the test_forum module.
 
-    async def test_timeout_propagation_explicit(self, monkeypatch, bot, chat_id):
-        # Use BaseException that's not a subclass of Exception such that
-        # OkException should not be caught anywhere
-        class OkException(BaseException):
-            pass
-
-        timeout = 42
-
-        async def do_request(*args, **kwargs):
-            obj = kwargs.get("read_timeout")
-            if obj == timeout:
-                raise OkException
-
-            return 200, b'{"ok": true, "result": []}'
-
-        monkeypatch.setattr(bot.request, "do_request", do_request)
-
-        # Test file uploading
-        with pytest.raises(OkException):
-            await bot.send_photo(
-                chat_id, data_file("telegram.jpg").open("rb"), read_timeout=timeout
-            )
-
-        # Test JSON submission
-        with pytest.raises(OkException):
-            await bot.get_chat_administrators(chat_id, read_timeout=timeout)
-
-    async def test_timeout_propagation_implicit(self, monkeypatch, bot, chat_id):
-        # Use BaseException that's not a subclass of Exception such that
-        # OkException should not be caught anywhere
-        class OkException(BaseException):
-            pass
-
-        async def do_request(*args, **kwargs):
-            obj = kwargs.get("write_timeout")
-            if obj == 20:
-                raise OkException
-
-            return 200, b'{"ok": true, "result": []}'
-
-        monkeypatch.setattr(bot.request, "do_request", do_request)
-
-        # Test file uploading
-        with pytest.raises(OkException):
-            await bot.send_photo(chat_id, data_file("telegram.jpg").open("rb"))
-
-    @pytest.mark.flaky(3, 1)
     async def test_send_message_entities(self, bot, chat_id):
         test_string = "Italic Bold Code Spoiler"
         entities = [
@@ -2569,34 +2680,37 @@ async def test_send_message_entities(self, bot, chat_id):
         assert message.text == test_string
         assert message.entities == tuple(entities)
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_send_message_default_parse_mode(self, default_bot, chat_id):
         test_string = "Italic Bold Code"
         test_markdown_string = "_Italic_ *Bold* `Code`"
 
-        message = await default_bot.send_message(chat_id, test_markdown_string)
-        assert message.text_markdown == test_markdown_string
-        assert message.text == test_string
+        tasks = asyncio.gather(
+            *(
+                default_bot.send_message(chat_id, test_markdown_string, **i)
+                for i in ({}, {"parse_mode": None}, {"parse_mode": "HTML"})
+            )
+        )
+        msg1, msg2, msg3 = await tasks
+        assert msg1.text_markdown == test_markdown_string
+        assert msg1.text == test_string
 
-        message = await default_bot.send_message(chat_id, test_markdown_string, parse_mode=None)
-        assert message.text == test_markdown_string
-        assert message.text_markdown == escape_markdown(test_markdown_string)
+        assert msg2.text == test_markdown_string
+        assert msg2.text_markdown == escape_markdown(test_markdown_string)
 
-        message = await default_bot.send_message(chat_id, test_markdown_string, parse_mode="HTML")
-        assert message.text == test_markdown_string
-        assert message.text_markdown == escape_markdown(test_markdown_string)
+        assert msg3.text == test_markdown_string
+        assert msg3.text_markdown == escape_markdown(test_markdown_string)
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
     async def test_send_message_default_protect_content(self, default_bot, chat_id):
-        to_check = await default_bot.send_message(chat_id, "test")
+        tasks = asyncio.gather(
+            default_bot.send_message(chat_id, "test"),
+            default_bot.send_message(chat_id, "test", protect_content=False),
+        )
+        to_check, no_protect = await tasks
         assert to_check.has_protected_content
-
-        no_protect = await default_bot.send_message(chat_id, "test", protect_content=False)
         assert not no_protect.has_protected_content
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize(
         "default_bot,custom",
         [
@@ -2630,17 +2744,16 @@ async def test_send_message_default_allow_sending_without_reply(
                     chat_id, "test", reply_to_message_id=reply_to_message.message_id
                 )
 
-    @pytest.mark.asyncio
     async def test_get_set_my_default_administrator_rights(self, bot):
         # Test that my default administrator rights for group are as all False
-        await bot.set_my_default_administrator_rights()
+        assert await bot.set_my_default_administrator_rights()  # clear any set rights
         my_admin_rights_grp = await bot.get_my_default_administrator_rights()
         assert isinstance(my_admin_rights_grp, ChatAdministratorRights)
         assert all(not getattr(my_admin_rights_grp, at) for at in my_admin_rights_grp.__slots__)
 
         # Test setting my default admin rights for channel
         my_rights = ChatAdministratorRights.all_rights()
-        await bot.set_my_default_administrator_rights(my_rights, for_channels=True)
+        assert await bot.set_my_default_administrator_rights(my_rights, for_channels=True)
         my_admin_rights_ch = await bot.get_my_default_administrator_rights(for_channels=True)
         assert my_admin_rights_ch.can_invite_users is my_rights.can_invite_users
         # tg bug? is_anonymous is False despite setting it True for channels:
@@ -2656,7 +2769,6 @@ async def test_get_set_my_default_administrator_rights(self, bot):
         assert my_admin_rights_ch.can_pin_messages is None  # Not returned for channels
         assert my_admin_rights_ch.can_manage_topics is None  # Not returned for channels
 
-    @pytest.mark.asyncio
     async def test_get_set_chat_menu_button(self, bot, chat_id):
         # Test our chat menu button is commands-
         menu_button = await bot.get_chat_menu_button()
@@ -2666,21 +2778,20 @@ async def test_get_set_chat_menu_button(self, bot, chat_id):
 
         # Test setting our chat menu button to Webapp.
         my_menu = MenuButtonWebApp("click me!", WebAppInfo("https://telegram.org/"))
-        await bot.set_chat_menu_button(chat_id=chat_id, menu_button=my_menu)
+        assert await bot.set_chat_menu_button(chat_id=chat_id, menu_button=my_menu)
         menu_button = await bot.get_chat_menu_button(chat_id)
         assert isinstance(menu_button, MenuButtonWebApp)
         assert menu_button.type == MenuButtonType.WEB_APP
         assert menu_button.text == my_menu.text
         assert menu_button.web_app.url == my_menu.web_app.url
 
-        await bot.set_chat_menu_button(chat_id=chat_id, menu_button=MenuButtonDefault())
+        assert await bot.set_chat_menu_button(chat_id=chat_id, menu_button=MenuButtonDefault())
         menu_button = await bot.get_chat_menu_button(chat_id=chat_id)
         assert isinstance(menu_button, MenuButtonDefault)
 
-    @pytest.mark.flaky(3, 1)
     async def test_set_and_get_my_commands(self, bot):
         commands = [BotCommand("cmd1", "descr1"), ["cmd2", "descr2"]]
-        await bot.set_my_commands([])
+        assert await bot.set_my_commands([])
         assert await bot.get_my_commands() == ()
         assert await bot.set_my_commands(commands)
 
@@ -2688,7 +2799,6 @@ async def test_set_and_get_my_commands(self, bot):
             assert bc.command == f"cmd{i+1}"
             assert bc.description == f"descr{i+1}"
 
-    @pytest.mark.flaky(3, 1)
     async def test_get_set_delete_my_commands_with_scope(self, bot, super_group_id, chat_id):
         group_cmds = [BotCommand("group_cmd", "visible to this supergroup only")]
         private_cmds = [BotCommand("private_cmd", "visible to this private chat only")]
@@ -2696,26 +2806,32 @@ async def test_get_set_delete_my_commands_with_scope(self, bot, super_group_id,
         private_scope = BotCommandScopeChat(chat_id)
 
         # Set supergroup command list with lang code and check if the same can be returned from api
-        await bot.set_my_commands(group_cmds, scope=group_scope, language_code="en")
+        assert await bot.set_my_commands(group_cmds, scope=group_scope, language_code="en")
         gotten_group_cmds = await bot.get_my_commands(scope=group_scope, language_code="en")
 
         assert len(gotten_group_cmds) == len(group_cmds)
         assert gotten_group_cmds[0].command == group_cmds[0].command
 
         # Set private command list and check if same can be returned from the api
-        await bot.set_my_commands(private_cmds, scope=private_scope)
+        assert await bot.set_my_commands(private_cmds, scope=private_scope)
         gotten_private_cmd = await bot.get_my_commands(scope=private_scope)
 
         assert len(gotten_private_cmd) == len(private_cmds)
         assert gotten_private_cmd[0].command == private_cmds[0].command
 
         # Delete command list from that supergroup and private chat-
-        await bot.delete_my_commands(private_scope)
-        await bot.delete_my_commands(group_scope, "en")
+        tasks = asyncio.gather(
+            bot.delete_my_commands(private_scope),
+            bot.delete_my_commands(group_scope, "en"),
+        )
+        assert all(await tasks)
 
         # Check if its been deleted-
-        deleted_priv_cmds = await bot.get_my_commands(scope=private_scope)
-        deleted_grp_cmds = await bot.get_my_commands(scope=group_scope, language_code="en")
+        tasks = asyncio.gather(
+            bot.get_my_commands(private_scope),
+            bot.get_my_commands(group_scope, "en"),
+        )
+        deleted_priv_cmds, deleted_grp_cmds = await tasks
 
         assert len(deleted_grp_cmds) == 0 == len(group_cmds) - 1
         assert len(deleted_priv_cmds) == 0 == len(private_cmds) - 1
@@ -2723,73 +2839,6 @@ async def test_get_set_delete_my_commands_with_scope(self, bot, super_group_id,
         await bot.delete_my_commands()  # Delete commands from default scope
         assert len(await bot.get_my_commands()) == 0
 
-    async def test_log_out(self, monkeypatch, bot):
-        # We don't actually make a request as to not break the test setup
-        async def assertion(url, request_data: RequestData, *args, **kwargs):
-            return request_data.json_parameters == {} and url.split("/")[-1] == "logOut"
-
-        monkeypatch.setattr(bot.request, "post", assertion)
-
-        assert await bot.log_out()
-
-    async def test_close(self, monkeypatch, bot):
-        # We don't actually make a request as to not break the test setup
-        async def assertion(url, request_data: RequestData, *args, **kwargs):
-            return request_data.json_parameters == {} and url.split("/")[-1] == "close"
-
-        monkeypatch.setattr(bot.request, "post", assertion)
-
-        assert await bot.close()
-
-    @pytest.mark.flaky(3, 1)
-    @pytest.mark.parametrize("json_keyboard", [True, False])
-    @pytest.mark.parametrize("caption", ["<b>Test</b>", "", None])
-    async def test_copy_message(
-        self, monkeypatch, bot, chat_id, media_message, json_keyboard, caption
-    ):
-        keyboard = InlineKeyboardMarkup(
-            [[InlineKeyboardButton(text="test", callback_data="test2")]]
-        )
-
-        async def post(url, request_data: RequestData, *args, **kwargs):
-            data = request_data.parameters
-            if not all(
-                [
-                    data["chat_id"] == chat_id,
-                    data["from_chat_id"] == chat_id,
-                    data["message_id"] == media_message.message_id,
-                    data.get("caption") == caption,
-                    data["parse_mode"] == ParseMode.HTML,
-                    data["reply_to_message_id"] == media_message.message_id,
-                    data["reply_markup"] == keyboard.to_json()
-                    if json_keyboard
-                    else keyboard.to_dict(),
-                    data["disable_notification"] is True,
-                    data["caption_entities"]
-                    == [MessageEntity(MessageEntity.BOLD, 0, 4).to_dict()],
-                    data["protect_content"] is True,
-                    data["message_thread_id"] == 1,
-                ]
-            ):
-                pytest.fail("I got wrong parameters in post")
-            return data
-
-        monkeypatch.setattr(bot.request, "post", post)
-        await bot.copy_message(
-            chat_id,
-            from_chat_id=chat_id,
-            message_id=media_message.message_id,
-            caption=caption,
-            caption_entities=[MessageEntity(MessageEntity.BOLD, 0, 4)],
-            parse_mode=ParseMode.HTML,
-            reply_to_message_id=media_message.message_id,
-            reply_markup=keyboard.to_json() if json_keyboard else keyboard,
-            disable_notification=True,
-            protect_content=True,
-            message_thread_id=1,
-        )
-
-    @pytest.mark.flaky(3, 1)
     async def test_copy_message_without_reply(self, bot, chat_id, media_message):
         keyboard = InlineKeyboardMarkup(
             [[InlineKeyboardButton(text="test", callback_data="test2")]]
@@ -2815,7 +2864,6 @@ async def test_copy_message_without_reply(self, bot, chat_id, media_message):
         assert len(message.caption_entities) == 1
         assert message.reply_markup == keyboard
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize(
         "default_bot",
         [
@@ -2946,62 +2994,6 @@ async def test_replace_callback_data_copy_message(self, cdc_bot, chat_id):
             bot.callback_data_cache.clear_callback_data()
             bot.callback_data_cache.clear_callback_queries()
 
-    # TODO: Needs improvement. We need incoming inline query to test answer.
-    async def test_replace_callback_data_answer_inline_query(self, monkeypatch, cdc_bot, chat_id):
-        bot = cdc_bot
-
-        # For now just test that our internals pass the correct data
-        async def make_assertion(
-            endpoint,
-            data=None,
-            *args,
-            **kwargs,
-        ):
-            inline_keyboard = data["results"][0]["reply_markup"].inline_keyboard
-            assertion_1 = inline_keyboard[0][1] == no_replace_button
-            assertion_2 = inline_keyboard[0][0] != replace_button
-            keyboard, button = (
-                inline_keyboard[0][0].callback_data[:32],
-                inline_keyboard[0][0].callback_data[32:],
-            )
-            assertion_3 = (
-                bot.callback_data_cache._keyboard_data[keyboard].button_data[button]
-                == "replace_test"
-            )
-            assertion_4 = data["results"][1].reply_markup is None
-            return assertion_1 and assertion_2 and assertion_3 and assertion_4
-
-        try:
-            replace_button = InlineKeyboardButton(text="replace", callback_data="replace_test")
-            no_replace_button = InlineKeyboardButton(
-                text="no_replace", url="http://python-telegram-bot.org/"
-            )
-            reply_markup = InlineKeyboardMarkup.from_row(
-                [
-                    replace_button,
-                    no_replace_button,
-                ]
-            )
-
-            bot.username  # call this here so `bot.get_me()` won't be called after mocking
-            monkeypatch.setattr(bot, "_post", make_assertion)
-            results = [
-                InlineQueryResultArticle(
-                    "11", "first", InputTextMessageContent("first"), reply_markup=reply_markup
-                ),
-                InlineQueryResultVoice(
-                    "22",
-                    "https://python-telegram-bot.org/static/testfiles/telegram.ogg",
-                    title="second",
-                ),
-            ]
-
-            assert await bot.answer_inline_query(chat_id, results=results)
-
-        finally:
-            bot.callback_data_cache.clear_callback_data()
-            bot.callback_data_cache.clear_callback_queries()
-
     async def test_get_chat_arbitrary_callback_data(self, super_group_id, cdc_bot):
         bot = cdc_bot
 
@@ -3186,48 +3178,3 @@ async def post(*args, **kwargs):
         finally:
             bot.callback_data_cache.clear_callback_data()
             bot.callback_data_cache.clear_callback_queries()
-
-    @bot_methods()
-    def test_camel_case_aliases(self, bot_class, bot_method_name, bot_method):
-        camel_case_name = to_camel_case(bot_method_name)
-        camel_case_function = getattr(bot_class, camel_case_name, False)
-        assert camel_case_function is not False, f"{camel_case_name} not found"
-        assert camel_case_function is bot_method, f"{camel_case_name} is not {bot_method}"
-
-    @bot_methods()
-    def test_coroutine_functions(self, bot_class, bot_method_name, bot_method):
-        """Check that all bot methods are defined as async def  ..."""
-        # not islower() skips the camelcase aliases
-        if not bot_method_name.islower():
-            return
-        # unfortunately `inspect.iscoroutinefunction` doesn't do the trick directly,
-        # as the @_log decorator interferes
-        source = "".join(inspect.getsourcelines(bot_method)[0])
-        assert (
-            f"async def {bot_method_name}" in source
-        ), f"{bot_method_name} should be a coroutine function"
-
-    @bot_methods()
-    def test_api_kwargs_and_timeouts_present(self, bot_class, bot_method_name, bot_method):
-        """Check that all bot methods have `api_kwargs` and timeout params."""
-        param_names = inspect.signature(bot_method).parameters.keys()
-        assert (
-            "pool_timeout" in param_names
-        ), f"{bot_method_name} is missing the parameter `pool_timeout`"
-        assert (
-            "read_timeout" in param_names
-        ), f"{bot_method_name} is missing the parameter `read_timeout`"
-        assert (
-            "connect_timeout" in param_names
-        ), f"{bot_method_name} is missing the parameter `connect_timeout`"
-        assert (
-            "write_timeout" in param_names
-        ), f"{bot_method_name} is missing the parameter `write_timeout`"
-        assert (
-            "api_kwargs" in param_names
-        ), f"{bot_method_name} is missing the parameter `api_kwargs`"
-
-        if bot_class is ExtBot and bot_method_name.replace("_", "").lower() != "getupdates":
-            assert (
-                "rate_limit_args" in param_names
-            ), f"{bot_method_name} of ExtBot is missing the parameter `rate_limit_args`"
diff --git a/tests/test_botcommand.py b/tests/test_botcommand.py
index a9fbbb9c5bd..f9965e4eeac 100644
--- a/tests/test_botcommand.py
+++ b/tests/test_botcommand.py
@@ -22,12 +22,12 @@
 from telegram import BotCommand, Dice
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def bot_command():
     return BotCommand(command="start", description="A command")
 
 
-class TestBotCommand:
+class TestBotCommandNoReq:
     command = "start"
     description = "A command"
 
diff --git a/tests/test_botcommandscope.py b/tests/test_botcommandscope.py
index 2b074b2a197..3ff14783872 100644
--- a/tests/test_botcommandscope.py
+++ b/tests/test_botcommandscope.py
@@ -33,7 +33,7 @@
 )
 
 
-@pytest.fixture(scope="class", params=["str", "int"])
+@pytest.fixture(scope="module", params=["str", "int"])
 def chat_id(request):
     if request.param == "str":
         return "@supergroupusername"
@@ -57,7 +57,7 @@ def scope_type(request):
 
 
 @pytest.fixture(
-    scope="class",
+    scope="module",
     params=[
         BotCommandScopeDefault,
         BotCommandScopeAllPrivateChats,
@@ -82,7 +82,7 @@ def scope_class(request):
 
 
 @pytest.fixture(
-    scope="class",
+    scope="module",
     params=[
         (BotCommandScopeDefault, BotCommandScope.DEFAULT),
         (BotCommandScopeAllPrivateChats, BotCommandScope.ALL_PRIVATE_CHATS),
@@ -106,7 +106,7 @@ def scope_class_and_type(request):
     return request.param
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def bot_command_scope(scope_class_and_type, chat_id):
     # we use de_json here so that we don't have to worry about which class needs which arguments
     return scope_class_and_type[0].de_json(
@@ -115,7 +115,7 @@ def bot_command_scope(scope_class_and_type, chat_id):
 
 
 # All the scope types are very similar, so we test everything via parametrization
-class TestBotCommandScope:
+class TestBotCommandScopeNoReq:
     def test_slot_behaviour(self, bot_command_scope, mro_slots):
         for attr in bot_command_scope.__slots__:
             assert getattr(bot_command_scope, attr, "err") != "err", f"got extra slot '{attr}'"
diff --git a/tests/test_callbackdatacache.py b/tests/test_callbackdatacache.py
index 2c2872ec017..3afed54bbfa 100644
--- a/tests/test_callbackdatacache.py
+++ b/tests/test_callbackdatacache.py
@@ -16,7 +16,6 @@
 #
 # You should have received a copy of the GNU Lesser Public License
 # along with this program.  If not, see [http://www.gnu.org/licenses/].
-import os
 import time
 from copy import deepcopy
 from datetime import datetime
@@ -28,7 +27,7 @@
 from telegram._utils.datetime import UTC
 from telegram.ext import ExtBot
 from telegram.ext._callbackdatacache import CallbackDataCache, InvalidCallbackData, _KeyboardData
-from tests.auxil.object_conversions import env_var_2_bool
+from tests.conftest import TEST_WITH_OPT_DEPS
 
 
 @pytest.fixture(scope="function")
@@ -36,9 +35,6 @@ def callback_data_cache(bot):
     return CallbackDataCache(bot)
 
 
-TEST_WITH_OPT_DEPS = env_var_2_bool(os.getenv("TEST_WITH_OPT_DEPS", True))
-
-
 @pytest.mark.skipif(
     TEST_WITH_OPT_DEPS,
     reason="Only relevant if the optional dependency is not installed",
diff --git a/tests/test_callbackquery.py b/tests/test_callbackquery.py
index 13b6133e298..2135f7569c2 100644
--- a/tests/test_callbackquery.py
+++ b/tests/test_callbackquery.py
@@ -32,23 +32,23 @@
 @pytest.fixture(scope="function", params=["message", "inline"])
 def callback_query(bot, request):
     cbq = CallbackQuery(
-        TestCallbackQuery.id_,
-        TestCallbackQuery.from_user,
-        TestCallbackQuery.chat_instance,
-        data=TestCallbackQuery.data,
-        game_short_name=TestCallbackQuery.game_short_name,
+        Space.id_,
+        Space.from_user,
+        Space.chat_instance,
+        data=Space.data,
+        game_short_name=Space.game_short_name,
     )
     cbq.set_bot(bot)
     cbq._unfreeze()
     if request.param == "message":
-        cbq.message = TestCallbackQuery.message
+        cbq.message = Space.message
         cbq.message.set_bot(bot)
     else:
-        cbq.inline_message_id = TestCallbackQuery.inline_message_id
+        cbq.inline_message_id = Space.inline_message_id
     return cbq
 
 
-class TestCallbackQuery:
+class Space:
     id_ = "id"
     from_user = User(1, "test_user", False)
     chat_instance = "chat_instance"
@@ -57,6 +57,8 @@ class TestCallbackQuery:
     inline_message_id = "inline_message_id"
     game_short_name = "the_game"
 
+
+class TestCallbackQueryNoReq:
     @staticmethod
     def skip_params(callback_query: CallbackQuery):
         if callback_query.inline_message_id:
@@ -88,24 +90,24 @@ def test_slot_behaviour(self, callback_query, mro_slots):
 
     def test_de_json(self, bot):
         json_dict = {
-            "id": self.id_,
-            "from": self.from_user.to_dict(),
-            "chat_instance": self.chat_instance,
-            "message": self.message.to_dict(),
-            "data": self.data,
-            "inline_message_id": self.inline_message_id,
-            "game_short_name": self.game_short_name,
+            "id": Space.id_,
+            "from": Space.from_user.to_dict(),
+            "chat_instance": Space.chat_instance,
+            "message": Space.message.to_dict(),
+            "data": Space.data,
+            "inline_message_id": Space.inline_message_id,
+            "game_short_name": Space.game_short_name,
         }
         callback_query = CallbackQuery.de_json(json_dict, bot)
         assert callback_query.api_kwargs == {}
 
-        assert callback_query.id == self.id_
-        assert callback_query.from_user == self.from_user
-        assert callback_query.chat_instance == self.chat_instance
-        assert callback_query.message == self.message
-        assert callback_query.data == self.data
-        assert callback_query.inline_message_id == self.inline_message_id
-        assert callback_query.game_short_name == self.game_short_name
+        assert callback_query.id == Space.id_
+        assert callback_query.from_user == Space.from_user
+        assert callback_query.chat_instance == Space.chat_instance
+        assert callback_query.message == Space.message
+        assert callback_query.data == Space.data
+        assert callback_query.inline_message_id == Space.inline_message_id
+        assert callback_query.game_short_name == Space.game_short_name
 
     def test_to_dict(self, callback_query):
         callback_query_dict = callback_query.to_dict()
@@ -449,11 +451,11 @@ async def make_assertion(*args, **kwargs):
         assert await callback_query.copy_message(1)
 
     def test_equality(self):
-        a = CallbackQuery(self.id_, self.from_user, "chat")
-        b = CallbackQuery(self.id_, self.from_user, "chat")
-        c = CallbackQuery(self.id_, None, "")
+        a = CallbackQuery(Space.id_, Space.from_user, "chat")
+        b = CallbackQuery(Space.id_, Space.from_user, "chat")
+        c = CallbackQuery(Space.id_, None, "")
         d = CallbackQuery("", None, "chat")
-        e = Audio(self.id_, "unique_id", 1)
+        e = Audio(Space.id_, "unique_id", 1)
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_chat.py b/tests/test_chat.py
index a8418ec9f6b..1f78a4ad4f4 100644
--- a/tests/test_chat.py
+++ b/tests/test_chat.py
@@ -29,35 +29,35 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def chat(bot):
     chat = Chat(
-        TestChat.id_,
-        title=TestChat.title,
-        type=TestChat.type_,
-        username=TestChat.username,
-        sticker_set_name=TestChat.sticker_set_name,
-        can_set_sticker_set=TestChat.can_set_sticker_set,
-        permissions=TestChat.permissions,
-        slow_mode_delay=TestChat.slow_mode_delay,
-        bio=TestChat.bio,
-        linked_chat_id=TestChat.linked_chat_id,
-        location=TestChat.location,
+        Space.id_,
+        title=Space.title,
+        type=Space.type_,
+        username=Space.username,
+        sticker_set_name=Space.sticker_set_name,
+        can_set_sticker_set=Space.can_set_sticker_set,
+        permissions=Space.permissions,
+        slow_mode_delay=Space.slow_mode_delay,
+        bio=Space.bio,
+        linked_chat_id=Space.linked_chat_id,
+        location=Space.location,
         has_private_forwards=True,
         has_protected_content=True,
         join_to_send_messages=True,
         join_by_request=True,
         has_restricted_voice_and_video_messages=True,
         is_forum=True,
-        active_usernames=TestChat.active_usernames,
-        emoji_status_custom_emoji_id=TestChat.emoji_status_custom_emoji_id,
+        active_usernames=Space.active_usernames,
+        emoji_status_custom_emoji_id=Space.emoji_status_custom_emoji_id,
     )
     chat.set_bot(bot)
     chat._unfreeze()
     return chat
 
 
-class TestChat:
+class Space:
     id_ = -28767330
     title = "ToledosPalaceBot - Group"
     type_ = "group"
@@ -83,6 +83,8 @@ class TestChat:
     active_usernames = ["These", "Are", "Usernames!"]
     emoji_status_custom_emoji_id = "VeryUniqueCustomEmojiID"
 
+
+class TestChatNoReq:
     def test_slot_behaviour(self, chat, mro_slots):
         for attr in chat.__slots__:
             assert getattr(chat, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -90,57 +92,57 @@ def test_slot_behaviour(self, chat, mro_slots):
 
     def test_de_json(self, bot):
         json_dict = {
-            "id": self.id_,
-            "title": self.title,
-            "type": self.type_,
-            "username": self.username,
-            "all_members_are_administrators": self.all_members_are_administrators,
-            "sticker_set_name": self.sticker_set_name,
-            "can_set_sticker_set": self.can_set_sticker_set,
-            "permissions": self.permissions.to_dict(),
-            "slow_mode_delay": self.slow_mode_delay,
-            "bio": self.bio,
-            "has_protected_content": self.has_protected_content,
-            "has_private_forwards": self.has_private_forwards,
-            "linked_chat_id": self.linked_chat_id,
-            "location": self.location.to_dict(),
-            "join_to_send_messages": self.join_to_send_messages,
-            "join_by_request": self.join_by_request,
+            "id": Space.id_,
+            "title": Space.title,
+            "type": Space.type_,
+            "username": Space.username,
+            "all_members_are_administrators": Space.all_members_are_administrators,
+            "sticker_set_name": Space.sticker_set_name,
+            "can_set_sticker_set": Space.can_set_sticker_set,
+            "permissions": Space.permissions.to_dict(),
+            "slow_mode_delay": Space.slow_mode_delay,
+            "bio": Space.bio,
+            "has_protected_content": Space.has_protected_content,
+            "has_private_forwards": Space.has_private_forwards,
+            "linked_chat_id": Space.linked_chat_id,
+            "location": Space.location.to_dict(),
+            "join_to_send_messages": Space.join_to_send_messages,
+            "join_by_request": Space.join_by_request,
             "has_restricted_voice_and_video_messages": (
-                self.has_restricted_voice_and_video_messages
+                Space.has_restricted_voice_and_video_messages
             ),
-            "is_forum": self.is_forum,
-            "active_usernames": self.active_usernames,
-            "emoji_status_custom_emoji_id": self.emoji_status_custom_emoji_id,
+            "is_forum": Space.is_forum,
+            "active_usernames": Space.active_usernames,
+            "emoji_status_custom_emoji_id": Space.emoji_status_custom_emoji_id,
         }
         chat = Chat.de_json(json_dict, bot)
 
-        assert chat.id == self.id_
-        assert chat.title == self.title
-        assert chat.type == self.type_
-        assert chat.username == self.username
-        assert chat.sticker_set_name == self.sticker_set_name
-        assert chat.can_set_sticker_set == self.can_set_sticker_set
-        assert chat.permissions == self.permissions
-        assert chat.slow_mode_delay == self.slow_mode_delay
-        assert chat.bio == self.bio
-        assert chat.has_protected_content == self.has_protected_content
-        assert chat.has_private_forwards == self.has_private_forwards
-        assert chat.linked_chat_id == self.linked_chat_id
-        assert chat.location.location == self.location.location
-        assert chat.location.address == self.location.address
-        assert chat.join_to_send_messages == self.join_to_send_messages
-        assert chat.join_by_request == self.join_by_request
+        assert chat.id == Space.id_
+        assert chat.title == Space.title
+        assert chat.type == Space.type_
+        assert chat.username == Space.username
+        assert chat.sticker_set_name == Space.sticker_set_name
+        assert chat.can_set_sticker_set == Space.can_set_sticker_set
+        assert chat.permissions == Space.permissions
+        assert chat.slow_mode_delay == Space.slow_mode_delay
+        assert chat.bio == Space.bio
+        assert chat.has_protected_content == Space.has_protected_content
+        assert chat.has_private_forwards == Space.has_private_forwards
+        assert chat.linked_chat_id == Space.linked_chat_id
+        assert chat.location.location == Space.location.location
+        assert chat.location.address == Space.location.address
+        assert chat.join_to_send_messages == Space.join_to_send_messages
+        assert chat.join_by_request == Space.join_by_request
         assert (
             chat.has_restricted_voice_and_video_messages
-            == self.has_restricted_voice_and_video_messages
+            == Space.has_restricted_voice_and_video_messages
         )
         assert chat.api_kwargs == {
-            "all_members_are_administrators": self.all_members_are_administrators
+            "all_members_are_administrators": Space.all_members_are_administrators
         }
-        assert chat.is_forum == self.is_forum
-        assert chat.active_usernames == tuple(self.active_usernames)
-        assert chat.emoji_status_custom_emoji_id == self.emoji_status_custom_emoji_id
+        assert chat.is_forum == Space.is_forum
+        assert chat.active_usernames == tuple(Space.active_usernames)
+        assert chat.emoji_status_custom_emoji_id == Space.emoji_status_custom_emoji_id
 
     def test_to_dict(self, chat):
         chat_dict = chat.to_dict()
@@ -403,7 +405,7 @@ async def make_assertion(*_, **kwargs):
     async def test_set_permissions(self, monkeypatch, chat):
         async def make_assertion(*_, **kwargs):
             chat_id = kwargs["chat_id"] == chat.id
-            permissions = kwargs["permissions"] == self.permissions
+            permissions = kwargs["permissions"] == Space.permissions
             return chat_id and permissions
 
         assert check_shortcut_signature(
@@ -415,7 +417,7 @@ async def make_assertion(*_, **kwargs):
         assert await check_defaults_handling(chat.set_permissions, chat.get_bot())
 
         monkeypatch.setattr(chat.get_bot(), "set_chat_permissions", make_assertion)
-        assert await chat.set_permissions(permissions=self.permissions)
+        assert await chat.set_permissions(permissions=Space.permissions)
 
     async def test_set_administrator_custom_title(self, monkeypatch, chat):
         async def make_assertion(*_, **kwargs):
@@ -1126,11 +1128,11 @@ def test_mention_markdown_v2(self):
             chat.mention_markdown_v2()
 
     def test_equality(self):
-        a = Chat(self.id_, self.title, self.type_)
-        b = Chat(self.id_, self.title, self.type_)
-        c = Chat(self.id_, "", "")
-        d = Chat(0, self.title, self.type_)
-        e = User(self.id_, "", False)
+        a = Chat(Space.id_, Space.title, Space.type_)
+        b = Chat(Space.id_, Space.title, Space.type_)
+        c = Chat(Space.id_, "", "")
+        d = Chat(0, Space.title, Space.type_)
+        e = User(Space.id_, "", False)
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_chatadministratorrights.py b/tests/test_chatadministratorrights.py
index 83826f74bac..100291f4a74 100644
--- a/tests/test_chatadministratorrights.py
+++ b/tests/test_chatadministratorrights.py
@@ -21,7 +21,7 @@
 from telegram import ChatAdministratorRights
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def chat_admin_rights():
     return ChatAdministratorRights(
         can_change_info=True,
@@ -39,7 +39,7 @@ def chat_admin_rights():
     )
 
 
-class TestChatAdministratorRights:
+class TestChatAdministratorRightsNoReq:
     def test_slot_behaviour(self, chat_admin_rights, mro_slots):
         inst = chat_admin_rights
         for attr in inst.__slots__:
diff --git a/tests/test_chatinvitelink.py b/tests/test_chatinvitelink.py
index 1f940d39ab5..b4868c6c80e 100644
--- a/tests/test_chatinvitelink.py
+++ b/tests/test_chatinvitelink.py
@@ -24,28 +24,27 @@
 from telegram._utils.datetime import to_timestamp
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def creator():
     return User(1, "First name", False)
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def invite_link(creator):
     return ChatInviteLink(
-        TestChatInviteLink.link,
+        Space.link,
         creator,
-        TestChatInviteLink.creates_join_request,
-        TestChatInviteLink.primary,
-        TestChatInviteLink.revoked,
-        expire_date=TestChatInviteLink.expire_date,
-        member_limit=TestChatInviteLink.member_limit,
-        name=TestChatInviteLink.name,
-        pending_join_request_count=TestChatInviteLink.pending_join_request_count,
+        Space.creates_join_request,
+        Space.primary,
+        Space.revoked,
+        expire_date=Space.expire_date,
+        member_limit=Space.member_limit,
+        name=Space.name,
+        pending_join_request_count=Space.pending_join_request_count,
     )
 
 
-class TestChatInviteLink:
-
+class Space:
     link = "thisialink"
     creates_join_request = False
     primary = True
@@ -55,6 +54,8 @@ class TestChatInviteLink:
     name = "LinkName"
     pending_join_request_count = 42
 
+
+class TestChatInviteLinkNoReq:
     def test_slot_behaviour(self, mro_slots, invite_link):
         for attr in invite_link.__slots__:
             assert getattr(invite_link, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -62,48 +63,48 @@ def test_slot_behaviour(self, mro_slots, invite_link):
 
     def test_de_json_required_args(self, bot, creator):
         json_dict = {
-            "invite_link": self.link,
+            "invite_link": Space.link,
             "creator": creator.to_dict(),
-            "creates_join_request": self.creates_join_request,
-            "is_primary": self.primary,
-            "is_revoked": self.revoked,
+            "creates_join_request": Space.creates_join_request,
+            "is_primary": Space.primary,
+            "is_revoked": Space.revoked,
         }
 
         invite_link = ChatInviteLink.de_json(json_dict, bot)
         assert invite_link.api_kwargs == {}
 
-        assert invite_link.invite_link == self.link
+        assert invite_link.invite_link == Space.link
         assert invite_link.creator == creator
-        assert invite_link.creates_join_request == self.creates_join_request
-        assert invite_link.is_primary == self.primary
-        assert invite_link.is_revoked == self.revoked
+        assert invite_link.creates_join_request == Space.creates_join_request
+        assert invite_link.is_primary == Space.primary
+        assert invite_link.is_revoked == Space.revoked
 
     def test_de_json_all_args(self, bot, creator):
         json_dict = {
-            "invite_link": self.link,
+            "invite_link": Space.link,
             "creator": creator.to_dict(),
-            "creates_join_request": self.creates_join_request,
-            "is_primary": self.primary,
-            "is_revoked": self.revoked,
-            "expire_date": to_timestamp(self.expire_date),
-            "member_limit": self.member_limit,
-            "name": self.name,
-            "pending_join_request_count": str(self.pending_join_request_count),
+            "creates_join_request": Space.creates_join_request,
+            "is_primary": Space.primary,
+            "is_revoked": Space.revoked,
+            "expire_date": to_timestamp(Space.expire_date),
+            "member_limit": Space.member_limit,
+            "name": Space.name,
+            "pending_join_request_count": str(Space.pending_join_request_count),
         }
 
         invite_link = ChatInviteLink.de_json(json_dict, bot)
         assert invite_link.api_kwargs == {}
 
-        assert invite_link.invite_link == self.link
+        assert invite_link.invite_link == Space.link
         assert invite_link.creator == creator
-        assert invite_link.creates_join_request == self.creates_join_request
-        assert invite_link.is_primary == self.primary
-        assert invite_link.is_revoked == self.revoked
-        assert abs(invite_link.expire_date - self.expire_date) < datetime.timedelta(seconds=1)
-        assert to_timestamp(invite_link.expire_date) == to_timestamp(self.expire_date)
-        assert invite_link.member_limit == self.member_limit
-        assert invite_link.name == self.name
-        assert invite_link.pending_join_request_count == self.pending_join_request_count
+        assert invite_link.creates_join_request == Space.creates_join_request
+        assert invite_link.is_primary == Space.primary
+        assert invite_link.is_revoked == Space.revoked
+        assert abs(invite_link.expire_date - Space.expire_date) < datetime.timedelta(seconds=1)
+        assert to_timestamp(invite_link.expire_date) == to_timestamp(Space.expire_date)
+        assert invite_link.member_limit == Space.member_limit
+        assert invite_link.name == Space.name
+        assert invite_link.pending_join_request_count == Space.pending_join_request_count
 
     def test_to_dict(self, invite_link):
         invite_link_dict = invite_link.to_dict()
@@ -111,12 +112,12 @@ def test_to_dict(self, invite_link):
         assert invite_link_dict["creator"] == invite_link.creator.to_dict()
         assert invite_link_dict["invite_link"] == invite_link.invite_link
         assert invite_link_dict["creates_join_request"] == invite_link.creates_join_request
-        assert invite_link_dict["is_primary"] == self.primary
-        assert invite_link_dict["is_revoked"] == self.revoked
-        assert invite_link_dict["expire_date"] == to_timestamp(self.expire_date)
-        assert invite_link_dict["member_limit"] == self.member_limit
-        assert invite_link_dict["name"] == self.name
-        assert invite_link_dict["pending_join_request_count"] == self.pending_join_request_count
+        assert invite_link_dict["is_primary"] == Space.primary
+        assert invite_link_dict["is_revoked"] == Space.revoked
+        assert invite_link_dict["expire_date"] == to_timestamp(Space.expire_date)
+        assert invite_link_dict["member_limit"] == Space.member_limit
+        assert invite_link_dict["name"] == Space.name
+        assert invite_link_dict["pending_join_request_count"] == Space.pending_join_request_count
 
     def test_equality(self):
         a = ChatInviteLink("link", User(1, "", False), True, True, True)
diff --git a/tests/test_chatjoinrequest.py b/tests/test_chatjoinrequest.py
index b01d6f48758..d7718ef4500 100644
--- a/tests/test_chatjoinrequest.py
+++ b/tests/test_chatjoinrequest.py
@@ -29,25 +29,25 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def time():
     return datetime.datetime.now(tz=UTC)
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def chat_join_request(bot, time):
     cjr = ChatJoinRequest(
-        chat=TestChatJoinRequest.chat,
-        from_user=TestChatJoinRequest.from_user,
+        chat=Space.chat,
+        from_user=Space.from_user,
         date=time,
-        bio=TestChatJoinRequest.bio,
-        invite_link=TestChatJoinRequest.invite_link,
+        bio=Space.bio,
+        invite_link=Space.invite_link,
     )
     cjr.set_bot(bot)
     return cjr
 
 
-class TestChatJoinRequest:
+class Space:
     chat = Chat(1, Chat.SUPERGROUP)
     from_user = User(2, "first_name", False)
     bio = "bio"
@@ -60,6 +60,8 @@ class TestChatJoinRequest:
         is_primary=False,
     )
 
+
+class TestChatJoinRequestNoReq:
     def test_slot_behaviour(self, chat_join_request, mro_slots):
         inst = chat_join_request
         for attr in inst.__slots__:
@@ -68,28 +70,28 @@ def test_slot_behaviour(self, chat_join_request, mro_slots):
 
     def test_de_json(self, bot, time):
         json_dict = {
-            "chat": self.chat.to_dict(),
-            "from": self.from_user.to_dict(),
+            "chat": Space.chat.to_dict(),
+            "from": Space.from_user.to_dict(),
             "date": to_timestamp(time),
         }
         chat_join_request = ChatJoinRequest.de_json(json_dict, bot)
         assert chat_join_request.api_kwargs == {}
 
-        assert chat_join_request.chat == self.chat
-        assert chat_join_request.from_user == self.from_user
+        assert chat_join_request.chat == Space.chat
+        assert chat_join_request.from_user == Space.from_user
         assert abs(chat_join_request.date - time) < datetime.timedelta(seconds=1)
         assert to_timestamp(chat_join_request.date) == to_timestamp(time)
 
-        json_dict.update({"bio": self.bio, "invite_link": self.invite_link.to_dict()})
+        json_dict.update({"bio": Space.bio, "invite_link": Space.invite_link.to_dict()})
         chat_join_request = ChatJoinRequest.de_json(json_dict, bot)
         assert chat_join_request.api_kwargs == {}
 
-        assert chat_join_request.chat == self.chat
-        assert chat_join_request.from_user == self.from_user
+        assert chat_join_request.chat == Space.chat
+        assert chat_join_request.from_user == Space.from_user
         assert abs(chat_join_request.date - time) < datetime.timedelta(seconds=1)
         assert to_timestamp(chat_join_request.date) == to_timestamp(time)
-        assert chat_join_request.bio == self.bio
-        assert chat_join_request.invite_link == self.invite_link
+        assert chat_join_request.bio == Space.bio
+        assert chat_join_request.invite_link == Space.invite_link
 
     def test_to_dict(self, chat_join_request, time):
         chat_join_request_dict = chat_join_request.to_dict()
@@ -103,10 +105,10 @@ def test_to_dict(self, chat_join_request, time):
 
     def test_equality(self, chat_join_request, time):
         a = chat_join_request
-        b = ChatJoinRequest(self.chat, self.from_user, time)
-        c = ChatJoinRequest(self.chat, self.from_user, time, bio="bio")
-        d = ChatJoinRequest(self.chat, self.from_user, time + datetime.timedelta(1))
-        e = ChatJoinRequest(self.chat, User(-1, "last_name", True), time)
+        b = ChatJoinRequest(Space.chat, Space.from_user, time)
+        c = ChatJoinRequest(Space.chat, Space.from_user, time, bio="bio")
+        d = ChatJoinRequest(Space.chat, Space.from_user, time + datetime.timedelta(1))
+        e = ChatJoinRequest(Space.chat, User(-1, "last_name", True), time)
         f = User(456, "", False)
 
         assert a == b
diff --git a/tests/test_chatlocation.py b/tests/test_chatlocation.py
index ea9bd3bc6a8..91f6ff5c7bc 100644
--- a/tests/test_chatlocation.py
+++ b/tests/test_chatlocation.py
@@ -22,15 +22,17 @@
 from telegram import ChatLocation, Location, User
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def chat_location(bot):
-    return ChatLocation(TestChatLocation.location, TestChatLocation.address)
+    return ChatLocation(Space.location, Space.address)
 
 
-class TestChatLocation:
+class Space:
     location = Location(123, 456)
     address = "The Shire"
 
+
+class TestChatLocationNoReq:
     def test_slot_behaviour(self, chat_location, mro_slots):
         inst = chat_location
         for attr in inst.__slots__:
@@ -39,14 +41,14 @@ def test_slot_behaviour(self, chat_location, mro_slots):
 
     def test_de_json(self, bot):
         json_dict = {
-            "location": self.location.to_dict(),
-            "address": self.address,
+            "location": Space.location.to_dict(),
+            "address": Space.address,
         }
         chat_location = ChatLocation.de_json(json_dict, bot)
         assert chat_location.api_kwargs == {}
 
-        assert chat_location.location == self.location
-        assert chat_location.address == self.address
+        assert chat_location.location == Space.location
+        assert chat_location.address == Space.address
 
     def test_to_dict(self, chat_location):
         chat_location_dict = chat_location.to_dict()
@@ -57,9 +59,9 @@ def test_to_dict(self, chat_location):
 
     def test_equality(self, chat_location):
         a = chat_location
-        b = ChatLocation(self.location, self.address)
-        c = ChatLocation(self.location, "Mordor")
-        d = ChatLocation(Location(456, 132), self.address)
+        b = ChatLocation(Space.location, Space.address)
+        c = ChatLocation(Space.location, "Mordor")
+        d = ChatLocation(Location(456, 132), Space.address)
         e = User(456, "", False)
 
         assert a == b
diff --git a/tests/test_chatmember.py b/tests/test_chatmember.py
index ab7e7d23da2..83a103db015 100644
--- a/tests/test_chatmember.py
+++ b/tests/test_chatmember.py
@@ -175,7 +175,7 @@ def chat_member_type(request):
     ],
     indirect=True,
 )
-class TestChatMemberTypes:
+class TestChatMemberTypesNoReq:
     def test_slot_behaviour(self, chat_member_type, mro_slots):
         inst = chat_member_type
         for attr in inst.__slots__:
diff --git a/tests/test_chatmemberupdated.py b/tests/test_chatmemberupdated.py
index 29cc9e5824f..724b51ec9d8 100644
--- a/tests/test_chatmemberupdated.py
+++ b/tests/test_chatmemberupdated.py
@@ -34,26 +34,26 @@
 from telegram._utils.datetime import UTC, to_timestamp
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def user():
     return User(1, "First name", False)
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def chat():
     return Chat(1, Chat.SUPERGROUP, "Chat")
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def old_chat_member(user):
-    return ChatMember(user, TestChatMemberUpdated.old_status)
+    return ChatMember(user, Space.old_status)
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def new_chat_member(user):
     return ChatMemberAdministrator(
         user,
-        TestChatMemberUpdated.new_status,
+        Space.new_status,
         True,
         True,
         True,
@@ -66,25 +66,27 @@ def new_chat_member(user):
     )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def time():
     return datetime.datetime.now(tz=UTC)
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def invite_link(user):
     return ChatInviteLink("link", user, False, True, True)
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def chat_member_updated(user, chat, old_chat_member, new_chat_member, invite_link, time):
     return ChatMemberUpdated(chat, user, time, old_chat_member, new_chat_member, invite_link)
 
 
-class TestChatMemberUpdated:
+class Space:
     old_status = ChatMember.MEMBER
     new_status = ChatMember.ADMINISTRATOR
 
+
+class TestChatMemberUpdatedNoReq:
     def test_slot_behaviour(self, mro_slots, chat_member_updated):
         action = chat_member_updated
         for attr in action.__slots__:
diff --git a/tests/test_chatpermissions.py b/tests/test_chatpermissions.py
index 5498bae24ca..66ccf95c5f3 100644
--- a/tests/test_chatpermissions.py
+++ b/tests/test_chatpermissions.py
@@ -22,7 +22,7 @@
 from telegram import ChatPermissions, User
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def chat_permissions():
     return ChatPermissions(
         can_send_messages=True,
@@ -37,7 +37,7 @@ def chat_permissions():
     )
 
 
-class TestChatPermissions:
+class Space:
     can_send_messages = True
     can_send_media_messages = True
     can_send_polls = True
@@ -48,6 +48,8 @@ class TestChatPermissions:
     can_pin_messages = None
     can_manage_topics = None
 
+
+class TestChatPermissionsNoReq:
     def test_slot_behaviour(self, chat_permissions, mro_slots):
         inst = chat_permissions
         for attr in inst.__slots__:
@@ -56,28 +58,28 @@ def test_slot_behaviour(self, chat_permissions, mro_slots):
 
     def test_de_json(self, bot):
         json_dict = {
-            "can_send_messages": self.can_send_messages,
-            "can_send_media_messages": self.can_send_media_messages,
-            "can_send_polls": self.can_send_polls,
-            "can_send_other_messages": self.can_send_other_messages,
-            "can_add_web_page_previews": self.can_add_web_page_previews,
-            "can_change_info": self.can_change_info,
-            "can_invite_users": self.can_invite_users,
-            "can_pin_messages": self.can_pin_messages,
-            "can_manage_topics": self.can_manage_topics,
+            "can_send_messages": Space.can_send_messages,
+            "can_send_media_messages": Space.can_send_media_messages,
+            "can_send_polls": Space.can_send_polls,
+            "can_send_other_messages": Space.can_send_other_messages,
+            "can_add_web_page_previews": Space.can_add_web_page_previews,
+            "can_change_info": Space.can_change_info,
+            "can_invite_users": Space.can_invite_users,
+            "can_pin_messages": Space.can_pin_messages,
+            "can_manage_topics": Space.can_manage_topics,
         }
         permissions = ChatPermissions.de_json(json_dict, bot)
         assert permissions.api_kwargs == {}
 
-        assert permissions.can_send_messages == self.can_send_messages
-        assert permissions.can_send_media_messages == self.can_send_media_messages
-        assert permissions.can_send_polls == self.can_send_polls
-        assert permissions.can_send_other_messages == self.can_send_other_messages
-        assert permissions.can_add_web_page_previews == self.can_add_web_page_previews
-        assert permissions.can_change_info == self.can_change_info
-        assert permissions.can_invite_users == self.can_invite_users
-        assert permissions.can_pin_messages == self.can_pin_messages
-        assert permissions.can_manage_topics == self.can_manage_topics
+        assert permissions.can_send_messages == Space.can_send_messages
+        assert permissions.can_send_media_messages == Space.can_send_media_messages
+        assert permissions.can_send_polls == Space.can_send_polls
+        assert permissions.can_send_other_messages == Space.can_send_other_messages
+        assert permissions.can_add_web_page_previews == Space.can_add_web_page_previews
+        assert permissions.can_change_info == Space.can_change_info
+        assert permissions.can_invite_users == Space.can_invite_users
+        assert permissions.can_pin_messages == Space.can_pin_messages
+        assert permissions.can_manage_topics == Space.can_manage_topics
 
     def test_to_dict(self, chat_permissions):
         permissions_dict = chat_permissions.to_dict()
diff --git a/tests/test_chatphoto.py b/tests/test_chatphoto.py
index 902402bfe69..a7c8320448b 100644
--- a/tests/test_chatphoto.py
+++ b/tests/test_chatphoto.py
@@ -17,6 +17,7 @@
 # You should have received a copy of the GNU Lesser Public License
 # along with this program.  If not, see [http://www.gnu.org/licenses/].
 
+import asyncio
 import os
 from pathlib import Path
 
@@ -35,12 +36,11 @@
 
 @pytest.fixture(scope="function")
 def chatphoto_file():
-    f = data_file("telegram.jpg").open("rb")
-    yield f
-    f.close()
+    with data_file("telegram.jpg").open("rb") as f:
+        yield f
 
 
-@pytest.fixture(scope="function")
+@pytest.fixture(scope="module")
 async def chat_photo(bot, super_group_id):
     async def func():
         return (await bot.get_chat(super_group_id, read_timeout=50)).photo
@@ -50,53 +50,20 @@ async def func():
     )
 
 
-class TestChatPhoto:
+class Space:
     chatphoto_small_file_id = "smallCgADAQADngIAAuyVeEez0xRovKi9VAI"
     chatphoto_big_file_id = "bigCgADAQADngIAAuyVeEez0xRovKi9VAI"
     chatphoto_small_file_unique_id = "smalladc3145fd2e84d95b64d68eaa22aa33e"
     chatphoto_big_file_unique_id = "bigadc3145fd2e84d95b64d68eaa22aa33e"
     chatphoto_file_url = "https://python-telegram-bot.org/static/testfiles/telegram.jpg"
 
+
+class TestChatPhotoNoReq:
     def test_slot_behaviour(self, chat_photo, mro_slots):
         for attr in chat_photo.__slots__:
             assert getattr(chat_photo, attr, "err") != "err", f"got extra slot '{attr}'"
         assert len(mro_slots(chat_photo)) == len(set(mro_slots(chat_photo))), "duplicate slot"
 
-    @pytest.mark.flaky(3, 1)
-    async def test_send_all_args(
-        self, bot, super_group_id, chatphoto_file, chat_photo, thumb_file
-    ):
-        async def func():
-            assert await bot.set_chat_photo(super_group_id, chatphoto_file)
-
-        await expect_bad_request(
-            func, "Type of file mismatch", "Telegram did not accept the file."
-        )
-
-    @pytest.mark.flaky(3, 1)
-    async def test_get_and_download(self, bot, chat_photo):
-        jpg_file = Path("telegram.jpg")
-        if jpg_file.is_file():
-            jpg_file.unlink()
-
-        new_file = await bot.get_file(chat_photo.small_file_id)
-
-        assert new_file.file_unique_id == chat_photo.small_file_unique_id
-        assert new_file.file_path.startswith("https://")
-
-        await new_file.download_to_drive(jpg_file)
-
-        assert jpg_file.is_file()
-
-        new_file = await bot.get_file(chat_photo.big_file_id)
-
-        assert new_file.file_unique_id == chat_photo.big_file_unique_id
-        assert new_file.file_path.startswith("https://")
-
-        await new_file.download_to_drive(jpg_file)
-
-        assert jpg_file.is_file()
-
     async def test_send_with_chat_photo(self, monkeypatch, bot, super_group_id, chat_photo):
         async def make_assertion(url, request_data: RequestData, *args, **kwargs):
             return request_data.parameters["photo"] == chat_photo.to_dict()
@@ -107,17 +74,17 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs):
 
     def test_de_json(self, bot, chat_photo):
         json_dict = {
-            "small_file_id": self.chatphoto_small_file_id,
-            "big_file_id": self.chatphoto_big_file_id,
-            "small_file_unique_id": self.chatphoto_small_file_unique_id,
-            "big_file_unique_id": self.chatphoto_big_file_unique_id,
+            "small_file_id": Space.chatphoto_small_file_id,
+            "big_file_id": Space.chatphoto_big_file_id,
+            "small_file_unique_id": Space.chatphoto_small_file_unique_id,
+            "big_file_unique_id": Space.chatphoto_big_file_unique_id,
         }
         chat_photo = ChatPhoto.de_json(json_dict, bot)
         assert chat_photo.api_kwargs == {}
-        assert chat_photo.small_file_id == self.chatphoto_small_file_id
-        assert chat_photo.big_file_id == self.chatphoto_big_file_id
-        assert chat_photo.small_file_unique_id == self.chatphoto_small_file_unique_id
-        assert chat_photo.big_file_unique_id == self.chatphoto_big_file_unique_id
+        assert chat_photo.small_file_id == Space.chatphoto_small_file_id
+        assert chat_photo.big_file_id == Space.chatphoto_big_file_id
+        assert chat_photo.small_file_unique_id == Space.chatphoto_small_file_unique_id
+        assert chat_photo.big_file_unique_id == Space.chatphoto_big_file_unique_id
 
     async def test_to_dict(self, chat_photo):
         chat_photo_dict = chat_photo.to_dict()
@@ -128,22 +95,6 @@ async def test_to_dict(self, chat_photo):
         assert chat_photo_dict["small_file_unique_id"] == chat_photo.small_file_unique_id
         assert chat_photo_dict["big_file_unique_id"] == chat_photo.big_file_unique_id
 
-    @pytest.mark.flaky(3, 1)
-    async def test_error_send_empty_file(self, bot, super_group_id):
-        chatphoto_file = open(os.devnull, "rb")
-
-        with pytest.raises(TelegramError):
-            await bot.set_chat_photo(chat_id=super_group_id, photo=chatphoto_file)
-
-    @pytest.mark.flaky(3, 1)
-    async def test_error_send_empty_file_id(self, bot, super_group_id):
-        with pytest.raises(TelegramError):
-            await bot.set_chat_photo(chat_id=super_group_id, photo="")
-
-    async def test_error_send_without_required_args(self, bot, super_group_id):
-        with pytest.raises(TypeError):
-            await bot.set_chat_photo(chat_id=super_group_id)
-
     async def test_get_small_file_instance_method(self, monkeypatch, chat_photo):
         async def make_assertion(*_, **kwargs):
             return kwargs["file_id"] == chat_photo.small_file_id
@@ -170,22 +121,22 @@ async def make_assertion(*_, **kwargs):
 
     def test_equality(self):
         a = ChatPhoto(
-            self.chatphoto_small_file_id,
-            self.chatphoto_big_file_id,
-            self.chatphoto_small_file_unique_id,
-            self.chatphoto_big_file_unique_id,
+            Space.chatphoto_small_file_id,
+            Space.chatphoto_big_file_id,
+            Space.chatphoto_small_file_unique_id,
+            Space.chatphoto_big_file_unique_id,
         )
         b = ChatPhoto(
-            self.chatphoto_small_file_id,
-            self.chatphoto_big_file_id,
-            self.chatphoto_small_file_unique_id,
-            self.chatphoto_big_file_unique_id,
+            Space.chatphoto_small_file_id,
+            Space.chatphoto_big_file_id,
+            Space.chatphoto_small_file_unique_id,
+            Space.chatphoto_big_file_unique_id,
         )
         c = ChatPhoto(
-            "", "", self.chatphoto_small_file_unique_id, self.chatphoto_big_file_unique_id
+            "", "", Space.chatphoto_small_file_unique_id, Space.chatphoto_big_file_unique_id
         )
         d = ChatPhoto("", "", 0, 0)
-        e = Voice(self.chatphoto_small_file_id, self.chatphoto_small_file_unique_id, 0)
+        e = Voice(Space.chatphoto_small_file_id, Space.chatphoto_small_file_unique_id, 0)
 
         assert a == b
         assert hash(a) == hash(b)
@@ -199,3 +150,47 @@ def test_equality(self):
 
         assert a != e
         assert hash(a) != hash(e)
+
+
+class TestChatPhotoReq:
+    async def test_get_and_download(self, bot, chat_photo):
+        jpg_file = Path("telegram.jpg")
+        if jpg_file.is_file():
+            jpg_file.unlink()
+
+        tasks = {bot.get_file(chat_photo.small_file_id), bot.get_file(chat_photo.big_file_id)}
+
+        for task in asyncio.as_completed(tasks):
+            file = await task
+            assert file.file_unique_id in (
+                chat_photo.small_file_unique_id,
+                chat_photo.big_file_unique_id,
+            )
+            assert file.file_path.startswith("https://")
+
+            await file.download_to_drive(jpg_file)
+            assert jpg_file.is_file()
+
+    async def test_send_all_args(
+        self, bot, super_group_id, chatphoto_file, chat_photo, thumb_file
+    ):
+        async def func():
+            assert await bot.set_chat_photo(super_group_id, chatphoto_file)
+
+        await expect_bad_request(
+            func, "Type of file mismatch", "Telegram did not accept the file."
+        )
+
+    async def test_error_send_empty_file(self, bot, super_group_id):
+        chatphoto_file = open(os.devnull, "rb")
+
+        with pytest.raises(TelegramError):
+            await bot.set_chat_photo(chat_id=super_group_id, photo=chatphoto_file)
+
+    async def test_error_send_empty_file_id(self, bot, super_group_id):
+        with pytest.raises(TelegramError):
+            await bot.set_chat_photo(chat_id=super_group_id, photo="")
+
+    async def test_error_send_without_required_args(self, bot, super_group_id):
+        with pytest.raises(TypeError):
+            await bot.set_chat_photo(chat_id=super_group_id)
diff --git a/tests/test_choseninlineresult.py b/tests/test_choseninlineresult.py
index 636aeceeeec..05e41ad621a 100644
--- a/tests/test_choseninlineresult.py
+++ b/tests/test_choseninlineresult.py
@@ -22,22 +22,24 @@
 from telegram import ChosenInlineResult, Location, User, Voice
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def user():
     user = User(1, "First name", False)
     user._unfreeze()
     return user
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def chosen_inline_result(user):
-    return ChosenInlineResult(TestChosenInlineResult.result_id, user, TestChosenInlineResult.query)
+    return ChosenInlineResult(Space.result_id, user, Space.query)
 
 
-class TestChosenInlineResult:
+class Space:
     result_id = "result id"
     query = "query text"
 
+
+class TestChosenInlineResultNoReq:
     def test_slot_behaviour(self, chosen_inline_result, mro_slots):
         inst = chosen_inline_result
         for attr in inst.__slots__:
@@ -45,29 +47,29 @@ def test_slot_behaviour(self, chosen_inline_result, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_de_json_required(self, bot, user):
-        json_dict = {"result_id": self.result_id, "from": user.to_dict(), "query": self.query}
+        json_dict = {"result_id": Space.result_id, "from": user.to_dict(), "query": Space.query}
         result = ChosenInlineResult.de_json(json_dict, bot)
         assert result.api_kwargs == {}
 
-        assert result.result_id == self.result_id
+        assert result.result_id == Space.result_id
         assert result.from_user == user
-        assert result.query == self.query
+        assert result.query == Space.query
 
     def test_de_json_all(self, bot, user):
         loc = Location(-42.003, 34.004)
         json_dict = {
-            "result_id": self.result_id,
+            "result_id": Space.result_id,
             "from": user.to_dict(),
-            "query": self.query,
+            "query": Space.query,
             "location": loc.to_dict(),
             "inline_message_id": "a random id",
         }
         result = ChosenInlineResult.de_json(json_dict, bot)
         assert result.api_kwargs == {}
 
-        assert result.result_id == self.result_id
+        assert result.result_id == Space.result_id
         assert result.from_user == user
-        assert result.query == self.query
+        assert result.query == Space.query
         assert result.location == loc
         assert result.inline_message_id == "a random id"
 
@@ -80,11 +82,11 @@ def test_to_dict(self, chosen_inline_result):
         assert chosen_inline_result_dict["query"] == chosen_inline_result.query
 
     def test_equality(self, user):
-        a = ChosenInlineResult(self.result_id, user, "Query", "")
-        b = ChosenInlineResult(self.result_id, user, "Query", "")
-        c = ChosenInlineResult(self.result_id, user, "", "")
+        a = ChosenInlineResult(Space.result_id, user, "Query", "")
+        b = ChosenInlineResult(Space.result_id, user, "Query", "")
+        c = ChosenInlineResult(Space.result_id, user, "", "")
         d = ChosenInlineResult("", user, "Query", "")
-        e = Voice(self.result_id, "unique_id", 0)
+        e = Voice(Space.result_id, "unique_id", 0)
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_constants.py b/tests/test_constants.py
index 0a37fa3e75d..9bb816700d8 100644
--- a/tests/test_constants.py
+++ b/tests/test_constants.py
@@ -16,10 +16,9 @@
 #
 # You should have received a copy of the GNU Lesser Public License
 # along with this program.  If not, see [http://www.gnu.org/licenses/].
+import asyncio
 import json
 
-import pytest
-
 from telegram import constants
 from telegram._utils.enum import IntEnum, StringEnum
 from telegram.error import BadRequest
@@ -36,7 +35,7 @@ class IntEnumTest(IntEnum):
     BAR = 2
 
 
-class TestConstants:
+class TestConstantsNoReq:
     """Also test _utils.enum.StringEnum on the fly because tg.constants is currently the only
     place where that class is used."""
 
@@ -110,30 +109,6 @@ def test_int_inheritance(self):
 
         assert hash(IntEnumTest.FOO) == hash(1)
 
-    @pytest.mark.flaky(3, 1)
-    async def test_max_message_length(self, bot, chat_id):
-        await bot.send_message(chat_id=chat_id, text="a" * constants.MessageLimit.MAX_TEXT_LENGTH)
-
-        with pytest.raises(
-            BadRequest,
-            match="Message is too long",
-        ):
-            await bot.send_message(
-                chat_id=chat_id, text="a" * (constants.MessageLimit.MAX_TEXT_LENGTH + 1)
-            )
-
-    @pytest.mark.flaky(3, 1)
-    async def test_max_caption_length(self, bot, chat_id):
-        good_caption = "a" * constants.MessageLimit.CAPTION_LENGTH
-        with data_file("telegram.png").open("rb") as f:
-            good_msg = await bot.send_photo(photo=f, caption=good_caption, chat_id=chat_id)
-        assert good_msg.caption == good_caption
-
-        bad_caption = good_caption + "Z"
-        match = "Message caption is too long"
-        with pytest.raises(BadRequest, match=match), data_file("telegram.png").open("rb") as f:
-            await bot.send_photo(photo=f, caption=bad_caption, chat_id=chat_id)
-
     def test_bot_api_version_and_info(self):
         assert constants.BOT_API_VERSION == str(constants.BOT_API_VERSION_INFO)
         assert constants.BOT_API_VERSION_INFO == tuple(
@@ -151,3 +126,27 @@ def test_bot_api_version_info(self):
         assert vi < (vi[0] + 1, vi[1] + 1)
         assert vi[0] == vi.major
         assert vi[1] == vi.minor
+
+
+class TestConstantsReq:
+    async def test_max_message_length(self, bot, chat_id):
+        tasks = asyncio.gather(
+            bot.send_message(chat_id, text="a" * constants.MessageLimit.MAX_TEXT_LENGTH),
+            bot.send_message(chat_id, text="a" * (constants.MessageLimit.MAX_TEXT_LENGTH + 1)),
+            return_exceptions=True,
+        )
+        results = await tasks
+        assert len(results) == 2
+        assert isinstance(results[1], BadRequest) and "Message is too long" in str(results[1])
+
+    async def test_max_caption_length(self, bot, chat_id):
+        good_caption = "a" * constants.MessageLimit.CAPTION_LENGTH
+        bad_caption = good_caption + "Z"
+        tasks = asyncio.gather(
+            bot.send_photo(chat_id, data_file("telegram.png").read_bytes(), good_caption),
+            bot.send_photo(chat_id, data_file("telegram.png").read_bytes(), bad_caption),
+            return_exceptions=True,
+        )
+        good_msg, bad_msg = await tasks
+        assert good_msg.caption == good_caption
+        assert isinstance(bad_msg, BadRequest) and "Message caption is too long" in str(bad_msg)
diff --git a/tests/test_contact.py b/tests/test_contact.py
index d35280a39b0..8e90feacf7f 100644
--- a/tests/test_contact.py
+++ b/tests/test_contact.py
@@ -17,6 +17,8 @@
 # You should have received a copy of the GNU Lesser Public License
 # along with this program.  If not, see [http://www.gnu.org/licenses/].
 
+import asyncio
+
 import pytest
 
 from telegram import Contact, Voice
@@ -24,49 +26,51 @@
 from telegram.request import RequestData
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def contact():
     return Contact(
-        TestContact.phone_number,
-        TestContact.first_name,
-        TestContact.last_name,
-        TestContact.user_id,
+        Space.phone_number,
+        Space.first_name,
+        Space.last_name,
+        Space.user_id,
     )
 
 
-class TestContact:
+class Space:
     phone_number = "+11234567890"
     first_name = "Leandro"
     last_name = "Toledo"
     user_id = 23
 
+
+class TestContactNoReq:
     def test_slot_behaviour(self, contact, mro_slots):
         for attr in contact.__slots__:
             assert getattr(contact, attr, "err") != "err", f"got extra slot '{attr}'"
         assert len(mro_slots(contact)) == len(set(mro_slots(contact))), "duplicate slot"
 
     def test_de_json_required(self, bot):
-        json_dict = {"phone_number": self.phone_number, "first_name": self.first_name}
+        json_dict = {"phone_number": Space.phone_number, "first_name": Space.first_name}
         contact = Contact.de_json(json_dict, bot)
         assert contact.api_kwargs == {}
 
-        assert contact.phone_number == self.phone_number
-        assert contact.first_name == self.first_name
+        assert contact.phone_number == Space.phone_number
+        assert contact.first_name == Space.first_name
 
     def test_de_json_all(self, bot):
         json_dict = {
-            "phone_number": self.phone_number,
-            "first_name": self.first_name,
-            "last_name": self.last_name,
-            "user_id": self.user_id,
+            "phone_number": Space.phone_number,
+            "first_name": Space.first_name,
+            "last_name": Space.last_name,
+            "user_id": Space.user_id,
         }
         contact = Contact.de_json(json_dict, bot)
         assert contact.api_kwargs == {}
 
-        assert contact.phone_number == self.phone_number
-        assert contact.first_name == self.first_name
-        assert contact.last_name == self.last_name
-        assert contact.user_id == self.user_id
+        assert contact.phone_number == Space.phone_number
+        assert contact.first_name == Space.first_name
+        assert contact.last_name == Space.last_name
+        assert contact.user_id == Space.user_id
 
     async def test_send_with_contact(self, monkeypatch, bot, chat_id, contact):
         async def make_assertion(url, request_data: RequestData, *args, **kwargs):
@@ -80,50 +84,6 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs):
         message = await bot.send_contact(contact=contact, chat_id=chat_id)
         assert message
 
-    @pytest.mark.flaky(3, 1)
-    @pytest.mark.parametrize(
-        "default_bot,custom",
-        [
-            ({"allow_sending_without_reply": True}, None),
-            ({"allow_sending_without_reply": False}, None),
-            ({"allow_sending_without_reply": False}, True),
-        ],
-        indirect=["default_bot"],
-    )
-    async def test_send_contact_default_allow_sending_without_reply(
-        self, default_bot, chat_id, contact, custom
-    ):
-        reply_to_message = await default_bot.send_message(chat_id, "test")
-        await reply_to_message.delete()
-        if custom is not None:
-            message = await default_bot.send_contact(
-                chat_id,
-                contact=contact,
-                allow_sending_without_reply=custom,
-                reply_to_message_id=reply_to_message.message_id,
-            )
-            assert message.reply_to_message is None
-        elif default_bot.defaults.allow_sending_without_reply:
-            message = await default_bot.send_contact(
-                chat_id, contact=contact, reply_to_message_id=reply_to_message.message_id
-            )
-            assert message.reply_to_message is None
-        else:
-            with pytest.raises(BadRequest, match="message not found"):
-                await default_bot.send_contact(
-                    chat_id, contact=contact, reply_to_message_id=reply_to_message.message_id
-                )
-
-    @pytest.mark.flaky(3, 1)
-    @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
-    async def test_send_contact_default_protect_content(self, chat_id, default_bot, contact):
-        protected = await default_bot.send_contact(chat_id, contact=contact)
-        assert protected.has_protected_content
-        unprotected = await default_bot.send_contact(
-            chat_id, contact=contact, protect_content=False
-        )
-        assert not unprotected.has_protected_content
-
     async def test_send_contact_without_required(self, bot, chat_id):
         with pytest.raises(ValueError, match="Either contact or phone_number and first_name"):
             await bot.send_contact(chat_id=chat_id)
@@ -147,10 +107,10 @@ def test_to_dict(self, contact):
         assert contact_dict["user_id"] == contact.user_id
 
     def test_equality(self):
-        a = Contact(self.phone_number, self.first_name)
-        b = Contact(self.phone_number, self.first_name)
-        c = Contact(self.phone_number, "")
-        d = Contact("", self.first_name)
+        a = Contact(Space.phone_number, Space.first_name)
+        b = Contact(Space.phone_number, Space.first_name)
+        c = Contact(Space.phone_number, "")
+        d = Contact("", Space.first_name)
         e = Voice("", "unique_id", 0)
 
         assert a == b
@@ -165,3 +125,48 @@ def test_equality(self):
 
         assert a != e
         assert hash(a) != hash(e)
+
+
+class TestContactReq:
+    @pytest.mark.parametrize(
+        "default_bot,custom",
+        [
+            ({"allow_sending_without_reply": True}, None),
+            ({"allow_sending_without_reply": False}, None),
+            ({"allow_sending_without_reply": False}, True),
+        ],
+        indirect=["default_bot"],
+    )
+    async def test_send_contact_default_allow_sending_without_reply(
+        self, default_bot, chat_id, contact, custom
+    ):
+        reply_to_message = await default_bot.send_message(chat_id, "test")
+        await reply_to_message.delete()
+        if custom is not None:
+            message = await default_bot.send_contact(
+                chat_id,
+                contact=contact,
+                allow_sending_without_reply=custom,
+                reply_to_message_id=reply_to_message.message_id,
+            )
+            assert message.reply_to_message is None
+        elif default_bot.defaults.allow_sending_without_reply:
+            message = await default_bot.send_contact(
+                chat_id, contact=contact, reply_to_message_id=reply_to_message.message_id
+            )
+            assert message.reply_to_message is None
+        else:
+            with pytest.raises(BadRequest, match="message not found"):
+                await default_bot.send_contact(
+                    chat_id, contact=contact, reply_to_message_id=reply_to_message.message_id
+                )
+
+    @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
+    async def test_send_contact_default_protect_content(self, chat_id, default_bot, contact):
+        tasks = asyncio.gather(
+            default_bot.send_contact(chat_id, contact=contact),
+            default_bot.send_contact(chat_id, contact=contact, protect_content=False),
+        )
+        protected, unprotected = await tasks
+        assert protected.has_protected_content
+        assert not unprotected.has_protected_content
diff --git a/tests/test_conversationhandler.py b/tests/test_conversationhandler.py
index 93f64963e08..2f16f94301d 100644
--- a/tests/test_conversationhandler.py
+++ b/tests/test_conversationhandler.py
@@ -24,7 +24,6 @@
 import pytest
 
 from telegram import (
-    Bot,
     CallbackQuery,
     Chat,
     ChosenInlineResult,
@@ -45,7 +44,6 @@
     CommandHandler,
     ConversationHandler,
     Defaults,
-    ExtBot,
     InlineQueryHandler,
     JobQueue,
     MessageHandler,
@@ -59,7 +57,7 @@
     filters,
 )
 from telegram.warnings import PTBUserWarning
-from tests.conftest import make_command_message
+from tests.conftest import DictBot, make_bot, make_command_message
 
 
 @pytest.fixture(scope="class")
@@ -2114,7 +2112,7 @@ async def test_conversation_handler_block_dont_override(self, app):
     @pytest.mark.parametrize("handler_block", [True, False, None])
     @pytest.mark.parametrize("ext_bot", [True, False], ids=["ExtBot", "Bot"])
     async def test_blocking_resolution_order(
-        self, bot, default_block, ch_block, handler_block, ext_bot
+        self, bot_info, default_block, ch_block, handler_block, ext_bot
     ):
 
         event = asyncio.Event()
@@ -2151,7 +2149,7 @@ async def callback(_, __):
                 fallbacks=[fallback],
             )
 
-        bot = ExtBot(bot.token, defaults=defaults) if ext_bot else Bot(bot.token)
+        bot = make_bot(bot_info, defaults=defaults) if ext_bot else DictBot(bot_info["token"])
         app = ApplicationBuilder().bot(bot).build()
         app.add_handler(conv_handler)
 
diff --git a/tests/test_datetime.py b/tests/test_datetime.py
index aae6ccac0af..2287513c23b 100644
--- a/tests/test_datetime.py
+++ b/tests/test_datetime.py
@@ -17,7 +17,6 @@
 # You should have received a copy of the GNU Lesser Public License
 # along with this program.  If not, see [http://www.gnu.org/licenses/].
 import datetime as dtm
-import os
 import time
 
 import pytest
@@ -26,7 +25,7 @@
 from telegram.ext import Defaults
 
 # sample time specification values categorised into absolute / delta / time-of-day
-from tests.auxil.object_conversions import env_var_2_bool
+from tests.conftest import TEST_WITH_OPT_DEPS
 
 ABSOLUTE_TIME_SPECS = [
     dtm.datetime.now(tz=dtm.timezone(dtm.timedelta(hours=-7))).replace(second=0, microsecond=0),
@@ -49,7 +48,6 @@
 
 with the TEST_WITH_OPT_DEPS=False environment variable in addition to the regular test suite.
 """
-TEST_WITH_OPT_DEPS = env_var_2_bool(os.getenv("TEST_WITH_OPT_DEPS", True))
 
 
 class TestDatetime:
diff --git a/tests/test_defaults.py b/tests/test_defaults.py
index 902753b05d2..8efcca754a2 100644
--- a/tests/test_defaults.py
+++ b/tests/test_defaults.py
@@ -19,15 +19,12 @@
 
 import datetime as dtm
 import inspect
-import os
 
 import pytest
 
 from telegram import User
 from telegram.ext import Defaults
-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))
+from tests.conftest import TEST_WITH_OPT_DEPS
 
 
 class TestDefault:
diff --git a/tests/test_dice.py b/tests/test_dice.py
index 39d37d7be40..573bbf22cb5 100644
--- a/tests/test_dice.py
+++ b/tests/test_dice.py
@@ -22,14 +22,16 @@
 from telegram import BotCommand, Dice
 
 
-@pytest.fixture(scope="class", params=Dice.ALL_EMOJI)
+@pytest.fixture(scope="module", params=Dice.ALL_EMOJI)
 def dice(request):
     return Dice(value=5, emoji=request.param)
 
 
-class TestDice:
+class Space:
     value = 4
 
+
+class TestDiceNoReq:
     def test_slot_behaviour(self, dice, mro_slots):
         for attr in dice.__slots__:
             assert getattr(dice, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -37,11 +39,11 @@ def test_slot_behaviour(self, dice, mro_slots):
 
     @pytest.mark.parametrize("emoji", Dice.ALL_EMOJI)
     def test_de_json(self, bot, emoji):
-        json_dict = {"value": self.value, "emoji": emoji}
+        json_dict = {"value": Space.value, "emoji": emoji}
         dice = Dice.de_json(json_dict, bot)
         assert dice.api_kwargs == {}
 
-        assert dice.value == self.value
+        assert dice.value == Space.value
         assert dice.emoji == emoji
         assert Dice.de_json(None, bot) is None
 
diff --git a/tests/test_document.py b/tests/test_document.py
index 1600eb45e0a..d882553a2e8 100644
--- a/tests/test_document.py
+++ b/tests/test_document.py
@@ -16,6 +16,7 @@
 #
 # You should have received a copy of the GNU Lesser Public License
 # along with this program.  If not, see [http://www.gnu.org/licenses/].
+import asyncio
 import os
 from pathlib import Path
 
@@ -35,18 +36,17 @@
 
 @pytest.fixture(scope="function")
 def document_file():
-    f = data_file("telegram.png").open("rb")
-    yield f
-    f.close()
+    with data_file("telegram.png").open("rb") as f:
+        yield f
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 async def document(bot, chat_id):
     with data_file("telegram.png").open("rb") as f:
         return (await bot.send_document(chat_id, document=f, read_timeout=50)).document
 
 
-class TestDocument:
+class Space:
     caption = "DocumentTest - *Caption*"
     document_file_url = "https://python-telegram-bot.org/static/testfiles/telegram.gif"
     file_size = 12948
@@ -58,6 +58,8 @@ class TestDocument:
     document_file_id = "5a3128a4d2a04750b5b58397f3b5e812"
     document_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
 
+
+class TestDocumentNoReq:
     def test_slot_behaviour(self, document, mro_slots):
         for attr in document.__slots__:
             assert getattr(document, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -71,19 +73,154 @@ def test_creation(self, document):
         assert document.file_unique_id != ""
 
     def test_expected_values(self, document):
-        assert document.file_size == self.file_size
-        assert document.mime_type == self.mime_type
-        assert document.file_name == self.file_name
-        assert document.thumb.file_size == self.thumb_file_size
-        assert document.thumb.width == self.thumb_width
-        assert document.thumb.height == self.thumb_height
-
-    @pytest.mark.flaky(3, 1)
+        assert document.file_size == Space.file_size
+        assert document.mime_type == Space.mime_type
+        assert document.file_name == Space.file_name
+        assert document.thumb.file_size == Space.thumb_file_size
+        assert document.thumb.width == Space.thumb_width
+        assert document.thumb.height == Space.thumb_height
+
+    @pytest.mark.parametrize("disable_content_type_detection", [True, False, None])
+    async def test_send_with_document(
+        self, monkeypatch, bot, chat_id, document, disable_content_type_detection
+    ):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            data = request_data.parameters
+            type_detection = (
+                data.get("disable_content_type_detection") == disable_content_type_detection
+            )
+            return data["document"] == document.file_id and type_detection
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+
+        message = await bot.send_document(
+            document=document,
+            chat_id=chat_id,
+            disable_content_type_detection=disable_content_type_detection,
+        )
+
+        assert message
+
+    @pytest.mark.parametrize("local_mode", [True, False])
+    async def test_send_document_local_files(self, monkeypatch, bot, chat_id, local_mode):
+        try:
+            bot._local_mode = local_mode
+            # For just test that the correct paths are passed as we have no local bot API set up
+            test_flag = False
+            file = data_file("telegram.jpg")
+            expected = file.as_uri()
+
+            async def make_assertion(_, data, *args, **kwargs):
+                nonlocal test_flag
+                if local_mode:
+                    test_flag = data.get("document") == expected and data.get("thumb") == expected
+                else:
+                    test_flag = isinstance(data.get("document"), InputFile) and isinstance(
+                        data.get("thumb"), InputFile
+                    )
+
+            monkeypatch.setattr(bot, "_post", make_assertion)
+            await bot.send_document(chat_id, file, thumb=file)
+            assert test_flag
+        finally:
+            bot._local_mode = False
+
+    def test_de_json(self, bot, document):
+        json_dict = {
+            "file_id": Space.document_file_id,
+            "file_unique_id": Space.document_file_unique_id,
+            "thumb": document.thumb.to_dict(),
+            "file_name": Space.file_name,
+            "mime_type": Space.mime_type,
+            "file_size": Space.file_size,
+        }
+        test_document = Document.de_json(json_dict, bot)
+        assert test_document.api_kwargs == {}
+
+        assert test_document.file_id == Space.document_file_id
+        assert test_document.file_unique_id == Space.document_file_unique_id
+        assert test_document.thumb == document.thumb
+        assert test_document.file_name == Space.file_name
+        assert test_document.mime_type == Space.mime_type
+        assert test_document.file_size == Space.file_size
+
+    def test_to_dict(self, document):
+        document_dict = document.to_dict()
+
+        assert isinstance(document_dict, dict)
+        assert document_dict["file_id"] == document.file_id
+        assert document_dict["file_unique_id"] == document.file_unique_id
+        assert document_dict["file_name"] == document.file_name
+        assert document_dict["mime_type"] == document.mime_type
+        assert document_dict["file_size"] == document.file_size
+
+    async def test_error_send_without_required_args(self, bot, chat_id):
+        with pytest.raises(TypeError):
+            await bot.send_document(chat_id=chat_id)
+
+    async def test_get_file_instance_method(self, monkeypatch, document):
+        async def make_assertion(*_, **kwargs):
+            return kwargs["file_id"] == document.file_id
+
+        assert check_shortcut_signature(Document.get_file, Bot.get_file, ["file_id"], [])
+        assert await check_shortcut_call(document.get_file, document.get_bot(), "get_file")
+        assert await check_defaults_handling(document.get_file, document.get_bot())
+
+        monkeypatch.setattr(document.get_bot(), "get_file", make_assertion)
+        assert await document.get_file()
+
+    def test_equality(self, document):
+        a = Document(document.file_id, document.file_unique_id)
+        b = Document("", document.file_unique_id)
+        d = Document("", "")
+        e = Voice(document.file_id, document.file_unique_id, 0)
+
+        assert a == b
+        assert hash(a) == hash(b)
+        assert a is not b
+
+        assert a != d
+        assert hash(a) != hash(d)
+
+        assert a != e
+        assert hash(a) != hash(e)
+
+
+class TestDocumentReq:
+    async def test_error_send_empty_file(self, bot, chat_id):
+        with open(os.devnull, "rb") as f:
+            with pytest.raises(TelegramError):
+                await bot.send_document(chat_id=chat_id, document=f)
+
+    async def test_error_send_empty_file_id(self, bot, chat_id):
+        with pytest.raises(TelegramError):
+            await bot.send_document(chat_id=chat_id, document="")
+
+    async def test_get_and_download(self, bot, document):
+        path = Path("telegram.png")
+        if path.is_file():
+            path.unlink()
+
+        new_file = await bot.get_file(document.file_id)
+
+        assert new_file.file_size == document.file_size
+        assert new_file.file_id == document.file_id
+        assert new_file.file_unique_id == document.file_unique_id
+        assert new_file.file_path.startswith("https://")
+
+        await new_file.download_to_drive("telegram.png")
+
+        assert path.is_file()
+
+    async def test_send_resend(self, bot, chat_id, document):
+        message = await bot.send_document(chat_id=chat_id, document=document.file_id)
+        assert message.document == document
+
     async def test_send_all_args(self, bot, chat_id, document_file, document, thumb_file):
         message = await bot.send_document(
             chat_id,
             document=document_file,
-            caption=self.caption,
+            caption=Space.caption,
             disable_notification=False,
             protect_content=True,
             filename="telegram_custom.png",
@@ -100,31 +237,13 @@ async def test_send_all_args(self, bot, chat_id, document_file, document, thumb_
         assert message.document.file_name == "telegram_custom.png"
         assert message.document.mime_type == document.mime_type
         assert message.document.file_size == document.file_size
-        assert message.caption == self.caption.replace("*", "")
-        assert message.document.thumb.width == self.thumb_width
-        assert message.document.thumb.height == self.thumb_height
+        assert message.caption == Space.caption.replace("*", "")
+        assert message.document.thumb.width == Space.thumb_width
+        assert message.document.thumb.height == Space.thumb_height
         assert message.has_protected_content
 
-    @pytest.mark.flaky(3, 1)
-    async def test_get_and_download(self, bot, document):
-        path = Path("telegram.png")
-        if path.is_file():
-            path.unlink()
-
-        new_file = await bot.get_file(document.file_id)
-
-        assert new_file.file_size == document.file_size
-        assert new_file.file_id == document.file_id
-        assert new_file.file_unique_id == document.file_unique_id
-        assert new_file.file_path.startswith("https://")
-
-        await new_file.download_to_drive("telegram.png")
-
-        assert path.is_file()
-
-    @pytest.mark.flaky(3, 1)
     async def test_send_url_gif_file(self, bot, chat_id):
-        message = await bot.send_document(chat_id, self.document_file_url)
+        message = await bot.send_document(chat_id, Space.document_file_url)
 
         document = message.document
 
@@ -138,34 +257,16 @@ async def test_send_url_gif_file(self, bot, chat_id):
         assert document.mime_type == "image/gif"
         assert document.file_size == 3878
 
-    @pytest.mark.flaky(3, 1)
-    async def test_send_resend(self, bot, chat_id, document):
-        message = await bot.send_document(chat_id=chat_id, document=document.file_id)
-
-        assert message.document == document
-
-    @pytest.mark.parametrize("disable_content_type_detection", [True, False, None])
-    async def test_send_with_document(
-        self, monkeypatch, bot, chat_id, document, disable_content_type_detection
-    ):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            data = request_data.parameters
-            type_detection = (
-                data.get("disable_content_type_detection") == disable_content_type_detection
-            )
-            return data["document"] == document.file_id and type_detection
-
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-
-        message = await bot.send_document(
-            document=document,
-            chat_id=chat_id,
-            disable_content_type_detection=disable_content_type_detection,
+    @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
+    async def test_send_document_default_protect_content(self, chat_id, default_bot, document):
+        tasks = asyncio.gather(
+            default_bot.send_document(chat_id, document),
+            default_bot.send_document(chat_id, document, protect_content=False),
         )
+        protected, unprotected = await tasks
+        assert protected.has_protected_content
+        assert not unprotected.has_protected_content
 
-        assert message
-
-    @pytest.mark.flaky(3, 1)
     async def test_send_document_caption_entities(self, bot, chat_id, document):
         test_string = "Italic Bold Code"
         entities = [
@@ -180,7 +281,6 @@ async def test_send_document_caption_entities(self, bot, chat_id, document):
         assert message.caption == test_string
         assert message.caption_entities == tuple(entities)
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_send_document_default_parse_mode_1(self, default_bot, chat_id, document):
         test_string = "Italic Bold Code"
@@ -190,7 +290,6 @@ async def test_send_document_default_parse_mode_1(self, default_bot, chat_id, do
         assert message.caption_markdown == test_markdown_string
         assert message.caption == test_string
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_send_document_default_parse_mode_2(self, default_bot, chat_id, document):
         test_markdown_string = "_Italic_ *Bold* `Code`"
@@ -201,7 +300,6 @@ async def test_send_document_default_parse_mode_2(self, default_bot, chat_id, do
         assert message.caption == test_markdown_string
         assert message.caption_markdown == escape_markdown(test_markdown_string)
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_send_document_default_parse_mode_3(self, default_bot, chat_id, document):
         test_markdown_string = "_Italic_ *Bold* `Code`"
@@ -212,7 +310,6 @@ async def test_send_document_default_parse_mode_3(self, default_bot, chat_id, do
         assert message.caption == test_markdown_string
         assert message.caption_markdown == escape_markdown(test_markdown_string)
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize(
         "default_bot,custom",
         [
@@ -245,106 +342,3 @@ async def test_send_document_default_allow_sending_without_reply(
                 await default_bot.send_document(
                     chat_id, document, reply_to_message_id=reply_to_message.message_id
                 )
-
-    @pytest.mark.flaky(3, 1)
-    @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
-    async def test_send_document_default_protect_content(self, chat_id, default_bot, document):
-        protected = await default_bot.send_document(chat_id, document)
-        assert protected.has_protected_content
-        unprotected = await default_bot.send_document(chat_id, document, protect_content=False)
-        assert not unprotected.has_protected_content
-
-    @pytest.mark.parametrize("local_mode", [True, False])
-    async def test_send_document_local_files(self, monkeypatch, bot, chat_id, local_mode):
-        try:
-            bot._local_mode = local_mode
-            # For just test that the correct paths are passed as we have no local bot API set up
-            test_flag = False
-            file = data_file("telegram.jpg")
-            expected = file.as_uri()
-
-            async def make_assertion(_, data, *args, **kwargs):
-                nonlocal test_flag
-                if local_mode:
-                    test_flag = data.get("document") == expected and data.get("thumb") == expected
-                else:
-                    test_flag = isinstance(data.get("document"), InputFile) and isinstance(
-                        data.get("thumb"), InputFile
-                    )
-
-            monkeypatch.setattr(bot, "_post", make_assertion)
-            await bot.send_document(chat_id, file, thumb=file)
-            assert test_flag
-        finally:
-            bot._local_mode = False
-
-    def test_de_json(self, bot, document):
-        json_dict = {
-            "file_id": self.document_file_id,
-            "file_unique_id": self.document_file_unique_id,
-            "thumb": document.thumb.to_dict(),
-            "file_name": self.file_name,
-            "mime_type": self.mime_type,
-            "file_size": self.file_size,
-        }
-        test_document = Document.de_json(json_dict, bot)
-        assert test_document.api_kwargs == {}
-
-        assert test_document.file_id == self.document_file_id
-        assert test_document.file_unique_id == self.document_file_unique_id
-        assert test_document.thumb == document.thumb
-        assert test_document.file_name == self.file_name
-        assert test_document.mime_type == self.mime_type
-        assert test_document.file_size == self.file_size
-
-    def test_to_dict(self, document):
-        document_dict = document.to_dict()
-
-        assert isinstance(document_dict, dict)
-        assert document_dict["file_id"] == document.file_id
-        assert document_dict["file_unique_id"] == document.file_unique_id
-        assert document_dict["file_name"] == document.file_name
-        assert document_dict["mime_type"] == document.mime_type
-        assert document_dict["file_size"] == document.file_size
-
-    @pytest.mark.flaky(3, 1)
-    async def test_error_send_empty_file(self, bot, chat_id):
-        with open(os.devnull, "rb") as f:
-            with pytest.raises(TelegramError):
-                await bot.send_document(chat_id=chat_id, document=f)
-
-    @pytest.mark.flaky(3, 1)
-    async def test_error_send_empty_file_id(self, bot, chat_id):
-        with pytest.raises(TelegramError):
-            await bot.send_document(chat_id=chat_id, document="")
-
-    async def test_error_send_without_required_args(self, bot, chat_id):
-        with pytest.raises(TypeError):
-            await bot.send_document(chat_id=chat_id)
-
-    async def test_get_file_instance_method(self, monkeypatch, document):
-        async def make_assertion(*_, **kwargs):
-            return kwargs["file_id"] == document.file_id
-
-        assert check_shortcut_signature(Document.get_file, Bot.get_file, ["file_id"], [])
-        assert await check_shortcut_call(document.get_file, document.get_bot(), "get_file")
-        assert await check_defaults_handling(document.get_file, document.get_bot())
-
-        monkeypatch.setattr(document.get_bot(), "get_file", make_assertion)
-        assert await document.get_file()
-
-    def test_equality(self, document):
-        a = Document(document.file_id, document.file_unique_id)
-        b = Document("", document.file_unique_id)
-        d = Document("", "")
-        e = Voice(document.file_id, document.file_unique_id, 0)
-
-        assert a == b
-        assert hash(a) == hash(b)
-        assert a is not b
-
-        assert a != d
-        assert hash(a) != hash(d)
-
-        assert a != e
-        assert hash(a) != hash(e)
diff --git a/tests/test_encryptedcredentials.py b/tests/test_encryptedcredentials.py
index c56a6ce4244..dc94bfd7117 100644
--- a/tests/test_encryptedcredentials.py
+++ b/tests/test_encryptedcredentials.py
@@ -22,20 +22,18 @@
 from telegram import EncryptedCredentials, PassportElementError
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def encrypted_credentials():
-    return EncryptedCredentials(
-        TestEncryptedCredentials.data,
-        TestEncryptedCredentials.hash,
-        TestEncryptedCredentials.secret,
-    )
+    return EncryptedCredentials(Space.data, Space.hash, Space.secret)
 
 
-class TestEncryptedCredentials:
+class Space:
     data = "data"
     hash = "hash"
     secret = "secret"
 
+
+class TestEncryptedCredentialsNoReq:
     def test_slot_behaviour(self, encrypted_credentials, mro_slots):
         inst = encrypted_credentials
         for attr in inst.__slots__:
@@ -43,9 +41,9 @@ def test_slot_behaviour(self, encrypted_credentials, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, encrypted_credentials):
-        assert encrypted_credentials.data == self.data
-        assert encrypted_credentials.hash == self.hash
-        assert encrypted_credentials.secret == self.secret
+        assert encrypted_credentials.data == Space.data
+        assert encrypted_credentials.hash == Space.hash
+        assert encrypted_credentials.secret == Space.secret
 
     def test_to_dict(self, encrypted_credentials):
         encrypted_credentials_dict = encrypted_credentials.to_dict()
@@ -56,11 +54,11 @@ def test_to_dict(self, encrypted_credentials):
         assert encrypted_credentials_dict["secret"] == encrypted_credentials.secret
 
     def test_equality(self):
-        a = EncryptedCredentials(self.data, self.hash, self.secret)
-        b = EncryptedCredentials(self.data, self.hash, self.secret)
-        c = EncryptedCredentials(self.data, "", "")
-        d = EncryptedCredentials("", self.hash, "")
-        e = EncryptedCredentials("", "", self.secret)
+        a = EncryptedCredentials(Space.data, Space.hash, Space.secret)
+        b = EncryptedCredentials(Space.data, Space.hash, Space.secret)
+        c = EncryptedCredentials(Space.data, "", "")
+        d = EncryptedCredentials("", Space.hash, "")
+        e = EncryptedCredentials("", "", Space.secret)
         f = PassportElementError("source", "type", "message")
 
         assert a == b
diff --git a/tests/test_encryptedpassportelement.py b/tests/test_encryptedpassportelement.py
index f57193d1a7a..a10ba2f843d 100644
--- a/tests/test_encryptedpassportelement.py
+++ b/tests/test_encryptedpassportelement.py
@@ -22,22 +22,22 @@
 from telegram import EncryptedPassportElement, PassportElementError, PassportFile
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def encrypted_passport_element():
     return EncryptedPassportElement(
-        TestEncryptedPassportElement.type_,
+        Space.type_,
         "this is a hash",
-        data=TestEncryptedPassportElement.data,
-        phone_number=TestEncryptedPassportElement.phone_number,
-        email=TestEncryptedPassportElement.email,
-        files=TestEncryptedPassportElement.files,
-        front_side=TestEncryptedPassportElement.front_side,
-        reverse_side=TestEncryptedPassportElement.reverse_side,
-        selfie=TestEncryptedPassportElement.selfie,
+        data=Space.data,
+        phone_number=Space.phone_number,
+        email=Space.email,
+        files=Space.files,
+        front_side=Space.front_side,
+        reverse_side=Space.reverse_side,
+        selfie=Space.selfie,
     )
 
 
-class TestEncryptedPassportElement:
+class Space:
     type_ = "type"
     hash = "this is a hash"
     data = "data"
@@ -48,6 +48,8 @@ class TestEncryptedPassportElement:
     reverse_side = PassportFile("file_id", 50, 0, 25)
     selfie = PassportFile("file_id", 50, 0, 25)
 
+
+class TestEncryptedPassportElementNoReq:
     def test_slot_behaviour(self, encrypted_passport_element, mro_slots):
         inst = encrypted_passport_element
         for attr in inst.__slots__:
@@ -55,15 +57,15 @@ def test_slot_behaviour(self, encrypted_passport_element, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, encrypted_passport_element):
-        assert encrypted_passport_element.type == self.type_
-        assert encrypted_passport_element.hash == self.hash
-        assert encrypted_passport_element.data == self.data
-        assert encrypted_passport_element.phone_number == self.phone_number
-        assert encrypted_passport_element.email == self.email
-        assert encrypted_passport_element.files == tuple(self.files)
-        assert encrypted_passport_element.front_side == self.front_side
-        assert encrypted_passport_element.reverse_side == self.reverse_side
-        assert encrypted_passport_element.selfie == self.selfie
+        assert encrypted_passport_element.type == Space.type_
+        assert encrypted_passport_element.hash == Space.hash
+        assert encrypted_passport_element.data == Space.data
+        assert encrypted_passport_element.phone_number == Space.phone_number
+        assert encrypted_passport_element.email == Space.email
+        assert encrypted_passport_element.files == tuple(Space.files)
+        assert encrypted_passport_element.front_side == Space.front_side
+        assert encrypted_passport_element.reverse_side == Space.reverse_side
+        assert encrypted_passport_element.selfie == Space.selfie
 
     def test_to_dict(self, encrypted_passport_element):
         encrypted_passport_element_dict = encrypted_passport_element.to_dict()
@@ -91,14 +93,14 @@ def test_to_dict(self, encrypted_passport_element):
         )
 
     def test_attributes_always_tuple(self):
-        element = EncryptedPassportElement(self.type_, self.hash)
+        element = EncryptedPassportElement(Space.type_, Space.hash)
         assert element.files == ()
         assert element.translation == ()
 
     def test_equality(self):
-        a = EncryptedPassportElement(self.type_, self.hash, data=self.data)
-        b = EncryptedPassportElement(self.type_, self.hash, data=self.data)
-        c = EncryptedPassportElement(self.data, "")
+        a = EncryptedPassportElement(Space.type_, Space.hash, data=Space.data)
+        b = EncryptedPassportElement(Space.type_, Space.hash, data=Space.data)
+        c = EncryptedPassportElement(Space.data, "")
         d = PassportElementError("source", "type", "message")
 
         assert a == b
diff --git a/tests/test_file.py b/tests/test_file.py
index 91fd3a3c880..99d0f9e3702 100644
--- a/tests/test_file.py
+++ b/tests/test_file.py
@@ -27,20 +27,20 @@
 from tests.conftest import data_file
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def file(bot):
     file = File(
-        TestFile.file_id,
-        TestFile.file_unique_id,
-        file_path=TestFile.file_path,
-        file_size=TestFile.file_size,
+        Space.file_id,
+        Space.file_unique_id,
+        file_path=Space.file_path,
+        file_size=Space.file_size,
     )
     file.set_bot(bot)
     file._unfreeze()
     return file
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def encrypted_file(bot):
     # check https://github.com/python-telegram-bot/python-telegram-bot/wiki/\
     # PTB-test-writing-knowledge-base#how-to-generate-encrypted-passport-files
@@ -49,13 +49,13 @@ def encrypted_file(bot):
         "Oq3G4sX+bKZthoyms1YlPqvWou9esb+z0Bi/KqQUG8s=",
         "Pt7fKPgYWKA/7a8E64Ea1X8C+Wf7Ky1tF4ANBl63vl4=",
     )
-    ef = File(TestFile.file_id, TestFile.file_unique_id, TestFile.file_size, TestFile.file_path)
+    ef = File(Space.file_id, Space.file_unique_id, Space.file_size, Space.file_path)
     ef.set_bot(bot)
     ef.set_credentials(fc)
     return ef
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def encrypted_local_file(bot):
     # check encrypted_file() for the source of the fc values
     fc = FileCredentials(
@@ -63,9 +63,9 @@ def encrypted_local_file(bot):
         "Pt7fKPgYWKA/7a8E64Ea1X8C+Wf7Ky1tF4ANBl63vl4=",
     )
     ef = File(
-        TestFile.file_id,
-        TestFile.file_unique_id,
-        TestFile.file_size,
+        Space.file_id,
+        Space.file_unique_id,
+        Space.file_size,
         file_path=str(data_file("image_encrypted.jpg")),
     )
     ef.set_bot(bot)
@@ -73,19 +73,19 @@ def encrypted_local_file(bot):
     return ef
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def local_file(bot):
     file = File(
-        TestFile.file_id,
-        TestFile.file_unique_id,
+        Space.file_id,
+        Space.file_unique_id,
         file_path=str(data_file("local_file.txt")),
-        file_size=TestFile.file_size,
+        file_size=Space.file_size,
     )
     file.set_bot(bot)
     return file
 
 
-class TestFile:
+class Space:
     file_id = "NOTVALIDDOESNOTMATTER"
     file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
     file_path = (
@@ -94,6 +94,8 @@ class TestFile:
     file_size = 28232
     file_content = "Saint-Saëns".encode()  # Intentionally contains unicode chars.
 
+
+class TestFileNoReq:
     def test_slot_behaviour(self, file, mro_slots):
         for attr in file.__slots__:
             assert getattr(file, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -101,18 +103,18 @@ def test_slot_behaviour(self, file, mro_slots):
 
     def test_de_json(self, bot):
         json_dict = {
-            "file_id": self.file_id,
-            "file_unique_id": self.file_unique_id,
-            "file_path": self.file_path,
-            "file_size": self.file_size,
+            "file_id": Space.file_id,
+            "file_unique_id": Space.file_unique_id,
+            "file_path": Space.file_path,
+            "file_size": Space.file_size,
         }
         new_file = File.de_json(json_dict, bot)
         assert new_file.api_kwargs == {}
 
-        assert new_file.file_id == self.file_id
-        assert new_file.file_unique_id == self.file_unique_id
-        assert new_file.file_path == self.file_path
-        assert new_file.file_size == self.file_size
+        assert new_file.file_id == Space.file_id
+        assert new_file.file_unique_id == Space.file_unique_id
+        assert new_file.file_path == Space.file_path
+        assert new_file.file_size == Space.file_size
 
     def test_to_dict(self, file):
         file_dict = file.to_dict()
@@ -123,32 +125,24 @@ def test_to_dict(self, file):
         assert file_dict["file_path"] == file.file_path
         assert file_dict["file_size"] == file.file_size
 
-    @pytest.mark.flaky(3, 1)
-    async def test_error_get_empty_file_id(self, bot):
-        with pytest.raises(TelegramError):
-            await bot.get_file(file_id="")
-
     async def test_download(self, monkeypatch, file):
         async def test(*args, **kwargs):
-            return self.file_content
+            return Space.file_content
 
         monkeypatch.setattr(file.get_bot().request, "retrieve", test)
         out_file = await file.download_to_drive()
 
         try:
-            assert out_file.read_bytes() == self.file_content
+            assert out_file.read_bytes() == Space.file_content
         finally:
             out_file.unlink()
 
-    async def test_download_local_file(self, local_file):
-        assert await local_file.download_to_drive() == Path(local_file.file_path)
-
     @pytest.mark.parametrize(
         "custom_path_type", [str, Path], ids=["str custom_path", "pathlib.Path custom_path"]
     )
     async def test_download_custom_path(self, monkeypatch, file, custom_path_type):
         async def test(*args, **kwargs):
-            return self.file_content
+            return Space.file_content
 
         monkeypatch.setattr(file.get_bot().request, "retrieve", test)
         file_handle, custom_path = mkstemp()
@@ -156,28 +150,14 @@ async def test(*args, **kwargs):
         try:
             out_file = await file.download_to_drive(custom_path_type(custom_path))
             assert out_file == custom_path
-            assert out_file.read_bytes() == self.file_content
-        finally:
-            os.close(file_handle)
-            custom_path.unlink()
-
-    @pytest.mark.parametrize(
-        "custom_path_type", [str, Path], ids=["str custom_path", "pathlib.Path custom_path"]
-    )
-    async def test_download_custom_path_local_file(self, local_file, custom_path_type):
-        file_handle, custom_path = mkstemp()
-        custom_path = Path(custom_path)
-        try:
-            out_file = await local_file.download_to_drive(custom_path_type(custom_path))
-            assert out_file == custom_path
-            assert out_file.read_bytes() == self.file_content
+            assert out_file.read_bytes() == Space.file_content
         finally:
             os.close(file_handle)
             custom_path.unlink()
 
     async def test_download_no_filename(self, monkeypatch, file):
         async def test(*args, **kwargs):
-            return self.file_content
+            return Space.file_content
 
         file.file_path = None
 
@@ -186,35 +166,29 @@ async def test(*args, **kwargs):
 
         assert str(out_file)[-len(file.file_id) :] == file.file_id
         try:
-            assert out_file.read_bytes() == self.file_content
+            assert out_file.read_bytes() == Space.file_content
         finally:
             out_file.unlink()
 
     async def test_download_file_obj(self, monkeypatch, file):
         async def test(*args, **kwargs):
-            return self.file_content
+            return Space.file_content
 
         monkeypatch.setattr(file.get_bot().request, "retrieve", test)
         with TemporaryFile() as custom_fobj:
             await file.download_to_memory(out=custom_fobj)
             custom_fobj.seek(0)
-            assert custom_fobj.read() == self.file_content
-
-    async def test_download_file_obj_local_file(self, local_file):
-        with TemporaryFile() as custom_fobj:
-            await local_file.download_to_memory(out=custom_fobj)
-            custom_fobj.seek(0)
-            assert custom_fobj.read() == self.file_content
+            assert custom_fobj.read() == Space.file_content
 
     async def test_download_bytearray(self, monkeypatch, file):
         async def test(*args, **kwargs):
-            return self.file_content
+            return Space.file_content
 
         monkeypatch.setattr(file.get_bot().request, "retrieve", test)
 
         # Check that a download to a newly allocated bytearray works.
         buf = await file.download_as_bytearray()
-        assert buf == bytearray(self.file_content)
+        assert buf == bytearray(Space.file_content)
 
         # Check that a download to a given bytearray works (extends the bytearray).
         buf2 = buf[:]
@@ -223,18 +197,6 @@ async def test(*args, **kwargs):
         assert buf2[len(buf) :] == buf
         assert buf2[: len(buf)] == buf
 
-    async def test_download_bytearray_local_file(self, local_file):
-        # Check that a download to a newly allocated bytearray works.
-        buf = await local_file.download_as_bytearray()
-        assert buf == bytearray(self.file_content)
-
-        # Check that a download to a given bytearray works (extends the bytearray).
-        buf2 = buf[:]
-        buf3 = await local_file.download_as_bytearray(buf=buf2)
-        assert buf3 is buf2
-        assert buf2[len(buf) :] == buf
-        assert buf2[: len(buf)] == buf
-
     async def test_download_encrypted(self, monkeypatch, bot, encrypted_file):
         async def test(*args, **kwargs):
             return data_file("image_encrypted.jpg").read_bytes()
@@ -257,13 +219,6 @@ async def test(*args, **kwargs):
             custom_fobj.seek(0)
             assert custom_fobj.read() == data_file("image_decrypted.jpg").read_bytes()
 
-    async def test_download_local_file_encrypted(self, encrypted_local_file):
-        out_file = await encrypted_local_file.download_to_drive()
-        try:
-            assert out_file.read_bytes() == data_file("image_decrypted.jpg").read_bytes()
-        finally:
-            out_file.unlink()
-
     @pytest.mark.parametrize(
         "custom_path_type", [str, Path], ids=["str custom_path", "pathlib.Path custom_path"]
     )
@@ -307,24 +262,12 @@ async def test(*args, **kwargs):
         assert buf2[len(buf) :] == buf
         assert buf2[: len(buf)] == buf
 
-    async def test_download_bytearray_local_file_encrypted(self, encrypted_local_file):
-        # Check that a download to a newly allocated bytearray works.
-        buf = await encrypted_local_file.download_as_bytearray()
-        assert buf == bytearray(data_file("image_decrypted.jpg").read_bytes())
-
-        # Check that a download to a given bytearray works (extends the bytearray).
-        buf2 = buf[:]
-        buf3 = await encrypted_local_file.download_as_bytearray(buf=buf2)
-        assert buf3 is buf2
-        assert buf2[len(buf) :] == buf
-        assert buf2[: len(buf)] == buf
-
     def test_equality(self, bot):
-        a = File(self.file_id, self.file_unique_id, bot)
-        b = File("", self.file_unique_id, bot)
-        c = File(self.file_id, self.file_unique_id, None)
+        a = File(Space.file_id, Space.file_unique_id, bot)
+        b = File("", Space.file_unique_id, bot)
+        c = File(Space.file_id, Space.file_unique_id, None)
         d = File("", "", bot)
-        e = Voice(self.file_id, self.file_unique_id, 0)
+        e = Voice(Space.file_id, Space.file_unique_id, 0)
 
         assert a == b
         assert hash(a) == hash(b)
@@ -338,3 +281,63 @@ def test_equality(self, bot):
 
         assert a != e
         assert hash(a) != hash(e)
+
+
+class TestFileReq:
+    async def test_error_get_empty_file_id(self, bot):
+        with pytest.raises(TelegramError):
+            await bot.get_file(file_id="")
+
+    async def test_download_local_file(self, local_file):
+        assert await local_file.download_to_drive() == Path(local_file.file_path)
+
+    @pytest.mark.parametrize(
+        "custom_path_type", [str, Path], ids=["str custom_path", "pathlib.Path custom_path"]
+    )
+    async def test_download_custom_path_local_file(self, local_file, custom_path_type):
+        file_handle, custom_path = mkstemp()
+        custom_path = Path(custom_path)
+        try:
+            out_file = await local_file.download_to_drive(custom_path_type(custom_path))
+            assert out_file == custom_path
+            assert out_file.read_bytes() == Space.file_content
+        finally:
+            os.close(file_handle)
+            custom_path.unlink()
+
+    async def test_download_file_obj_local_file(self, local_file):
+        with TemporaryFile() as custom_fobj:
+            await local_file.download_to_memory(out=custom_fobj)
+            custom_fobj.seek(0)
+            assert custom_fobj.read() == Space.file_content
+
+    async def test_download_local_file_encrypted(self, encrypted_local_file):
+        out_file = await encrypted_local_file.download_to_drive()
+        try:
+            assert out_file.read_bytes() == data_file("image_decrypted.jpg").read_bytes()
+        finally:
+            out_file.unlink()
+
+    async def test_download_bytearray_local_file(self, local_file):
+        # Check that a download to a newly allocated bytearray works.
+        buf = await local_file.download_as_bytearray()
+        assert buf == bytearray(Space.file_content)
+
+        # Check that a download to a given bytearray works (extends the bytearray).
+        buf2 = buf[:]
+        buf3 = await local_file.download_as_bytearray(buf=buf2)
+        assert buf3 is buf2
+        assert buf2[len(buf) :] == buf
+        assert buf2[: len(buf)] == buf
+
+    async def test_download_bytearray_local_file_encrypted(self, encrypted_local_file):
+        # Check that a download to a newly allocated bytearray works.
+        buf = await encrypted_local_file.download_as_bytearray()
+        assert buf == bytearray(data_file("image_decrypted.jpg").read_bytes())
+
+        # Check that a download to a given bytearray works (extends the bytearray).
+        buf2 = buf[:]
+        buf3 = await encrypted_local_file.download_as_bytearray(buf=buf2)
+        assert buf3 is buf2
+        assert buf2[len(buf) :] == buf
+        assert buf2[: len(buf)] == buf
diff --git a/tests/test_forcereply.py b/tests/test_forcereply.py
index 1b41ddfa776..4585c0a2a5a 100644
--- a/tests/test_forcereply.py
+++ b/tests/test_forcereply.py
@@ -22,34 +22,27 @@
 from telegram import ForceReply, ReplyKeyboardRemove
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def force_reply():
-    return ForceReply(
-        TestForceReply.selective,
-        TestForceReply.input_field_placeholder,
-    )
+    return ForceReply(Space.selective, Space.input_field_placeholder)
 
 
-class TestForceReply:
+class Space:
     force_reply = True
     selective = True
     input_field_placeholder = "force replies can be annoying if not used properly"
 
+
+class TestForceReplyNoReq:
     def test_slot_behaviour(self, force_reply, mro_slots):
         for attr in force_reply.__slots__:
             assert getattr(force_reply, attr, "err") != "err", f"got extra slot '{attr}'"
         assert len(mro_slots(force_reply)) == len(set(mro_slots(force_reply))), "duplicate slot"
 
-    @pytest.mark.flaky(3, 1)
-    async def test_send_message_with_force_reply(self, bot, chat_id, force_reply):
-        message = await bot.send_message(chat_id, "text", reply_markup=force_reply)
-
-        assert message.text == "text"
-
     def test_expected(self, force_reply):
-        assert force_reply.force_reply == self.force_reply
-        assert force_reply.selective == self.selective
-        assert force_reply.input_field_placeholder == self.input_field_placeholder
+        assert force_reply.force_reply == Space.force_reply
+        assert force_reply.selective == Space.selective
+        assert force_reply.input_field_placeholder == Space.input_field_placeholder
 
     def test_to_dict(self, force_reply):
         force_reply_dict = force_reply.to_dict()
@@ -73,3 +66,9 @@ def test_equality(self):
 
         assert a != d
         assert hash(a) != hash(d)
+
+
+class TestForceReplyReq:
+    async def test_send_message_with_force_reply(self, bot, chat_id, force_reply):
+        message = await bot.send_message(chat_id, "text", reply_markup=force_reply)
+        assert message.text == "text"
diff --git a/tests/test_forum.py b/tests/test_forum.py
index d903d3e3d1a..bcd5122a970 100644
--- a/tests/test_forum.py
+++ b/tests/test_forum.py
@@ -16,6 +16,8 @@
 #
 # You should have received a copy of the GNU Lesser Public License
 # along with this program.  If not, see [http://www.gnu.org/licenses/].
+import asyncio
+
 import pytest
 
 from telegram import ForumTopic, ForumTopicClosed, ForumTopicCreated, ForumTopicReopened, Sticker
@@ -32,7 +34,7 @@ async def emoji_id(bot):
     return first_sticker.custom_emoji_id
 
 
-@pytest.fixture
+@pytest.fixture(scope="module")
 async def forum_topic_object(forum_group_id, emoji_id):
     return ForumTopic(
         message_thread_id=forum_group_id,
@@ -42,7 +44,7 @@ async def forum_topic_object(forum_group_id, emoji_id):
     )
 
 
-@pytest.fixture
+@pytest.fixture(scope="module")
 async def real_topic(bot, emoji_id, forum_group_id):
     result = await bot.create_forum_topic(
         chat_id=forum_group_id,
@@ -59,7 +61,7 @@ async def real_topic(bot, emoji_id, forum_group_id):
     assert result is True, "Topic was not deleted"
 
 
-class TestForumTopic:
+class TestForumTopicNoReq:
     def test_slot_behaviour(self, mro_slots, forum_topic_object):
         for attr in forum_topic_object.__slots__:
             assert getattr(forum_topic_object, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -139,7 +141,8 @@ def test_equality(self, emoji_id, forum_group_id):
         assert a != e
         assert hash(a) != hash(e)
 
-    @pytest.mark.flaky(3, 1)
+
+class TestForumTopicReq:
     async def test_create_forum_topic(self, real_topic):
         result = real_topic
         assert isinstance(result, ForumTopic)
@@ -161,7 +164,6 @@ async def test_create_forum_topic_with_only_required_args(self, bot, forum_group
         )
         assert result is True, "Failed to delete forum topic"
 
-    @pytest.mark.flaky(3, 1)
     async def test_get_forum_topic_icon_stickers(self, bot):
         emoji_sticker_list = await bot.get_forum_topic_icon_stickers()
         first_sticker = emoji_sticker_list[0]
@@ -194,7 +196,6 @@ async def test_edit_forum_topic(self, emoji_id, forum_group_id, bot, real_topic)
         assert result is True, "Failed to edit forum topic"
         # no way of checking the edited name, just the boolean result
 
-    @pytest.mark.flaky(3, 1)
     async def test_send_message_to_topic(self, bot, forum_group_id, real_topic):
         message_thread_id = real_topic.message_thread_id
 
@@ -226,31 +227,29 @@ async def test_close_and_reopen_forum_topic(self, bot, forum_group_id, real_topi
     @pytest.mark.xfail(reason="Can fail due to race conditions in GH actions CI")
     async def test_unpin_all_forum_topic_messages(self, bot, forum_group_id, real_topic):
         message_thread_id = real_topic.message_thread_id
+        pin_msg_tasks = set()
 
-        msgs = [
-            await (
-                await bot.send_message(
-                    chat_id=forum_group_id, text=TEST_MSG_TEXT, message_thread_id=message_thread_id
-                )
-            ).pin()
+        awaitables = {
+            bot.send_message(forum_group_id, TEST_MSG_TEXT, message_thread_id=message_thread_id)
             for _ in range(2)
-        ]
+        }
+        for coro in asyncio.as_completed(awaitables):
+            msg = await coro
+            pin_msg_tasks.add(asyncio.create_task(msg.pin()))
 
-        assert all(msgs) is True, "Message(s) were not pinned"
+        assert all([await task for task in pin_msg_tasks]) is True, "Message(s) were not pinned"
 
         # We need 2 or more pinned msgs for this to work, else we get Chat_not_modified error
-        result = await bot.unpin_all_forum_topic_messages(
-            chat_id=forum_group_id, message_thread_id=message_thread_id
-        )
+        result = await bot.unpin_all_forum_topic_messages(forum_group_id, message_thread_id)
         assert result is True, "Failed to unpin all the messages in forum topic"
 
 
-@pytest.fixture
+@pytest.fixture(scope="module")
 def topic_created():
     return ForumTopicCreated(name=TEST_TOPIC_NAME, icon_color=TEST_TOPIC_ICON_COLOR)
 
 
-class TestForumTopicCreated:
+class TestForumTopicCreatedNoReq:
     def test_slot_behaviour(self, topic_created, mro_slots):
         for attr in topic_created.__slots__:
             assert getattr(topic_created, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -299,7 +298,7 @@ def test_equality(self, emoji_id):
         assert hash(a) != hash(d)
 
 
-class TestForumTopicClosed:
+class TestForumTopicClosedNoReq:
     def test_slot_behaviour(self, mro_slots):
         action = ForumTopicClosed()
         for attr in action.__slots__:
@@ -317,7 +316,7 @@ def test_to_dict(self):
         assert action_dict == {}
 
 
-class TestForumTopicReopened:
+class TestForumTopicReopenedNoReq:
     def test_slot_behaviour(self, mro_slots):
         action = ForumTopicReopened()
         for attr in action.__slots__:
diff --git a/tests/test_game.py b/tests/test_game.py
index dc775016467..9c63cac0a29 100644
--- a/tests/test_game.py
+++ b/tests/test_game.py
@@ -22,21 +22,21 @@
 from telegram import Animation, Game, MessageEntity, PhotoSize
 
 
-@pytest.fixture(scope="function")
+@pytest.fixture(scope="module")
 def game():
     game = Game(
-        TestGame.title,
-        TestGame.description,
-        TestGame.photo,
-        text=TestGame.text,
-        text_entities=TestGame.text_entities,
-        animation=TestGame.animation,
+        Space.title,
+        Space.description,
+        Space.photo,
+        text=Space.text,
+        text_entities=Space.text_entities,
+        animation=Space.animation,
     )
     game._unfreeze()
     return game
 
 
-class TestGame:
+class Space:
     title = "Python-telegram-bot Test Game"
     description = "description"
     photo = [PhotoSize("Blah", "ElseBlah", 640, 360, file_size=0)]
@@ -47,6 +47,8 @@ class TestGame:
     text_entities = [MessageEntity(13, 17, MessageEntity.URL)]
     animation = Animation("blah", "unique_id", 320, 180, 1)
 
+
+class TestGameNoReq:
     def test_slot_behaviour(self, game, mro_slots):
         for attr in game.__slots__:
             assert getattr(game, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -54,35 +56,35 @@ def test_slot_behaviour(self, game, mro_slots):
 
     def test_de_json_required(self, bot):
         json_dict = {
-            "title": self.title,
-            "description": self.description,
-            "photo": [self.photo[0].to_dict()],
+            "title": Space.title,
+            "description": Space.description,
+            "photo": [Space.photo[0].to_dict()],
         }
         game = Game.de_json(json_dict, bot)
         assert game.api_kwargs == {}
 
-        assert game.title == self.title
-        assert game.description == self.description
-        assert game.photo == tuple(self.photo)
+        assert game.title == Space.title
+        assert game.description == Space.description
+        assert game.photo == tuple(Space.photo)
 
     def test_de_json_all(self, bot):
         json_dict = {
-            "title": self.title,
-            "description": self.description,
-            "photo": [self.photo[0].to_dict()],
-            "text": self.text,
-            "text_entities": [self.text_entities[0].to_dict()],
-            "animation": self.animation.to_dict(),
+            "title": Space.title,
+            "description": Space.description,
+            "photo": [Space.photo[0].to_dict()],
+            "text": Space.text,
+            "text_entities": [Space.text_entities[0].to_dict()],
+            "animation": Space.animation.to_dict(),
         }
         game = Game.de_json(json_dict, bot)
         assert game.api_kwargs == {}
 
-        assert game.title == self.title
-        assert game.description == self.description
-        assert game.photo == tuple(self.photo)
-        assert game.text == self.text
-        assert game.text_entities == tuple(self.text_entities)
-        assert game.animation == self.animation
+        assert game.title == Space.title
+        assert game.description == Space.description
+        assert game.photo == tuple(Space.photo)
+        assert game.text == Space.text
+        assert game.text_entities == tuple(Space.text_entities)
+        assert game.animation == Space.animation
 
     def test_to_dict(self, game):
         game_dict = game.to_dict()
diff --git a/tests/test_gamehighscore.py b/tests/test_gamehighscore.py
index 43ebbe99312..669ddf2d62f 100644
--- a/tests/test_gamehighscore.py
+++ b/tests/test_gamehighscore.py
@@ -22,31 +22,35 @@
 from telegram import GameHighScore, User
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def game_highscore():
-    return GameHighScore(
-        TestGameHighScore.position, TestGameHighScore.user, TestGameHighScore.score
-    )
+    return GameHighScore(Space.position, Space.user, Space.score)
 
 
-class TestGameHighScore:
+class Space:
     position = 12
     user = User(2, "test user", False)
     score = 42
 
+
+class TestGameHighScoreNoReq:
     def test_slot_behaviour(self, game_highscore, mro_slots):
         for attr in game_highscore.__slots__:
             assert getattr(game_highscore, attr, "err") != "err", f"got extra slot '{attr}'"
         assert len(mro_slots(game_highscore)) == len(set(mro_slots(game_highscore))), "same slot"
 
     def test_de_json(self, bot):
-        json_dict = {"position": self.position, "user": self.user.to_dict(), "score": self.score}
+        json_dict = {
+            "position": Space.position,
+            "user": Space.user.to_dict(),
+            "score": Space.score,
+        }
         highscore = GameHighScore.de_json(json_dict, bot)
         assert highscore.api_kwargs == {}
 
-        assert highscore.position == self.position
-        assert highscore.user == self.user
-        assert highscore.score == self.score
+        assert highscore.position == Space.position
+        assert highscore.user == Space.user
+        assert highscore.score == Space.score
 
         assert GameHighScore.de_json(None, bot) is None
 
diff --git a/tests/test_inlinekeyboardbutton.py b/tests/test_inlinekeyboardbutton.py
index dad079ead7a..d4e64e7cff1 100644
--- a/tests/test_inlinekeyboardbutton.py
+++ b/tests/test_inlinekeyboardbutton.py
@@ -22,22 +22,22 @@
 from telegram import CallbackGame, InlineKeyboardButton, LoginUrl, WebAppInfo
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_keyboard_button():
     return InlineKeyboardButton(
-        TestInlineKeyboardButton.text,
-        url=TestInlineKeyboardButton.url,
-        callback_data=TestInlineKeyboardButton.callback_data,
-        switch_inline_query=TestInlineKeyboardButton.switch_inline_query,
-        switch_inline_query_current_chat=TestInlineKeyboardButton.switch_inline_query_current_chat,
-        callback_game=TestInlineKeyboardButton.callback_game,
-        pay=TestInlineKeyboardButton.pay,
-        login_url=TestInlineKeyboardButton.login_url,
-        web_app=TestInlineKeyboardButton.web_app,
+        Space.text,
+        url=Space.url,
+        callback_data=Space.callback_data,
+        switch_inline_query=Space.switch_inline_query,
+        switch_inline_query_current_chat=Space.switch_inline_query_current_chat,
+        callback_game=Space.callback_game,
+        pay=Space.pay,
+        login_url=Space.login_url,
+        web_app=Space.web_app,
     )
 
 
-class TestInlineKeyboardButton:
+class Space:
     text = "text"
     url = "url"
     callback_data = "callback data"
@@ -48,6 +48,8 @@ class TestInlineKeyboardButton:
     login_url = LoginUrl("http://google.com")
     web_app = WebAppInfo(url="https://example.com")
 
+
+class TestInlineKeyboardButtonNoReq:
     def test_slot_behaviour(self, inline_keyboard_button, mro_slots):
         inst = inline_keyboard_button
         for attr in inst.__slots__:
@@ -55,18 +57,18 @@ def test_slot_behaviour(self, inline_keyboard_button, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, inline_keyboard_button):
-        assert inline_keyboard_button.text == self.text
-        assert inline_keyboard_button.url == self.url
-        assert inline_keyboard_button.callback_data == self.callback_data
-        assert inline_keyboard_button.switch_inline_query == self.switch_inline_query
+        assert inline_keyboard_button.text == Space.text
+        assert inline_keyboard_button.url == Space.url
+        assert inline_keyboard_button.callback_data == Space.callback_data
+        assert inline_keyboard_button.switch_inline_query == Space.switch_inline_query
         assert (
             inline_keyboard_button.switch_inline_query_current_chat
-            == self.switch_inline_query_current_chat
+            == Space.switch_inline_query_current_chat
         )
         assert isinstance(inline_keyboard_button.callback_game, CallbackGame)
-        assert inline_keyboard_button.pay == self.pay
-        assert inline_keyboard_button.login_url == self.login_url
-        assert inline_keyboard_button.web_app == self.web_app
+        assert inline_keyboard_button.pay == Space.pay
+        assert inline_keyboard_button.login_url == Space.login_url
+        assert inline_keyboard_button.web_app == Space.web_app
 
     def test_to_dict(self, inline_keyboard_button):
         inline_keyboard_button_dict = inline_keyboard_button.to_dict()
@@ -95,32 +97,32 @@ def test_to_dict(self, inline_keyboard_button):
 
     def test_de_json(self, bot):
         json_dict = {
-            "text": self.text,
-            "url": self.url,
-            "callback_data": self.callback_data,
-            "switch_inline_query": self.switch_inline_query,
-            "switch_inline_query_current_chat": self.switch_inline_query_current_chat,
-            "callback_game": self.callback_game.to_dict(),
-            "web_app": self.web_app.to_dict(),
-            "login_url": self.login_url.to_dict(),
-            "pay": self.pay,
+            "text": Space.text,
+            "url": Space.url,
+            "callback_data": Space.callback_data,
+            "switch_inline_query": Space.switch_inline_query,
+            "switch_inline_query_current_chat": Space.switch_inline_query_current_chat,
+            "callback_game": Space.callback_game.to_dict(),
+            "web_app": Space.web_app.to_dict(),
+            "login_url": Space.login_url.to_dict(),
+            "pay": Space.pay,
         }
 
         inline_keyboard_button = InlineKeyboardButton.de_json(json_dict, None)
         assert inline_keyboard_button.api_kwargs == {}
-        assert inline_keyboard_button.text == self.text
-        assert inline_keyboard_button.url == self.url
-        assert inline_keyboard_button.callback_data == self.callback_data
-        assert inline_keyboard_button.switch_inline_query == self.switch_inline_query
+        assert inline_keyboard_button.text == Space.text
+        assert inline_keyboard_button.url == Space.url
+        assert inline_keyboard_button.callback_data == Space.callback_data
+        assert inline_keyboard_button.switch_inline_query == Space.switch_inline_query
         assert (
             inline_keyboard_button.switch_inline_query_current_chat
-            == self.switch_inline_query_current_chat
+            == Space.switch_inline_query_current_chat
         )
         # CallbackGame has empty _id_attrs, so just test if the class is created.
         assert isinstance(inline_keyboard_button.callback_game, CallbackGame)
-        assert inline_keyboard_button.pay == self.pay
-        assert inline_keyboard_button.login_url == self.login_url
-        assert inline_keyboard_button.web_app == self.web_app
+        assert inline_keyboard_button.pay == Space.pay
+        assert inline_keyboard_button.login_url == Space.login_url
+        assert inline_keyboard_button.web_app == Space.web_app
 
         none = InlineKeyboardButton.de_json({}, bot)
         assert none is None
diff --git a/tests/test_inlinekeyboardmarkup.py b/tests/test_inlinekeyboardmarkup.py
index d852f685bf7..1c63e14624d 100644
--- a/tests/test_inlinekeyboardmarkup.py
+++ b/tests/test_inlinekeyboardmarkup.py
@@ -28,12 +28,12 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_keyboard_markup():
-    return InlineKeyboardMarkup(TestInlineKeyboardMarkup.inline_keyboard)
+    return InlineKeyboardMarkup(Space.inline_keyboard)
 
 
-class TestInlineKeyboardMarkup:
+class Space:
     inline_keyboard = [
         [
             InlineKeyboardButton(text="button1", callback_data="data1"),
@@ -41,22 +41,14 @@ class TestInlineKeyboardMarkup:
         ]
     ]
 
+
+class TestInlineKeyboardMarkupNoReq:
     def test_slot_behaviour(self, inline_keyboard_markup, mro_slots):
         inst = inline_keyboard_markup
         for attr in inst.__slots__:
             assert getattr(inst, attr, "err") != "err", f"got extra slot '{attr}'"
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
-    @pytest.mark.flaky(3, 1)
-    async def test_send_message_with_inline_keyboard_markup(
-        self, bot, chat_id, inline_keyboard_markup
-    ):
-        message = await bot.send_message(
-            chat_id, "Testing InlineKeyboardMarkup", reply_markup=inline_keyboard_markup
-        )
-
-        assert message.text == "Testing InlineKeyboardMarkup"
-
     def test_from_button(self):
         inline_keyboard_markup = InlineKeyboardMarkup.from_button(
             InlineKeyboardButton(text="button1", callback_data="data1")
@@ -87,7 +79,7 @@ def test_from_column(self):
 
     def test_expected_values(self, inline_keyboard_markup):
         assert inline_keyboard_markup.inline_keyboard == tuple(
-            tuple(row) for row in self.inline_keyboard
+            tuple(row) for row in Space.inline_keyboard
         )
 
     def test_wrong_keyboard_inputs(self):
@@ -142,7 +134,7 @@ def test_to_dict(self, inline_keyboard_markup):
 
         assert isinstance(inline_keyboard_markup_dict, dict)
         assert inline_keyboard_markup_dict["inline_keyboard"] == [
-            [self.inline_keyboard[0][0].to_dict(), self.inline_keyboard[0][1].to_dict()]
+            [Space.inline_keyboard[0][0].to_dict(), Space.inline_keyboard[0][1].to_dict()]
         ]
 
     def test_de_json(self):
@@ -231,3 +223,14 @@ def test_equality(self):
 
         assert a != g
         assert hash(a) != hash(g)
+
+
+class TestInlineKeyborardMarkupReq:
+    async def test_send_message_with_inline_keyboard_markup(
+        self, bot, chat_id, inline_keyboard_markup
+    ):
+        message = await bot.send_message(
+            chat_id, "Testing InlineKeyboardMarkup", reply_markup=inline_keyboard_markup
+        )
+
+        assert message.text == "Testing InlineKeyboardMarkup"
diff --git a/tests/test_inlinequery.py b/tests/test_inlinequery.py
index 86d14453092..a99cd6ee42b 100644
--- a/tests/test_inlinequery.py
+++ b/tests/test_inlinequery.py
@@ -27,26 +27,28 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query(bot):
     ilq = InlineQuery(
-        TestInlineQuery.id_,
-        TestInlineQuery.from_user,
-        TestInlineQuery.query,
-        TestInlineQuery.offset,
-        location=TestInlineQuery.location,
+        Space.id_,
+        Space.from_user,
+        Space.query,
+        Space.offset,
+        location=Space.location,
     )
     ilq.set_bot(bot)
     return ilq
 
 
-class TestInlineQuery:
+class Space:
     id_ = 1234
     from_user = User(1, "First name", False)
     query = "query text"
     offset = "offset"
     location = Location(8.8, 53.1)
 
+
+class TestInlineQueryNoReq:
     def test_slot_behaviour(self, inline_query, mro_slots):
         for attr in inline_query.__slots__:
             assert getattr(inline_query, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -54,20 +56,20 @@ def test_slot_behaviour(self, inline_query, mro_slots):
 
     def test_de_json(self, bot):
         json_dict = {
-            "id": self.id_,
-            "from": self.from_user.to_dict(),
-            "query": self.query,
-            "offset": self.offset,
-            "location": self.location.to_dict(),
+            "id": Space.id_,
+            "from": Space.from_user.to_dict(),
+            "query": Space.query,
+            "offset": Space.offset,
+            "location": Space.location.to_dict(),
         }
         inline_query_json = InlineQuery.de_json(json_dict, bot)
         assert inline_query_json.api_kwargs == {}
 
-        assert inline_query_json.id == self.id_
-        assert inline_query_json.from_user == self.from_user
-        assert inline_query_json.location == self.location
-        assert inline_query_json.query == self.query
-        assert inline_query_json.offset == self.offset
+        assert inline_query_json.id == Space.id_
+        assert inline_query_json.from_user == Space.from_user
+        assert inline_query_json.location == Space.location
+        assert inline_query_json.query == Space.query
+        assert inline_query_json.offset == Space.offset
 
     def test_to_dict(self, inline_query):
         inline_query_dict = inline_query.to_dict()
@@ -108,11 +110,11 @@ async def make_assertion(*_, **kwargs):
         assert await inline_query.answer(results=[], auto_pagination=True)
 
     def test_equality(self):
-        a = InlineQuery(self.id_, User(1, "", False), "", "")
-        b = InlineQuery(self.id_, User(1, "", False), "", "")
-        c = InlineQuery(self.id_, User(0, "", False), "", "")
+        a = InlineQuery(Space.id_, User(1, "", False), "", "")
+        b = InlineQuery(Space.id_, User(1, "", False), "", "")
+        c = InlineQuery(Space.id_, User(0, "", False), "", "")
         d = InlineQuery(0, User(1, "", False), "", "")
-        e = Update(self.id_)
+        e = Update(Space.id_)
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inlinequeryresultarticle.py b/tests/test_inlinequeryresultarticle.py
index 67626d54c38..3d93580f976 100644
--- a/tests/test_inlinequeryresultarticle.py
+++ b/tests/test_inlinequeryresultarticle.py
@@ -28,23 +28,23 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query_result_article():
     return InlineQueryResultArticle(
-        TestInlineQueryResultArticle.id_,
-        TestInlineQueryResultArticle.title,
-        input_message_content=TestInlineQueryResultArticle.input_message_content,
-        reply_markup=TestInlineQueryResultArticle.reply_markup,
-        url=TestInlineQueryResultArticle.url,
-        hide_url=TestInlineQueryResultArticle.hide_url,
-        description=TestInlineQueryResultArticle.description,
-        thumb_url=TestInlineQueryResultArticle.thumb_url,
-        thumb_height=TestInlineQueryResultArticle.thumb_height,
-        thumb_width=TestInlineQueryResultArticle.thumb_width,
+        Space.id_,
+        Space.title,
+        input_message_content=Space.input_message_content,
+        reply_markup=Space.reply_markup,
+        url=Space.url,
+        hide_url=Space.hide_url,
+        description=Space.description,
+        thumb_url=Space.thumb_url,
+        thumb_height=Space.thumb_height,
+        thumb_width=Space.thumb_width,
     )
 
 
-class TestInlineQueryResultArticle:
+class Space:
     id_ = "id"
     type_ = "article"
     title = "title"
@@ -57,6 +57,8 @@ class TestInlineQueryResultArticle:
     thumb_height = 10
     thumb_width = 15
 
+
+class TestInlineQueryResultArticleNoReq:
     def test_slot_behaviour(self, inline_query_result_article, mro_slots, recwarn):
         inst = inline_query_result_article
         for attr in inst.__slots__:
@@ -64,20 +66,20 @@ def test_slot_behaviour(self, inline_query_result_article, mro_slots, recwarn):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, inline_query_result_article):
-        assert inline_query_result_article.type == self.type_
-        assert inline_query_result_article.id == self.id_
-        assert inline_query_result_article.title == self.title
+        assert inline_query_result_article.type == Space.type_
+        assert inline_query_result_article.id == Space.id_
+        assert inline_query_result_article.title == Space.title
         assert (
             inline_query_result_article.input_message_content.to_dict()
-            == self.input_message_content.to_dict()
+            == Space.input_message_content.to_dict()
         )
-        assert inline_query_result_article.reply_markup.to_dict() == self.reply_markup.to_dict()
-        assert inline_query_result_article.url == self.url
-        assert inline_query_result_article.hide_url == self.hide_url
-        assert inline_query_result_article.description == self.description
-        assert inline_query_result_article.thumb_url == self.thumb_url
-        assert inline_query_result_article.thumb_height == self.thumb_height
-        assert inline_query_result_article.thumb_width == self.thumb_width
+        assert inline_query_result_article.reply_markup.to_dict() == Space.reply_markup.to_dict()
+        assert inline_query_result_article.url == Space.url
+        assert inline_query_result_article.hide_url == Space.hide_url
+        assert inline_query_result_article.description == Space.description
+        assert inline_query_result_article.thumb_url == Space.thumb_url
+        assert inline_query_result_article.thumb_height == Space.thumb_height
+        assert inline_query_result_article.thumb_width == Space.thumb_width
 
     def test_to_dict(self, inline_query_result_article):
         inline_query_result_article_dict = inline_query_result_article.to_dict()
@@ -113,11 +115,11 @@ def test_to_dict(self, inline_query_result_article):
         )
 
     def test_equality(self):
-        a = InlineQueryResultArticle(self.id_, self.title, self.input_message_content)
-        b = InlineQueryResultArticle(self.id_, self.title, self.input_message_content)
-        c = InlineQueryResultArticle(self.id_, "", self.input_message_content)
-        d = InlineQueryResultArticle("", self.title, self.input_message_content)
-        e = InlineQueryResultAudio(self.id_, "", "")
+        a = InlineQueryResultArticle(Space.id_, Space.title, Space.input_message_content)
+        b = InlineQueryResultArticle(Space.id_, Space.title, Space.input_message_content)
+        c = InlineQueryResultArticle(Space.id_, "", Space.input_message_content)
+        d = InlineQueryResultArticle("", Space.title, Space.input_message_content)
+        e = InlineQueryResultAudio(Space.id_, "", "")
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inlinequeryresultaudio.py b/tests/test_inlinequeryresultaudio.py
index e7056f62465..a0b084d153f 100644
--- a/tests/test_inlinequeryresultaudio.py
+++ b/tests/test_inlinequeryresultaudio.py
@@ -29,23 +29,23 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query_result_audio():
     return InlineQueryResultAudio(
-        TestInlineQueryResultAudio.id_,
-        TestInlineQueryResultAudio.audio_url,
-        TestInlineQueryResultAudio.title,
-        performer=TestInlineQueryResultAudio.performer,
-        audio_duration=TestInlineQueryResultAudio.audio_duration,
-        caption=TestInlineQueryResultAudio.caption,
-        parse_mode=TestInlineQueryResultAudio.parse_mode,
-        caption_entities=TestInlineQueryResultAudio.caption_entities,
-        input_message_content=TestInlineQueryResultAudio.input_message_content,
-        reply_markup=TestInlineQueryResultAudio.reply_markup,
+        Space.id_,
+        Space.audio_url,
+        Space.title,
+        performer=Space.performer,
+        audio_duration=Space.audio_duration,
+        caption=Space.caption,
+        parse_mode=Space.parse_mode,
+        caption_entities=Space.caption_entities,
+        input_message_content=Space.input_message_content,
+        reply_markup=Space.reply_markup,
     )
 
 
-class TestInlineQueryResultAudio:
+class Space:
     id_ = "id"
     type_ = "audio"
     audio_url = "audio url"
@@ -58,6 +58,8 @@ class TestInlineQueryResultAudio:
     input_message_content = InputTextMessageContent("input_message_content")
     reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
 
+
+class TestInlineQueryResultAudioNoReq:
     def test_slot_behaviour(self, inline_query_result_audio, mro_slots):
         inst = inline_query_result_audio
         for attr in inst.__slots__:
@@ -65,20 +67,20 @@ def test_slot_behaviour(self, inline_query_result_audio, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, inline_query_result_audio):
-        assert inline_query_result_audio.type == self.type_
-        assert inline_query_result_audio.id == self.id_
-        assert inline_query_result_audio.audio_url == self.audio_url
-        assert inline_query_result_audio.title == self.title
-        assert inline_query_result_audio.performer == self.performer
-        assert inline_query_result_audio.audio_duration == self.audio_duration
-        assert inline_query_result_audio.caption == self.caption
-        assert inline_query_result_audio.parse_mode == self.parse_mode
-        assert inline_query_result_audio.caption_entities == tuple(self.caption_entities)
+        assert inline_query_result_audio.type == Space.type_
+        assert inline_query_result_audio.id == Space.id_
+        assert inline_query_result_audio.audio_url == Space.audio_url
+        assert inline_query_result_audio.title == Space.title
+        assert inline_query_result_audio.performer == Space.performer
+        assert inline_query_result_audio.audio_duration == Space.audio_duration
+        assert inline_query_result_audio.caption == Space.caption
+        assert inline_query_result_audio.parse_mode == Space.parse_mode
+        assert inline_query_result_audio.caption_entities == tuple(Space.caption_entities)
         assert (
             inline_query_result_audio.input_message_content.to_dict()
-            == self.input_message_content.to_dict()
+            == Space.input_message_content.to_dict()
         )
-        assert inline_query_result_audio.reply_markup.to_dict() == self.reply_markup.to_dict()
+        assert inline_query_result_audio.reply_markup.to_dict() == Space.reply_markup.to_dict()
 
     def test_to_dict(self, inline_query_result_audio):
         inline_query_result_audio_dict = inline_query_result_audio.to_dict()
@@ -108,15 +110,15 @@ def test_to_dict(self, inline_query_result_audio):
         )
 
     def test_caption_entities_always_tuple(self):
-        inline_query_result_audio = InlineQueryResultAudio(self.id_, self.audio_url, self.title)
+        inline_query_result_audio = InlineQueryResultAudio(Space.id_, Space.audio_url, Space.title)
         assert inline_query_result_audio.caption_entities == ()
 
     def test_equality(self):
-        a = InlineQueryResultAudio(self.id_, self.audio_url, self.title)
-        b = InlineQueryResultAudio(self.id_, self.title, self.title)
-        c = InlineQueryResultAudio(self.id_, "", self.title)
-        d = InlineQueryResultAudio("", self.audio_url, self.title)
-        e = InlineQueryResultVoice(self.id_, "", "")
+        a = InlineQueryResultAudio(Space.id_, Space.audio_url, Space.title)
+        b = InlineQueryResultAudio(Space.id_, Space.title, Space.title)
+        c = InlineQueryResultAudio(Space.id_, "", Space.title)
+        d = InlineQueryResultAudio("", Space.audio_url, Space.title)
+        e = InlineQueryResultVoice(Space.id_, "", "")
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inlinequeryresultcachedaudio.py b/tests/test_inlinequeryresultcachedaudio.py
index ac654e915a5..d1c56de3403 100644
--- a/tests/test_inlinequeryresultcachedaudio.py
+++ b/tests/test_inlinequeryresultcachedaudio.py
@@ -29,20 +29,20 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query_result_cached_audio():
     return InlineQueryResultCachedAudio(
-        TestInlineQueryResultCachedAudio.id_,
-        TestInlineQueryResultCachedAudio.audio_file_id,
-        caption=TestInlineQueryResultCachedAudio.caption,
-        parse_mode=TestInlineQueryResultCachedAudio.parse_mode,
-        caption_entities=TestInlineQueryResultCachedAudio.caption_entities,
-        input_message_content=TestInlineQueryResultCachedAudio.input_message_content,
-        reply_markup=TestInlineQueryResultCachedAudio.reply_markup,
+        Space.id_,
+        Space.audio_file_id,
+        caption=Space.caption,
+        parse_mode=Space.parse_mode,
+        caption_entities=Space.caption_entities,
+        input_message_content=Space.input_message_content,
+        reply_markup=Space.reply_markup,
     )
 
 
-class TestInlineQueryResultCachedAudio:
+class Space:
     id_ = "id"
     type_ = "audio"
     audio_file_id = "audio file id"
@@ -52,6 +52,8 @@ class TestInlineQueryResultCachedAudio:
     input_message_content = InputTextMessageContent("input_message_content")
     reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
 
+
+class TestInlineQueryResultCachedAudioNoReq:
     def test_slot_behaviour(self, inline_query_result_cached_audio, mro_slots):
         inst = inline_query_result_cached_audio
         for attr in inst.__slots__:
@@ -59,22 +61,22 @@ def test_slot_behaviour(self, inline_query_result_cached_audio, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, inline_query_result_cached_audio):
-        assert inline_query_result_cached_audio.type == self.type_
-        assert inline_query_result_cached_audio.id == self.id_
-        assert inline_query_result_cached_audio.audio_file_id == self.audio_file_id
-        assert inline_query_result_cached_audio.caption == self.caption
-        assert inline_query_result_cached_audio.parse_mode == self.parse_mode
-        assert inline_query_result_cached_audio.caption_entities == tuple(self.caption_entities)
+        assert inline_query_result_cached_audio.type == Space.type_
+        assert inline_query_result_cached_audio.id == Space.id_
+        assert inline_query_result_cached_audio.audio_file_id == Space.audio_file_id
+        assert inline_query_result_cached_audio.caption == Space.caption
+        assert inline_query_result_cached_audio.parse_mode == Space.parse_mode
+        assert inline_query_result_cached_audio.caption_entities == tuple(Space.caption_entities)
         assert (
             inline_query_result_cached_audio.input_message_content.to_dict()
-            == self.input_message_content.to_dict()
+            == Space.input_message_content.to_dict()
         )
         assert (
-            inline_query_result_cached_audio.reply_markup.to_dict() == self.reply_markup.to_dict()
+            inline_query_result_cached_audio.reply_markup.to_dict() == Space.reply_markup.to_dict()
         )
 
     def test_caption_entities_always_tuple(self):
-        audio = InlineQueryResultCachedAudio(self.id_, self.audio_file_id)
+        audio = InlineQueryResultCachedAudio(Space.id_, Space.audio_file_id)
         assert audio.caption_entities == ()
 
     def test_to_dict(self, inline_query_result_cached_audio):
@@ -110,11 +112,11 @@ def test_to_dict(self, inline_query_result_cached_audio):
         )
 
     def test_equality(self):
-        a = InlineQueryResultCachedAudio(self.id_, self.audio_file_id)
-        b = InlineQueryResultCachedAudio(self.id_, self.audio_file_id)
-        c = InlineQueryResultCachedAudio(self.id_, "")
-        d = InlineQueryResultCachedAudio("", self.audio_file_id)
-        e = InlineQueryResultCachedVoice(self.id_, "", "")
+        a = InlineQueryResultCachedAudio(Space.id_, Space.audio_file_id)
+        b = InlineQueryResultCachedAudio(Space.id_, Space.audio_file_id)
+        c = InlineQueryResultCachedAudio(Space.id_, "")
+        d = InlineQueryResultCachedAudio("", Space.audio_file_id)
+        e = InlineQueryResultCachedVoice(Space.id_, "", "")
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inlinequeryresultcacheddocument.py b/tests/test_inlinequeryresultcacheddocument.py
index e728d333d17..8c0edb485e4 100644
--- a/tests/test_inlinequeryresultcacheddocument.py
+++ b/tests/test_inlinequeryresultcacheddocument.py
@@ -29,22 +29,22 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query_result_cached_document():
     return InlineQueryResultCachedDocument(
-        TestInlineQueryResultCachedDocument.id_,
-        TestInlineQueryResultCachedDocument.title,
-        TestInlineQueryResultCachedDocument.document_file_id,
-        caption=TestInlineQueryResultCachedDocument.caption,
-        parse_mode=TestInlineQueryResultCachedDocument.parse_mode,
-        caption_entities=TestInlineQueryResultCachedDocument.caption_entities,
-        description=TestInlineQueryResultCachedDocument.description,
-        input_message_content=TestInlineQueryResultCachedDocument.input_message_content,
-        reply_markup=TestInlineQueryResultCachedDocument.reply_markup,
+        Space.id_,
+        Space.title,
+        Space.document_file_id,
+        caption=Space.caption,
+        parse_mode=Space.parse_mode,
+        caption_entities=Space.caption_entities,
+        description=Space.description,
+        input_message_content=Space.input_message_content,
+        reply_markup=Space.reply_markup,
     )
 
 
-class TestInlineQueryResultCachedDocument:
+class Space:
     id_ = "id"
     type_ = "document"
     document_file_id = "document file id"
@@ -56,6 +56,8 @@ class TestInlineQueryResultCachedDocument:
     input_message_content = InputTextMessageContent("input_message_content")
     reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
 
+
+class TestInlineQueryResultCachedDocumentNoReq:
     def test_slot_behaviour(self, inline_query_result_cached_document, mro_slots):
         inst = inline_query_result_cached_document
         for attr in inst.__slots__:
@@ -63,25 +65,27 @@ def test_slot_behaviour(self, inline_query_result_cached_document, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, inline_query_result_cached_document):
-        assert inline_query_result_cached_document.id == self.id_
-        assert inline_query_result_cached_document.type == self.type_
-        assert inline_query_result_cached_document.document_file_id == self.document_file_id
-        assert inline_query_result_cached_document.title == self.title
-        assert inline_query_result_cached_document.caption == self.caption
-        assert inline_query_result_cached_document.parse_mode == self.parse_mode
-        assert inline_query_result_cached_document.caption_entities == tuple(self.caption_entities)
-        assert inline_query_result_cached_document.description == self.description
+        assert inline_query_result_cached_document.id == Space.id_
+        assert inline_query_result_cached_document.type == Space.type_
+        assert inline_query_result_cached_document.document_file_id == Space.document_file_id
+        assert inline_query_result_cached_document.title == Space.title
+        assert inline_query_result_cached_document.caption == Space.caption
+        assert inline_query_result_cached_document.parse_mode == Space.parse_mode
+        assert inline_query_result_cached_document.caption_entities == tuple(
+            Space.caption_entities
+        )
+        assert inline_query_result_cached_document.description == Space.description
         assert (
             inline_query_result_cached_document.input_message_content.to_dict()
-            == self.input_message_content.to_dict()
+            == Space.input_message_content.to_dict()
         )
         assert (
             inline_query_result_cached_document.reply_markup.to_dict()
-            == self.reply_markup.to_dict()
+            == Space.reply_markup.to_dict()
         )
 
     def test_caption_entities_always_tuple(self):
-        test = InlineQueryResultCachedDocument(self.id_, self.title, self.document_file_id)
+        test = InlineQueryResultCachedDocument(Space.id_, Space.title, Space.document_file_id)
         assert test.caption_entities == ()
 
     def test_to_dict(self, inline_query_result_cached_document):
@@ -129,11 +133,11 @@ def test_to_dict(self, inline_query_result_cached_document):
         )
 
     def test_equality(self):
-        a = InlineQueryResultCachedDocument(self.id_, self.title, self.document_file_id)
-        b = InlineQueryResultCachedDocument(self.id_, self.title, self.document_file_id)
-        c = InlineQueryResultCachedDocument(self.id_, self.title, "")
-        d = InlineQueryResultCachedDocument("", self.title, self.document_file_id)
-        e = InlineQueryResultCachedVoice(self.id_, "", "")
+        a = InlineQueryResultCachedDocument(Space.id_, Space.title, Space.document_file_id)
+        b = InlineQueryResultCachedDocument(Space.id_, Space.title, Space.document_file_id)
+        c = InlineQueryResultCachedDocument(Space.id_, Space.title, "")
+        d = InlineQueryResultCachedDocument("", Space.title, Space.document_file_id)
+        e = InlineQueryResultCachedVoice(Space.id_, "", "")
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inlinequeryresultcachedgif.py b/tests/test_inlinequeryresultcachedgif.py
index 7af70a7daa7..0cb3375ab67 100644
--- a/tests/test_inlinequeryresultcachedgif.py
+++ b/tests/test_inlinequeryresultcachedgif.py
@@ -28,21 +28,21 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query_result_cached_gif():
     return InlineQueryResultCachedGif(
-        TestInlineQueryResultCachedGif.id_,
-        TestInlineQueryResultCachedGif.gif_file_id,
-        title=TestInlineQueryResultCachedGif.title,
-        caption=TestInlineQueryResultCachedGif.caption,
-        parse_mode=TestInlineQueryResultCachedGif.parse_mode,
-        caption_entities=TestInlineQueryResultCachedGif.caption_entities,
-        input_message_content=TestInlineQueryResultCachedGif.input_message_content,
-        reply_markup=TestInlineQueryResultCachedGif.reply_markup,
+        Space.id_,
+        Space.gif_file_id,
+        title=Space.title,
+        caption=Space.caption,
+        parse_mode=Space.parse_mode,
+        caption_entities=Space.caption_entities,
+        input_message_content=Space.input_message_content,
+        reply_markup=Space.reply_markup,
     )
 
 
-class TestInlineQueryResultCachedGif:
+class Space:
     id_ = "id"
     type_ = "gif"
     gif_file_id = "gif file id"
@@ -53,6 +53,8 @@ class TestInlineQueryResultCachedGif:
     input_message_content = InputTextMessageContent("input_message_content")
     reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
 
+
+class TestInlineQueryResultCachedGifNoReq:
     def test_slot_behaviour(self, inline_query_result_cached_gif, mro_slots):
         inst = inline_query_result_cached_gif
         for attr in inst.__slots__:
@@ -60,21 +62,23 @@ def test_slot_behaviour(self, inline_query_result_cached_gif, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, inline_query_result_cached_gif):
-        assert inline_query_result_cached_gif.type == self.type_
-        assert inline_query_result_cached_gif.id == self.id_
-        assert inline_query_result_cached_gif.gif_file_id == self.gif_file_id
-        assert inline_query_result_cached_gif.title == self.title
-        assert inline_query_result_cached_gif.caption == self.caption
-        assert inline_query_result_cached_gif.parse_mode == self.parse_mode
-        assert inline_query_result_cached_gif.caption_entities == tuple(self.caption_entities)
+        assert inline_query_result_cached_gif.type == Space.type_
+        assert inline_query_result_cached_gif.id == Space.id_
+        assert inline_query_result_cached_gif.gif_file_id == Space.gif_file_id
+        assert inline_query_result_cached_gif.title == Space.title
+        assert inline_query_result_cached_gif.caption == Space.caption
+        assert inline_query_result_cached_gif.parse_mode == Space.parse_mode
+        assert inline_query_result_cached_gif.caption_entities == tuple(Space.caption_entities)
         assert (
             inline_query_result_cached_gif.input_message_content.to_dict()
-            == self.input_message_content.to_dict()
+            == Space.input_message_content.to_dict()
+        )
+        assert (
+            inline_query_result_cached_gif.reply_markup.to_dict() == Space.reply_markup.to_dict()
         )
-        assert inline_query_result_cached_gif.reply_markup.to_dict() == self.reply_markup.to_dict()
 
     def test_caption_entities_always_tuple(self):
-        result = InlineQueryResultCachedGif(self.id_, self.gif_file_id)
+        result = InlineQueryResultCachedGif(Space.id_, Space.gif_file_id)
         assert result.caption_entities == ()
 
     def test_to_dict(self, inline_query_result_cached_gif):
@@ -109,11 +113,11 @@ def test_to_dict(self, inline_query_result_cached_gif):
         )
 
     def test_equality(self):
-        a = InlineQueryResultCachedGif(self.id_, self.gif_file_id)
-        b = InlineQueryResultCachedGif(self.id_, self.gif_file_id)
-        c = InlineQueryResultCachedGif(self.id_, "")
-        d = InlineQueryResultCachedGif("", self.gif_file_id)
-        e = InlineQueryResultCachedVoice(self.id_, "", "")
+        a = InlineQueryResultCachedGif(Space.id_, Space.gif_file_id)
+        b = InlineQueryResultCachedGif(Space.id_, Space.gif_file_id)
+        c = InlineQueryResultCachedGif(Space.id_, "")
+        d = InlineQueryResultCachedGif("", Space.gif_file_id)
+        e = InlineQueryResultCachedVoice(Space.id_, "", "")
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inlinequeryresultcachedmpeg4gif.py b/tests/test_inlinequeryresultcachedmpeg4gif.py
index df273eff1af..360ef648697 100644
--- a/tests/test_inlinequeryresultcachedmpeg4gif.py
+++ b/tests/test_inlinequeryresultcachedmpeg4gif.py
@@ -28,21 +28,21 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query_result_cached_mpeg4_gif():
     return InlineQueryResultCachedMpeg4Gif(
-        TestInlineQueryResultCachedMpeg4Gif.id_,
-        TestInlineQueryResultCachedMpeg4Gif.mpeg4_file_id,
-        title=TestInlineQueryResultCachedMpeg4Gif.title,
-        caption=TestInlineQueryResultCachedMpeg4Gif.caption,
-        parse_mode=TestInlineQueryResultCachedMpeg4Gif.parse_mode,
-        caption_entities=TestInlineQueryResultCachedMpeg4Gif.caption_entities,
-        input_message_content=TestInlineQueryResultCachedMpeg4Gif.input_message_content,
-        reply_markup=TestInlineQueryResultCachedMpeg4Gif.reply_markup,
+        Space.id_,
+        Space.mpeg4_file_id,
+        title=Space.title,
+        caption=Space.caption,
+        parse_mode=Space.parse_mode,
+        caption_entities=Space.caption_entities,
+        input_message_content=Space.input_message_content,
+        reply_markup=Space.reply_markup,
     )
 
 
-class TestInlineQueryResultCachedMpeg4Gif:
+class Space:
     id_ = "id"
     type_ = "mpeg4_gif"
     mpeg4_file_id = "mpeg4 file id"
@@ -53,6 +53,8 @@ class TestInlineQueryResultCachedMpeg4Gif:
     input_message_content = InputTextMessageContent("input_message_content")
     reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
 
+
+class TestInlineQueryResultCachedMpeg4GifNoReq:
     def test_slot_behaviour(self, inline_query_result_cached_mpeg4_gif, mro_slots):
         inst = inline_query_result_cached_mpeg4_gif
         for attr in inst.__slots__:
@@ -60,26 +62,26 @@ def test_slot_behaviour(self, inline_query_result_cached_mpeg4_gif, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, inline_query_result_cached_mpeg4_gif):
-        assert inline_query_result_cached_mpeg4_gif.type == self.type_
-        assert inline_query_result_cached_mpeg4_gif.id == self.id_
-        assert inline_query_result_cached_mpeg4_gif.mpeg4_file_id == self.mpeg4_file_id
-        assert inline_query_result_cached_mpeg4_gif.title == self.title
-        assert inline_query_result_cached_mpeg4_gif.caption == self.caption
-        assert inline_query_result_cached_mpeg4_gif.parse_mode == self.parse_mode
+        assert inline_query_result_cached_mpeg4_gif.type == Space.type_
+        assert inline_query_result_cached_mpeg4_gif.id == Space.id_
+        assert inline_query_result_cached_mpeg4_gif.mpeg4_file_id == Space.mpeg4_file_id
+        assert inline_query_result_cached_mpeg4_gif.title == Space.title
+        assert inline_query_result_cached_mpeg4_gif.caption == Space.caption
+        assert inline_query_result_cached_mpeg4_gif.parse_mode == Space.parse_mode
         assert inline_query_result_cached_mpeg4_gif.caption_entities == tuple(
-            self.caption_entities
+            Space.caption_entities
         )
         assert (
             inline_query_result_cached_mpeg4_gif.input_message_content.to_dict()
-            == self.input_message_content.to_dict()
+            == Space.input_message_content.to_dict()
         )
         assert (
             inline_query_result_cached_mpeg4_gif.reply_markup.to_dict()
-            == self.reply_markup.to_dict()
+            == Space.reply_markup.to_dict()
         )
 
     def test_caption_entities_always_tuple(self):
-        result = InlineQueryResultCachedMpeg4Gif(self.id_, self.mpeg4_file_id)
+        result = InlineQueryResultCachedMpeg4Gif(Space.id_, Space.mpeg4_file_id)
         assert result.caption_entities == ()
 
     def test_to_dict(self, inline_query_result_cached_mpeg4_gif):
@@ -123,11 +125,11 @@ def test_to_dict(self, inline_query_result_cached_mpeg4_gif):
         )
 
     def test_equality(self):
-        a = InlineQueryResultCachedMpeg4Gif(self.id_, self.mpeg4_file_id)
-        b = InlineQueryResultCachedMpeg4Gif(self.id_, self.mpeg4_file_id)
-        c = InlineQueryResultCachedMpeg4Gif(self.id_, "")
-        d = InlineQueryResultCachedMpeg4Gif("", self.mpeg4_file_id)
-        e = InlineQueryResultCachedVoice(self.id_, "", "")
+        a = InlineQueryResultCachedMpeg4Gif(Space.id_, Space.mpeg4_file_id)
+        b = InlineQueryResultCachedMpeg4Gif(Space.id_, Space.mpeg4_file_id)
+        c = InlineQueryResultCachedMpeg4Gif(Space.id_, "")
+        d = InlineQueryResultCachedMpeg4Gif("", Space.mpeg4_file_id)
+        e = InlineQueryResultCachedVoice(Space.id_, "", "")
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inlinequeryresultcachedphoto.py b/tests/test_inlinequeryresultcachedphoto.py
index 2ef9fbe62cf..473d3772194 100644
--- a/tests/test_inlinequeryresultcachedphoto.py
+++ b/tests/test_inlinequeryresultcachedphoto.py
@@ -28,22 +28,22 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query_result_cached_photo():
     return InlineQueryResultCachedPhoto(
-        TestInlineQueryResultCachedPhoto.id_,
-        TestInlineQueryResultCachedPhoto.photo_file_id,
-        title=TestInlineQueryResultCachedPhoto.title,
-        description=TestInlineQueryResultCachedPhoto.description,
-        caption=TestInlineQueryResultCachedPhoto.caption,
-        parse_mode=TestInlineQueryResultCachedPhoto.parse_mode,
-        caption_entities=TestInlineQueryResultCachedPhoto.caption_entities,
-        input_message_content=TestInlineQueryResultCachedPhoto.input_message_content,
-        reply_markup=TestInlineQueryResultCachedPhoto.reply_markup,
+        Space.id_,
+        Space.photo_file_id,
+        title=Space.title,
+        description=Space.description,
+        caption=Space.caption,
+        parse_mode=Space.parse_mode,
+        caption_entities=Space.caption_entities,
+        input_message_content=Space.input_message_content,
+        reply_markup=Space.reply_markup,
     )
 
 
-class TestInlineQueryResultCachedPhoto:
+class Space:
     id_ = "id"
     type_ = "photo"
     photo_file_id = "photo file id"
@@ -55,6 +55,8 @@ class TestInlineQueryResultCachedPhoto:
     input_message_content = InputTextMessageContent("input_message_content")
     reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
 
+
+class TestInlineQueryResultCachedPhotoNoReq:
     def test_slot_behaviour(self, inline_query_result_cached_photo, mro_slots):
         inst = inline_query_result_cached_photo
         for attr in inst.__slots__:
@@ -62,24 +64,24 @@ def test_slot_behaviour(self, inline_query_result_cached_photo, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, inline_query_result_cached_photo):
-        assert inline_query_result_cached_photo.type == self.type_
-        assert inline_query_result_cached_photo.id == self.id_
-        assert inline_query_result_cached_photo.photo_file_id == self.photo_file_id
-        assert inline_query_result_cached_photo.title == self.title
-        assert inline_query_result_cached_photo.description == self.description
-        assert inline_query_result_cached_photo.caption == self.caption
-        assert inline_query_result_cached_photo.parse_mode == self.parse_mode
-        assert inline_query_result_cached_photo.caption_entities == tuple(self.caption_entities)
+        assert inline_query_result_cached_photo.type == Space.type_
+        assert inline_query_result_cached_photo.id == Space.id_
+        assert inline_query_result_cached_photo.photo_file_id == Space.photo_file_id
+        assert inline_query_result_cached_photo.title == Space.title
+        assert inline_query_result_cached_photo.description == Space.description
+        assert inline_query_result_cached_photo.caption == Space.caption
+        assert inline_query_result_cached_photo.parse_mode == Space.parse_mode
+        assert inline_query_result_cached_photo.caption_entities == tuple(Space.caption_entities)
         assert (
             inline_query_result_cached_photo.input_message_content.to_dict()
-            == self.input_message_content.to_dict()
+            == Space.input_message_content.to_dict()
         )
         assert (
-            inline_query_result_cached_photo.reply_markup.to_dict() == self.reply_markup.to_dict()
+            inline_query_result_cached_photo.reply_markup.to_dict() == Space.reply_markup.to_dict()
         )
 
     def test_caption_entities_always_tuple(self):
-        result = InlineQueryResultCachedPhoto(self.id_, self.photo_file_id)
+        result = InlineQueryResultCachedPhoto(Space.id_, Space.photo_file_id)
         assert result.caption_entities == ()
 
     def test_to_dict(self, inline_query_result_cached_photo):
@@ -123,11 +125,11 @@ def test_to_dict(self, inline_query_result_cached_photo):
         )
 
     def test_equality(self):
-        a = InlineQueryResultCachedPhoto(self.id_, self.photo_file_id)
-        b = InlineQueryResultCachedPhoto(self.id_, self.photo_file_id)
-        c = InlineQueryResultCachedPhoto(self.id_, "")
-        d = InlineQueryResultCachedPhoto("", self.photo_file_id)
-        e = InlineQueryResultCachedVoice(self.id_, "", "")
+        a = InlineQueryResultCachedPhoto(Space.id_, Space.photo_file_id)
+        b = InlineQueryResultCachedPhoto(Space.id_, Space.photo_file_id)
+        c = InlineQueryResultCachedPhoto(Space.id_, "")
+        d = InlineQueryResultCachedPhoto("", Space.photo_file_id)
+        e = InlineQueryResultCachedVoice(Space.id_, "", "")
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inlinequeryresultcachedsticker.py b/tests/test_inlinequeryresultcachedsticker.py
index d698e306f3e..a02bb1d5d0f 100644
--- a/tests/test_inlinequeryresultcachedsticker.py
+++ b/tests/test_inlinequeryresultcachedsticker.py
@@ -27,23 +27,25 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query_result_cached_sticker():
     return InlineQueryResultCachedSticker(
-        TestInlineQueryResultCachedSticker.id_,
-        TestInlineQueryResultCachedSticker.sticker_file_id,
-        input_message_content=TestInlineQueryResultCachedSticker.input_message_content,
-        reply_markup=TestInlineQueryResultCachedSticker.reply_markup,
+        Space.id_,
+        Space.sticker_file_id,
+        input_message_content=Space.input_message_content,
+        reply_markup=Space.reply_markup,
     )
 
 
-class TestInlineQueryResultCachedSticker:
+class Space:
     id_ = "id"
     type_ = "sticker"
     sticker_file_id = "sticker file id"
     input_message_content = InputTextMessageContent("input_message_content")
     reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
 
+
+class TestInlineQueryResultCachedStickerNoReq:
     def test_slot_behaviour(self, inline_query_result_cached_sticker, mro_slots):
         inst = inline_query_result_cached_sticker
         for attr in inst.__slots__:
@@ -51,16 +53,16 @@ def test_slot_behaviour(self, inline_query_result_cached_sticker, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, inline_query_result_cached_sticker):
-        assert inline_query_result_cached_sticker.type == self.type_
-        assert inline_query_result_cached_sticker.id == self.id_
-        assert inline_query_result_cached_sticker.sticker_file_id == self.sticker_file_id
+        assert inline_query_result_cached_sticker.type == Space.type_
+        assert inline_query_result_cached_sticker.id == Space.id_
+        assert inline_query_result_cached_sticker.sticker_file_id == Space.sticker_file_id
         assert (
             inline_query_result_cached_sticker.input_message_content.to_dict()
-            == self.input_message_content.to_dict()
+            == Space.input_message_content.to_dict()
         )
         assert (
             inline_query_result_cached_sticker.reply_markup.to_dict()
-            == self.reply_markup.to_dict()
+            == Space.reply_markup.to_dict()
         )
 
     def test_to_dict(self, inline_query_result_cached_sticker):
@@ -88,11 +90,11 @@ def test_to_dict(self, inline_query_result_cached_sticker):
         )
 
     def test_equality(self):
-        a = InlineQueryResultCachedSticker(self.id_, self.sticker_file_id)
-        b = InlineQueryResultCachedSticker(self.id_, self.sticker_file_id)
-        c = InlineQueryResultCachedSticker(self.id_, "")
-        d = InlineQueryResultCachedSticker("", self.sticker_file_id)
-        e = InlineQueryResultCachedVoice(self.id_, "", "")
+        a = InlineQueryResultCachedSticker(Space.id_, Space.sticker_file_id)
+        b = InlineQueryResultCachedSticker(Space.id_, Space.sticker_file_id)
+        c = InlineQueryResultCachedSticker(Space.id_, "")
+        d = InlineQueryResultCachedSticker("", Space.sticker_file_id)
+        e = InlineQueryResultCachedVoice(Space.id_, "", "")
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inlinequeryresultcachedvideo.py b/tests/test_inlinequeryresultcachedvideo.py
index c7861e0ce0c..884d4face6d 100644
--- a/tests/test_inlinequeryresultcachedvideo.py
+++ b/tests/test_inlinequeryresultcachedvideo.py
@@ -28,22 +28,22 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query_result_cached_video():
     return InlineQueryResultCachedVideo(
-        TestInlineQueryResultCachedVideo.id_,
-        TestInlineQueryResultCachedVideo.video_file_id,
-        TestInlineQueryResultCachedVideo.title,
-        caption=TestInlineQueryResultCachedVideo.caption,
-        parse_mode=TestInlineQueryResultCachedVideo.parse_mode,
-        caption_entities=TestInlineQueryResultCachedVideo.caption_entities,
-        description=TestInlineQueryResultCachedVideo.description,
-        input_message_content=TestInlineQueryResultCachedVideo.input_message_content,
-        reply_markup=TestInlineQueryResultCachedVideo.reply_markup,
+        Space.id_,
+        Space.video_file_id,
+        Space.title,
+        caption=Space.caption,
+        parse_mode=Space.parse_mode,
+        caption_entities=Space.caption_entities,
+        description=Space.description,
+        input_message_content=Space.input_message_content,
+        reply_markup=Space.reply_markup,
     )
 
 
-class TestInlineQueryResultCachedVideo:
+class Space:
     id_ = "id"
     type_ = "video"
     video_file_id = "video file id"
@@ -55,6 +55,8 @@ class TestInlineQueryResultCachedVideo:
     input_message_content = InputTextMessageContent("input_message_content")
     reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
 
+
+class TestInlineQueryResultCachedVideoNoReq:
     def test_slot_behaviour(self, inline_query_result_cached_video, mro_slots):
         inst = inline_query_result_cached_video
         for attr in inst.__slots__:
@@ -62,24 +64,24 @@ def test_slot_behaviour(self, inline_query_result_cached_video, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, inline_query_result_cached_video):
-        assert inline_query_result_cached_video.type == self.type_
-        assert inline_query_result_cached_video.id == self.id_
-        assert inline_query_result_cached_video.video_file_id == self.video_file_id
-        assert inline_query_result_cached_video.title == self.title
-        assert inline_query_result_cached_video.description == self.description
-        assert inline_query_result_cached_video.caption == self.caption
-        assert inline_query_result_cached_video.parse_mode == self.parse_mode
-        assert inline_query_result_cached_video.caption_entities == tuple(self.caption_entities)
+        assert inline_query_result_cached_video.type == Space.type_
+        assert inline_query_result_cached_video.id == Space.id_
+        assert inline_query_result_cached_video.video_file_id == Space.video_file_id
+        assert inline_query_result_cached_video.title == Space.title
+        assert inline_query_result_cached_video.description == Space.description
+        assert inline_query_result_cached_video.caption == Space.caption
+        assert inline_query_result_cached_video.parse_mode == Space.parse_mode
+        assert inline_query_result_cached_video.caption_entities == tuple(Space.caption_entities)
         assert (
             inline_query_result_cached_video.input_message_content.to_dict()
-            == self.input_message_content.to_dict()
+            == Space.input_message_content.to_dict()
         )
         assert (
-            inline_query_result_cached_video.reply_markup.to_dict() == self.reply_markup.to_dict()
+            inline_query_result_cached_video.reply_markup.to_dict() == Space.reply_markup.to_dict()
         )
 
     def test_caption_entities_always_tuple(self):
-        video = InlineQueryResultCachedVideo(self.id_, self.video_file_id, self.title)
+        video = InlineQueryResultCachedVideo(Space.id_, Space.video_file_id, Space.title)
 
         assert video.caption_entities == ()
 
@@ -124,11 +126,11 @@ def test_to_dict(self, inline_query_result_cached_video):
         )
 
     def test_equality(self):
-        a = InlineQueryResultCachedVideo(self.id_, self.video_file_id, self.title)
-        b = InlineQueryResultCachedVideo(self.id_, self.video_file_id, self.title)
-        c = InlineQueryResultCachedVideo(self.id_, "", self.title)
-        d = InlineQueryResultCachedVideo("", self.video_file_id, self.title)
-        e = InlineQueryResultCachedVoice(self.id_, "", "")
+        a = InlineQueryResultCachedVideo(Space.id_, Space.video_file_id, Space.title)
+        b = InlineQueryResultCachedVideo(Space.id_, Space.video_file_id, Space.title)
+        c = InlineQueryResultCachedVideo(Space.id_, "", Space.title)
+        d = InlineQueryResultCachedVideo("", Space.video_file_id, Space.title)
+        e = InlineQueryResultCachedVoice(Space.id_, "", "")
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inlinequeryresultcachedvoice.py b/tests/test_inlinequeryresultcachedvoice.py
index c4033edc386..6ee7159dcee 100644
--- a/tests/test_inlinequeryresultcachedvoice.py
+++ b/tests/test_inlinequeryresultcachedvoice.py
@@ -28,21 +28,21 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query_result_cached_voice():
     return InlineQueryResultCachedVoice(
-        TestInlineQueryResultCachedVoice.id_,
-        TestInlineQueryResultCachedVoice.voice_file_id,
-        TestInlineQueryResultCachedVoice.title,
-        caption=TestInlineQueryResultCachedVoice.caption,
-        parse_mode=TestInlineQueryResultCachedVoice.parse_mode,
-        caption_entities=TestInlineQueryResultCachedVoice.caption_entities,
-        input_message_content=TestInlineQueryResultCachedVoice.input_message_content,
-        reply_markup=TestInlineQueryResultCachedVoice.reply_markup,
+        Space.id_,
+        Space.voice_file_id,
+        Space.title,
+        caption=Space.caption,
+        parse_mode=Space.parse_mode,
+        caption_entities=Space.caption_entities,
+        input_message_content=Space.input_message_content,
+        reply_markup=Space.reply_markup,
     )
 
 
-class TestInlineQueryResultCachedVoice:
+class Space:
     id_ = "id"
     type_ = "voice"
     voice_file_id = "voice file id"
@@ -53,6 +53,8 @@ class TestInlineQueryResultCachedVoice:
     input_message_content = InputTextMessageContent("input_message_content")
     reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
 
+
+class TestInlineQueryResultCachedVoiceNoReq:
     def test_slot_behaviour(self, inline_query_result_cached_voice, mro_slots):
         inst = inline_query_result_cached_voice
         for attr in inst.__slots__:
@@ -60,23 +62,23 @@ def test_slot_behaviour(self, inline_query_result_cached_voice, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, inline_query_result_cached_voice):
-        assert inline_query_result_cached_voice.type == self.type_
-        assert inline_query_result_cached_voice.id == self.id_
-        assert inline_query_result_cached_voice.voice_file_id == self.voice_file_id
-        assert inline_query_result_cached_voice.title == self.title
-        assert inline_query_result_cached_voice.caption == self.caption
-        assert inline_query_result_cached_voice.parse_mode == self.parse_mode
-        assert inline_query_result_cached_voice.caption_entities == tuple(self.caption_entities)
+        assert inline_query_result_cached_voice.type == Space.type_
+        assert inline_query_result_cached_voice.id == Space.id_
+        assert inline_query_result_cached_voice.voice_file_id == Space.voice_file_id
+        assert inline_query_result_cached_voice.title == Space.title
+        assert inline_query_result_cached_voice.caption == Space.caption
+        assert inline_query_result_cached_voice.parse_mode == Space.parse_mode
+        assert inline_query_result_cached_voice.caption_entities == tuple(Space.caption_entities)
         assert (
             inline_query_result_cached_voice.input_message_content.to_dict()
-            == self.input_message_content.to_dict()
+            == Space.input_message_content.to_dict()
         )
         assert (
-            inline_query_result_cached_voice.reply_markup.to_dict() == self.reply_markup.to_dict()
+            inline_query_result_cached_voice.reply_markup.to_dict() == Space.reply_markup.to_dict()
         )
 
     def test_caption_entities_always_tuple(self):
-        result = InlineQueryResultCachedVoice(self.id_, self.voice_file_id, self.title)
+        result = InlineQueryResultCachedVoice(Space.id_, Space.voice_file_id, Space.title)
         assert result.caption_entities == ()
 
     def test_to_dict(self, inline_query_result_cached_voice):
@@ -116,11 +118,11 @@ def test_to_dict(self, inline_query_result_cached_voice):
         )
 
     def test_equality(self):
-        a = InlineQueryResultCachedVoice(self.id_, self.voice_file_id, self.title)
-        b = InlineQueryResultCachedVoice(self.id_, self.voice_file_id, self.title)
-        c = InlineQueryResultCachedVoice(self.id_, "", self.title)
-        d = InlineQueryResultCachedVoice("", self.voice_file_id, self.title)
-        e = InlineQueryResultCachedAudio(self.id_, "", "")
+        a = InlineQueryResultCachedVoice(Space.id_, Space.voice_file_id, Space.title)
+        b = InlineQueryResultCachedVoice(Space.id_, Space.voice_file_id, Space.title)
+        c = InlineQueryResultCachedVoice(Space.id_, "", Space.title)
+        d = InlineQueryResultCachedVoice("", Space.voice_file_id, Space.title)
+        e = InlineQueryResultCachedAudio(Space.id_, "", "")
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inlinequeryresultcontact.py b/tests/test_inlinequeryresultcontact.py
index c3a0c845428..cdbc922c57c 100644
--- a/tests/test_inlinequeryresultcontact.py
+++ b/tests/test_inlinequeryresultcontact.py
@@ -27,22 +27,22 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query_result_contact():
     return InlineQueryResultContact(
-        TestInlineQueryResultContact.id_,
-        TestInlineQueryResultContact.phone_number,
-        TestInlineQueryResultContact.first_name,
-        last_name=TestInlineQueryResultContact.last_name,
-        thumb_url=TestInlineQueryResultContact.thumb_url,
-        thumb_width=TestInlineQueryResultContact.thumb_width,
-        thumb_height=TestInlineQueryResultContact.thumb_height,
-        input_message_content=TestInlineQueryResultContact.input_message_content,
-        reply_markup=TestInlineQueryResultContact.reply_markup,
+        Space.id_,
+        Space.phone_number,
+        Space.first_name,
+        last_name=Space.last_name,
+        thumb_url=Space.thumb_url,
+        thumb_width=Space.thumb_width,
+        thumb_height=Space.thumb_height,
+        input_message_content=Space.input_message_content,
+        reply_markup=Space.reply_markup,
     )
 
 
-class TestInlineQueryResultContact:
+class Space:
     id_ = "id"
     type_ = "contact"
     phone_number = "phone_number"
@@ -54,6 +54,8 @@ class TestInlineQueryResultContact:
     input_message_content = InputTextMessageContent("input_message_content")
     reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
 
+
+class TestInlineQueryResultContactNoReq:
     def test_slot_behaviour(self, inline_query_result_contact, mro_slots):
         inst = inline_query_result_contact
         for attr in inst.__slots__:
@@ -61,19 +63,19 @@ def test_slot_behaviour(self, inline_query_result_contact, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, inline_query_result_contact):
-        assert inline_query_result_contact.id == self.id_
-        assert inline_query_result_contact.type == self.type_
-        assert inline_query_result_contact.phone_number == self.phone_number
-        assert inline_query_result_contact.first_name == self.first_name
-        assert inline_query_result_contact.last_name == self.last_name
-        assert inline_query_result_contact.thumb_url == self.thumb_url
-        assert inline_query_result_contact.thumb_width == self.thumb_width
-        assert inline_query_result_contact.thumb_height == self.thumb_height
+        assert inline_query_result_contact.id == Space.id_
+        assert inline_query_result_contact.type == Space.type_
+        assert inline_query_result_contact.phone_number == Space.phone_number
+        assert inline_query_result_contact.first_name == Space.first_name
+        assert inline_query_result_contact.last_name == Space.last_name
+        assert inline_query_result_contact.thumb_url == Space.thumb_url
+        assert inline_query_result_contact.thumb_width == Space.thumb_width
+        assert inline_query_result_contact.thumb_height == Space.thumb_height
         assert (
             inline_query_result_contact.input_message_content.to_dict()
-            == self.input_message_content.to_dict()
+            == Space.input_message_content.to_dict()
         )
-        assert inline_query_result_contact.reply_markup.to_dict() == self.reply_markup.to_dict()
+        assert inline_query_result_contact.reply_markup.to_dict() == Space.reply_markup.to_dict()
 
     def test_to_dict(self, inline_query_result_contact):
         inline_query_result_contact_dict = inline_query_result_contact.to_dict()
@@ -113,11 +115,11 @@ def test_to_dict(self, inline_query_result_contact):
         )
 
     def test_equality(self):
-        a = InlineQueryResultContact(self.id_, self.phone_number, self.first_name)
-        b = InlineQueryResultContact(self.id_, self.phone_number, self.first_name)
-        c = InlineQueryResultContact(self.id_, "", self.first_name)
-        d = InlineQueryResultContact("", self.phone_number, self.first_name)
-        e = InlineQueryResultVoice(self.id_, "", "")
+        a = InlineQueryResultContact(Space.id_, Space.phone_number, Space.first_name)
+        b = InlineQueryResultContact(Space.id_, Space.phone_number, Space.first_name)
+        c = InlineQueryResultContact(Space.id_, "", Space.first_name)
+        d = InlineQueryResultContact("", Space.phone_number, Space.first_name)
+        e = InlineQueryResultVoice(Space.id_, "", "")
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inlinequeryresultdocument.py b/tests/test_inlinequeryresultdocument.py
index 2915e7451e6..f9aa3ae7a0f 100644
--- a/tests/test_inlinequeryresultdocument.py
+++ b/tests/test_inlinequeryresultdocument.py
@@ -28,26 +28,26 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query_result_document():
     return InlineQueryResultDocument(
-        TestInlineQueryResultDocument.id_,
-        TestInlineQueryResultDocument.document_url,
-        TestInlineQueryResultDocument.title,
-        TestInlineQueryResultDocument.mime_type,
-        caption=TestInlineQueryResultDocument.caption,
-        parse_mode=TestInlineQueryResultDocument.parse_mode,
-        caption_entities=TestInlineQueryResultDocument.caption_entities,
-        description=TestInlineQueryResultDocument.description,
-        thumb_url=TestInlineQueryResultDocument.thumb_url,
-        thumb_width=TestInlineQueryResultDocument.thumb_width,
-        thumb_height=TestInlineQueryResultDocument.thumb_height,
-        input_message_content=TestInlineQueryResultDocument.input_message_content,
-        reply_markup=TestInlineQueryResultDocument.reply_markup,
+        Space.id_,
+        Space.document_url,
+        Space.title,
+        Space.mime_type,
+        caption=Space.caption,
+        parse_mode=Space.parse_mode,
+        caption_entities=Space.caption_entities,
+        description=Space.description,
+        thumb_url=Space.thumb_url,
+        thumb_width=Space.thumb_width,
+        thumb_height=Space.thumb_height,
+        input_message_content=Space.input_message_content,
+        reply_markup=Space.reply_markup,
     )
 
 
-class TestInlineQueryResultDocument:
+class Space:
     id_ = "id"
     type_ = "document"
     document_url = "document url"
@@ -63,6 +63,8 @@ class TestInlineQueryResultDocument:
     input_message_content = InputTextMessageContent("input_message_content")
     reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
 
+
+class TestInlineQueryResultDocumentNoReq:
     def test_slot_behaviour(self, inline_query_result_document, mro_slots):
         inst = inline_query_result_document
         for attr in inst.__slots__:
@@ -70,26 +72,28 @@ def test_slot_behaviour(self, inline_query_result_document, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, inline_query_result_document):
-        assert inline_query_result_document.id == self.id_
-        assert inline_query_result_document.type == self.type_
-        assert inline_query_result_document.document_url == self.document_url
-        assert inline_query_result_document.title == self.title
-        assert inline_query_result_document.caption == self.caption
-        assert inline_query_result_document.parse_mode == self.parse_mode
-        assert inline_query_result_document.caption_entities == tuple(self.caption_entities)
-        assert inline_query_result_document.mime_type == self.mime_type
-        assert inline_query_result_document.description == self.description
-        assert inline_query_result_document.thumb_url == self.thumb_url
-        assert inline_query_result_document.thumb_width == self.thumb_width
-        assert inline_query_result_document.thumb_height == self.thumb_height
+        assert inline_query_result_document.id == Space.id_
+        assert inline_query_result_document.type == Space.type_
+        assert inline_query_result_document.document_url == Space.document_url
+        assert inline_query_result_document.title == Space.title
+        assert inline_query_result_document.caption == Space.caption
+        assert inline_query_result_document.parse_mode == Space.parse_mode
+        assert inline_query_result_document.caption_entities == tuple(Space.caption_entities)
+        assert inline_query_result_document.mime_type == Space.mime_type
+        assert inline_query_result_document.description == Space.description
+        assert inline_query_result_document.thumb_url == Space.thumb_url
+        assert inline_query_result_document.thumb_width == Space.thumb_width
+        assert inline_query_result_document.thumb_height == Space.thumb_height
         assert (
             inline_query_result_document.input_message_content.to_dict()
-            == self.input_message_content.to_dict()
+            == Space.input_message_content.to_dict()
         )
-        assert inline_query_result_document.reply_markup.to_dict() == self.reply_markup.to_dict()
+        assert inline_query_result_document.reply_markup.to_dict() == Space.reply_markup.to_dict()
 
     def test_caption_entities_always_tuple(self):
-        result = InlineQueryResultDocument(self.id_, self.document_url, self.title, self.mime_type)
+        result = InlineQueryResultDocument(
+            Space.id_, Space.document_url, Space.title, Space.mime_type
+        )
         assert result.caption_entities == ()
 
     def test_to_dict(self, inline_query_result_document):
@@ -141,11 +145,11 @@ def test_to_dict(self, inline_query_result_document):
         )
 
     def test_equality(self):
-        a = InlineQueryResultDocument(self.id_, self.document_url, self.title, self.mime_type)
-        b = InlineQueryResultDocument(self.id_, self.document_url, self.title, self.mime_type)
-        c = InlineQueryResultDocument(self.id_, "", self.title, self.mime_type)
-        d = InlineQueryResultDocument("", self.document_url, self.title, self.mime_type)
-        e = InlineQueryResultVoice(self.id_, "", "")
+        a = InlineQueryResultDocument(Space.id_, Space.document_url, Space.title, Space.mime_type)
+        b = InlineQueryResultDocument(Space.id_, Space.document_url, Space.title, Space.mime_type)
+        c = InlineQueryResultDocument(Space.id_, "", Space.title, Space.mime_type)
+        d = InlineQueryResultDocument("", Space.document_url, Space.title, Space.mime_type)
+        e = InlineQueryResultVoice(Space.id_, "", "")
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inlinequeryresultgame.py b/tests/test_inlinequeryresultgame.py
index 3c65c61acb5..df7e120f22b 100644
--- a/tests/test_inlinequeryresultgame.py
+++ b/tests/test_inlinequeryresultgame.py
@@ -26,21 +26,23 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query_result_game():
     return InlineQueryResultGame(
-        TestInlineQueryResultGame.id_,
-        TestInlineQueryResultGame.game_short_name,
-        reply_markup=TestInlineQueryResultGame.reply_markup,
+        Space.id_,
+        Space.game_short_name,
+        reply_markup=Space.reply_markup,
     )
 
 
-class TestInlineQueryResultGame:
+class Space:
     id_ = "id"
     type_ = "game"
     game_short_name = "game short name"
     reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
 
+
+class TestInlineQueryResultGameNoReq:
     def test_slot_behaviour(self, inline_query_result_game, mro_slots):
         inst = inline_query_result_game
         for attr in inst.__slots__:
@@ -48,10 +50,10 @@ def test_slot_behaviour(self, inline_query_result_game, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, inline_query_result_game):
-        assert inline_query_result_game.type == self.type_
-        assert inline_query_result_game.id == self.id_
-        assert inline_query_result_game.game_short_name == self.game_short_name
-        assert inline_query_result_game.reply_markup.to_dict() == self.reply_markup.to_dict()
+        assert inline_query_result_game.type == Space.type_
+        assert inline_query_result_game.id == Space.id_
+        assert inline_query_result_game.game_short_name == Space.game_short_name
+        assert inline_query_result_game.reply_markup.to_dict() == Space.reply_markup.to_dict()
 
     def test_to_dict(self, inline_query_result_game):
         inline_query_result_game_dict = inline_query_result_game.to_dict()
@@ -69,11 +71,11 @@ def test_to_dict(self, inline_query_result_game):
         )
 
     def test_equality(self):
-        a = InlineQueryResultGame(self.id_, self.game_short_name)
-        b = InlineQueryResultGame(self.id_, self.game_short_name)
-        c = InlineQueryResultGame(self.id_, "")
-        d = InlineQueryResultGame("", self.game_short_name)
-        e = InlineQueryResultVoice(self.id_, "", "")
+        a = InlineQueryResultGame(Space.id_, Space.game_short_name)
+        b = InlineQueryResultGame(Space.id_, Space.game_short_name)
+        c = InlineQueryResultGame(Space.id_, "")
+        d = InlineQueryResultGame("", Space.game_short_name)
+        e = InlineQueryResultVoice(Space.id_, "", "")
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inlinequeryresultgif.py b/tests/test_inlinequeryresultgif.py
index f0242148155..c00da6eb514 100644
--- a/tests/test_inlinequeryresultgif.py
+++ b/tests/test_inlinequeryresultgif.py
@@ -28,26 +28,26 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query_result_gif():
     return InlineQueryResultGif(
-        TestInlineQueryResultGif.id_,
-        TestInlineQueryResultGif.gif_url,
-        TestInlineQueryResultGif.thumb_url,
-        gif_width=TestInlineQueryResultGif.gif_width,
-        gif_height=TestInlineQueryResultGif.gif_height,
-        gif_duration=TestInlineQueryResultGif.gif_duration,
-        title=TestInlineQueryResultGif.title,
-        caption=TestInlineQueryResultGif.caption,
-        parse_mode=TestInlineQueryResultGif.parse_mode,
-        caption_entities=TestInlineQueryResultGif.caption_entities,
-        input_message_content=TestInlineQueryResultGif.input_message_content,
-        reply_markup=TestInlineQueryResultGif.reply_markup,
-        thumb_mime_type=TestInlineQueryResultGif.thumb_mime_type,
+        Space.id_,
+        Space.gif_url,
+        Space.thumb_url,
+        gif_width=Space.gif_width,
+        gif_height=Space.gif_height,
+        gif_duration=Space.gif_duration,
+        title=Space.title,
+        caption=Space.caption,
+        parse_mode=Space.parse_mode,
+        caption_entities=Space.caption_entities,
+        input_message_content=Space.input_message_content,
+        reply_markup=Space.reply_markup,
+        thumb_mime_type=Space.thumb_mime_type,
     )
 
 
-class TestInlineQueryResultGif:
+class Space:
     id_ = "id"
     type_ = "gif"
     gif_url = "gif url"
@@ -63,6 +63,8 @@ class TestInlineQueryResultGif:
     input_message_content = InputTextMessageContent("input_message_content")
     reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
 
+
+class TestInlineQueryResultGifNoReq:
     def test_slot_behaviour(self, inline_query_result_gif, mro_slots):
         inst = inline_query_result_gif
         for attr in inst.__slots__:
@@ -70,27 +72,27 @@ def test_slot_behaviour(self, inline_query_result_gif, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_caption_entities_always_tuple(self):
-        result = InlineQueryResultGif(self.id_, self.gif_url, self.thumb_url)
+        result = InlineQueryResultGif(Space.id_, Space.gif_url, Space.thumb_url)
         assert result.caption_entities == ()
 
     def test_expected_values(self, inline_query_result_gif):
-        assert inline_query_result_gif.type == self.type_
-        assert inline_query_result_gif.id == self.id_
-        assert inline_query_result_gif.gif_url == self.gif_url
-        assert inline_query_result_gif.gif_width == self.gif_width
-        assert inline_query_result_gif.gif_height == self.gif_height
-        assert inline_query_result_gif.gif_duration == self.gif_duration
-        assert inline_query_result_gif.thumb_url == self.thumb_url
-        assert inline_query_result_gif.thumb_mime_type == self.thumb_mime_type
-        assert inline_query_result_gif.title == self.title
-        assert inline_query_result_gif.caption == self.caption
-        assert inline_query_result_gif.parse_mode == self.parse_mode
-        assert inline_query_result_gif.caption_entities == tuple(self.caption_entities)
+        assert inline_query_result_gif.type == Space.type_
+        assert inline_query_result_gif.id == Space.id_
+        assert inline_query_result_gif.gif_url == Space.gif_url
+        assert inline_query_result_gif.gif_width == Space.gif_width
+        assert inline_query_result_gif.gif_height == Space.gif_height
+        assert inline_query_result_gif.gif_duration == Space.gif_duration
+        assert inline_query_result_gif.thumb_url == Space.thumb_url
+        assert inline_query_result_gif.thumb_mime_type == Space.thumb_mime_type
+        assert inline_query_result_gif.title == Space.title
+        assert inline_query_result_gif.caption == Space.caption
+        assert inline_query_result_gif.parse_mode == Space.parse_mode
+        assert inline_query_result_gif.caption_entities == tuple(Space.caption_entities)
         assert (
             inline_query_result_gif.input_message_content.to_dict()
-            == self.input_message_content.to_dict()
+            == Space.input_message_content.to_dict()
         )
-        assert inline_query_result_gif.reply_markup.to_dict() == self.reply_markup.to_dict()
+        assert inline_query_result_gif.reply_markup.to_dict() == Space.reply_markup.to_dict()
 
     def test_to_dict(self, inline_query_result_gif):
         inline_query_result_gif_dict = inline_query_result_gif.to_dict()
@@ -123,11 +125,11 @@ def test_to_dict(self, inline_query_result_gif):
         )
 
     def test_equality(self):
-        a = InlineQueryResultGif(self.id_, self.gif_url, self.thumb_url)
-        b = InlineQueryResultGif(self.id_, self.gif_url, self.thumb_url)
-        c = InlineQueryResultGif(self.id_, "", self.thumb_url)
-        d = InlineQueryResultGif("", self.gif_url, self.thumb_url)
-        e = InlineQueryResultVoice(self.id_, "", "")
+        a = InlineQueryResultGif(Space.id_, Space.gif_url, Space.thumb_url)
+        b = InlineQueryResultGif(Space.id_, Space.gif_url, Space.thumb_url)
+        c = InlineQueryResultGif(Space.id_, "", Space.thumb_url)
+        d = InlineQueryResultGif("", Space.gif_url, Space.thumb_url)
+        e = InlineQueryResultVoice(Space.id_, "", "")
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inlinequeryresultlocation.py b/tests/test_inlinequeryresultlocation.py
index 912273d2782..ac746613db4 100644
--- a/tests/test_inlinequeryresultlocation.py
+++ b/tests/test_inlinequeryresultlocation.py
@@ -27,26 +27,26 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query_result_location():
     return InlineQueryResultLocation(
-        TestInlineQueryResultLocation.id_,
-        TestInlineQueryResultLocation.latitude,
-        TestInlineQueryResultLocation.longitude,
-        TestInlineQueryResultLocation.title,
-        live_period=TestInlineQueryResultLocation.live_period,
-        thumb_url=TestInlineQueryResultLocation.thumb_url,
-        thumb_width=TestInlineQueryResultLocation.thumb_width,
-        thumb_height=TestInlineQueryResultLocation.thumb_height,
-        input_message_content=TestInlineQueryResultLocation.input_message_content,
-        reply_markup=TestInlineQueryResultLocation.reply_markup,
-        horizontal_accuracy=TestInlineQueryResultLocation.horizontal_accuracy,
-        heading=TestInlineQueryResultLocation.heading,
-        proximity_alert_radius=TestInlineQueryResultLocation.proximity_alert_radius,
+        Space.id_,
+        Space.latitude,
+        Space.longitude,
+        Space.title,
+        live_period=Space.live_period,
+        thumb_url=Space.thumb_url,
+        thumb_width=Space.thumb_width,
+        thumb_height=Space.thumb_height,
+        input_message_content=Space.input_message_content,
+        reply_markup=Space.reply_markup,
+        horizontal_accuracy=Space.horizontal_accuracy,
+        heading=Space.heading,
+        proximity_alert_radius=Space.proximity_alert_radius,
     )
 
 
-class TestInlineQueryResultLocation:
+class Space:
     id_ = "id"
     type_ = "location"
     latitude = 0.0
@@ -62,6 +62,8 @@ class TestInlineQueryResultLocation:
     input_message_content = InputTextMessageContent("input_message_content")
     reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
 
+
+class TestInlineQueryResultLocationNoReq:
     def test_slot_behaviour(self, inline_query_result_location, mro_slots):
         inst = inline_query_result_location
         for attr in inst.__slots__:
@@ -69,23 +71,23 @@ def test_slot_behaviour(self, inline_query_result_location, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, inline_query_result_location):
-        assert inline_query_result_location.id == self.id_
-        assert inline_query_result_location.type == self.type_
-        assert inline_query_result_location.latitude == self.latitude
-        assert inline_query_result_location.longitude == self.longitude
-        assert inline_query_result_location.title == self.title
-        assert inline_query_result_location.live_period == self.live_period
-        assert inline_query_result_location.thumb_url == self.thumb_url
-        assert inline_query_result_location.thumb_width == self.thumb_width
-        assert inline_query_result_location.thumb_height == self.thumb_height
+        assert inline_query_result_location.id == Space.id_
+        assert inline_query_result_location.type == Space.type_
+        assert inline_query_result_location.latitude == Space.latitude
+        assert inline_query_result_location.longitude == Space.longitude
+        assert inline_query_result_location.title == Space.title
+        assert inline_query_result_location.live_period == Space.live_period
+        assert inline_query_result_location.thumb_url == Space.thumb_url
+        assert inline_query_result_location.thumb_width == Space.thumb_width
+        assert inline_query_result_location.thumb_height == Space.thumb_height
         assert (
             inline_query_result_location.input_message_content.to_dict()
-            == self.input_message_content.to_dict()
+            == Space.input_message_content.to_dict()
         )
-        assert inline_query_result_location.reply_markup.to_dict() == self.reply_markup.to_dict()
-        assert inline_query_result_location.heading == self.heading
-        assert inline_query_result_location.horizontal_accuracy == self.horizontal_accuracy
-        assert inline_query_result_location.proximity_alert_radius == self.proximity_alert_radius
+        assert inline_query_result_location.reply_markup.to_dict() == Space.reply_markup.to_dict()
+        assert inline_query_result_location.heading == Space.heading
+        assert inline_query_result_location.horizontal_accuracy == Space.horizontal_accuracy
+        assert inline_query_result_location.proximity_alert_radius == Space.proximity_alert_radius
 
     def test_to_dict(self, inline_query_result_location):
         inline_query_result_location_dict = inline_query_result_location.to_dict()
@@ -136,11 +138,11 @@ def test_to_dict(self, inline_query_result_location):
         )
 
     def test_equality(self):
-        a = InlineQueryResultLocation(self.id_, self.longitude, self.latitude, self.title)
-        b = InlineQueryResultLocation(self.id_, self.longitude, self.latitude, self.title)
-        c = InlineQueryResultLocation(self.id_, 0, self.latitude, self.title)
-        d = InlineQueryResultLocation("", self.longitude, self.latitude, self.title)
-        e = InlineQueryResultVoice(self.id_, "", "")
+        a = InlineQueryResultLocation(Space.id_, Space.longitude, Space.latitude, Space.title)
+        b = InlineQueryResultLocation(Space.id_, Space.longitude, Space.latitude, Space.title)
+        c = InlineQueryResultLocation(Space.id_, 0, Space.latitude, Space.title)
+        d = InlineQueryResultLocation("", Space.longitude, Space.latitude, Space.title)
+        e = InlineQueryResultVoice(Space.id_, "", "")
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inlinequeryresultmpeg4gif.py b/tests/test_inlinequeryresultmpeg4gif.py
index 2c564d94fd7..f4a65e7a062 100644
--- a/tests/test_inlinequeryresultmpeg4gif.py
+++ b/tests/test_inlinequeryresultmpeg4gif.py
@@ -28,26 +28,26 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query_result_mpeg4_gif():
     return InlineQueryResultMpeg4Gif(
-        TestInlineQueryResultMpeg4Gif.id_,
-        TestInlineQueryResultMpeg4Gif.mpeg4_url,
-        TestInlineQueryResultMpeg4Gif.thumb_url,
-        mpeg4_width=TestInlineQueryResultMpeg4Gif.mpeg4_width,
-        mpeg4_height=TestInlineQueryResultMpeg4Gif.mpeg4_height,
-        mpeg4_duration=TestInlineQueryResultMpeg4Gif.mpeg4_duration,
-        title=TestInlineQueryResultMpeg4Gif.title,
-        caption=TestInlineQueryResultMpeg4Gif.caption,
-        parse_mode=TestInlineQueryResultMpeg4Gif.parse_mode,
-        caption_entities=TestInlineQueryResultMpeg4Gif.caption_entities,
-        input_message_content=TestInlineQueryResultMpeg4Gif.input_message_content,
-        reply_markup=TestInlineQueryResultMpeg4Gif.reply_markup,
-        thumb_mime_type=TestInlineQueryResultMpeg4Gif.thumb_mime_type,
+        Space.id_,
+        Space.mpeg4_url,
+        Space.thumb_url,
+        mpeg4_width=Space.mpeg4_width,
+        mpeg4_height=Space.mpeg4_height,
+        mpeg4_duration=Space.mpeg4_duration,
+        title=Space.title,
+        caption=Space.caption,
+        parse_mode=Space.parse_mode,
+        caption_entities=Space.caption_entities,
+        input_message_content=Space.input_message_content,
+        reply_markup=Space.reply_markup,
+        thumb_mime_type=Space.thumb_mime_type,
     )
 
 
-class TestInlineQueryResultMpeg4Gif:
+class Space:
     id_ = "id"
     type_ = "mpeg4_gif"
     mpeg4_url = "mpeg4 url"
@@ -63,6 +63,8 @@ class TestInlineQueryResultMpeg4Gif:
     input_message_content = InputTextMessageContent("input_message_content")
     reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
 
+
+class TestInlineQueryResultMpeg4GifNoReq:
     def test_slot_behaviour(self, inline_query_result_mpeg4_gif, mro_slots):
         inst = inline_query_result_mpeg4_gif
         for attr in inst.__slots__:
@@ -70,26 +72,26 @@ def test_slot_behaviour(self, inline_query_result_mpeg4_gif, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, inline_query_result_mpeg4_gif):
-        assert inline_query_result_mpeg4_gif.type == self.type_
-        assert inline_query_result_mpeg4_gif.id == self.id_
-        assert inline_query_result_mpeg4_gif.mpeg4_url == self.mpeg4_url
-        assert inline_query_result_mpeg4_gif.mpeg4_width == self.mpeg4_width
-        assert inline_query_result_mpeg4_gif.mpeg4_height == self.mpeg4_height
-        assert inline_query_result_mpeg4_gif.mpeg4_duration == self.mpeg4_duration
-        assert inline_query_result_mpeg4_gif.thumb_url == self.thumb_url
-        assert inline_query_result_mpeg4_gif.thumb_mime_type == self.thumb_mime_type
-        assert inline_query_result_mpeg4_gif.title == self.title
-        assert inline_query_result_mpeg4_gif.caption == self.caption
-        assert inline_query_result_mpeg4_gif.parse_mode == self.parse_mode
-        assert inline_query_result_mpeg4_gif.caption_entities == tuple(self.caption_entities)
+        assert inline_query_result_mpeg4_gif.type == Space.type_
+        assert inline_query_result_mpeg4_gif.id == Space.id_
+        assert inline_query_result_mpeg4_gif.mpeg4_url == Space.mpeg4_url
+        assert inline_query_result_mpeg4_gif.mpeg4_width == Space.mpeg4_width
+        assert inline_query_result_mpeg4_gif.mpeg4_height == Space.mpeg4_height
+        assert inline_query_result_mpeg4_gif.mpeg4_duration == Space.mpeg4_duration
+        assert inline_query_result_mpeg4_gif.thumb_url == Space.thumb_url
+        assert inline_query_result_mpeg4_gif.thumb_mime_type == Space.thumb_mime_type
+        assert inline_query_result_mpeg4_gif.title == Space.title
+        assert inline_query_result_mpeg4_gif.caption == Space.caption
+        assert inline_query_result_mpeg4_gif.parse_mode == Space.parse_mode
+        assert inline_query_result_mpeg4_gif.caption_entities == tuple(Space.caption_entities)
         assert (
             inline_query_result_mpeg4_gif.input_message_content.to_dict()
-            == self.input_message_content.to_dict()
+            == Space.input_message_content.to_dict()
         )
-        assert inline_query_result_mpeg4_gif.reply_markup.to_dict() == self.reply_markup.to_dict()
+        assert inline_query_result_mpeg4_gif.reply_markup.to_dict() == Space.reply_markup.to_dict()
 
     def test_caption_entities_always_tuple(self):
-        result = InlineQueryResultMpeg4Gif(self.id_, self.mpeg4_url, self.thumb_url)
+        result = InlineQueryResultMpeg4Gif(Space.id_, Space.mpeg4_url, Space.thumb_url)
         assert result.caption_entities == ()
 
     def test_to_dict(self, inline_query_result_mpeg4_gif):
@@ -143,11 +145,11 @@ def test_to_dict(self, inline_query_result_mpeg4_gif):
         )
 
     def test_equality(self):
-        a = InlineQueryResultMpeg4Gif(self.id_, self.mpeg4_url, self.thumb_url)
-        b = InlineQueryResultMpeg4Gif(self.id_, self.mpeg4_url, self.thumb_url)
-        c = InlineQueryResultMpeg4Gif(self.id_, "", self.thumb_url)
-        d = InlineQueryResultMpeg4Gif("", self.mpeg4_url, self.thumb_url)
-        e = InlineQueryResultVoice(self.id_, "", "")
+        a = InlineQueryResultMpeg4Gif(Space.id_, Space.mpeg4_url, Space.thumb_url)
+        b = InlineQueryResultMpeg4Gif(Space.id_, Space.mpeg4_url, Space.thumb_url)
+        c = InlineQueryResultMpeg4Gif(Space.id_, "", Space.thumb_url)
+        d = InlineQueryResultMpeg4Gif("", Space.mpeg4_url, Space.thumb_url)
+        e = InlineQueryResultVoice(Space.id_, "", "")
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inlinequeryresultphoto.py b/tests/test_inlinequeryresultphoto.py
index 0e40fc5a3db..c9864b0200a 100644
--- a/tests/test_inlinequeryresultphoto.py
+++ b/tests/test_inlinequeryresultphoto.py
@@ -28,25 +28,25 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query_result_photo():
     return InlineQueryResultPhoto(
-        TestInlineQueryResultPhoto.id_,
-        TestInlineQueryResultPhoto.photo_url,
-        TestInlineQueryResultPhoto.thumb_url,
-        photo_width=TestInlineQueryResultPhoto.photo_width,
-        photo_height=TestInlineQueryResultPhoto.photo_height,
-        title=TestInlineQueryResultPhoto.title,
-        description=TestInlineQueryResultPhoto.description,
-        caption=TestInlineQueryResultPhoto.caption,
-        parse_mode=TestInlineQueryResultPhoto.parse_mode,
-        caption_entities=TestInlineQueryResultPhoto.caption_entities,
-        input_message_content=TestInlineQueryResultPhoto.input_message_content,
-        reply_markup=TestInlineQueryResultPhoto.reply_markup,
+        Space.id_,
+        Space.photo_url,
+        Space.thumb_url,
+        photo_width=Space.photo_width,
+        photo_height=Space.photo_height,
+        title=Space.title,
+        description=Space.description,
+        caption=Space.caption,
+        parse_mode=Space.parse_mode,
+        caption_entities=Space.caption_entities,
+        input_message_content=Space.input_message_content,
+        reply_markup=Space.reply_markup,
     )
 
 
-class TestInlineQueryResultPhoto:
+class Space:
     id_ = "id"
     type_ = "photo"
     photo_url = "photo url"
@@ -62,6 +62,8 @@ class TestInlineQueryResultPhoto:
     input_message_content = InputTextMessageContent("input_message_content")
     reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
 
+
+class TestInlineQueryResultPhotoNoReq:
     def test_slot_behaviour(self, inline_query_result_photo, mro_slots):
         inst = inline_query_result_photo
         for attr in inst.__slots__:
@@ -69,25 +71,25 @@ def test_slot_behaviour(self, inline_query_result_photo, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, inline_query_result_photo):
-        assert inline_query_result_photo.type == self.type_
-        assert inline_query_result_photo.id == self.id_
-        assert inline_query_result_photo.photo_url == self.photo_url
-        assert inline_query_result_photo.photo_width == self.photo_width
-        assert inline_query_result_photo.photo_height == self.photo_height
-        assert inline_query_result_photo.thumb_url == self.thumb_url
-        assert inline_query_result_photo.title == self.title
-        assert inline_query_result_photo.description == self.description
-        assert inline_query_result_photo.caption == self.caption
-        assert inline_query_result_photo.parse_mode == self.parse_mode
-        assert inline_query_result_photo.caption_entities == tuple(self.caption_entities)
+        assert inline_query_result_photo.type == Space.type_
+        assert inline_query_result_photo.id == Space.id_
+        assert inline_query_result_photo.photo_url == Space.photo_url
+        assert inline_query_result_photo.photo_width == Space.photo_width
+        assert inline_query_result_photo.photo_height == Space.photo_height
+        assert inline_query_result_photo.thumb_url == Space.thumb_url
+        assert inline_query_result_photo.title == Space.title
+        assert inline_query_result_photo.description == Space.description
+        assert inline_query_result_photo.caption == Space.caption
+        assert inline_query_result_photo.parse_mode == Space.parse_mode
+        assert inline_query_result_photo.caption_entities == tuple(Space.caption_entities)
         assert (
             inline_query_result_photo.input_message_content.to_dict()
-            == self.input_message_content.to_dict()
+            == Space.input_message_content.to_dict()
         )
-        assert inline_query_result_photo.reply_markup.to_dict() == self.reply_markup.to_dict()
+        assert inline_query_result_photo.reply_markup.to_dict() == Space.reply_markup.to_dict()
 
     def test_caption_entities_always_tuple(self):
-        result = InlineQueryResultPhoto(self.id_, self.photo_url, self.thumb_url)
+        result = InlineQueryResultPhoto(Space.id_, Space.photo_url, Space.thumb_url)
         assert result.caption_entities == ()
 
     def test_to_dict(self, inline_query_result_photo):
@@ -124,11 +126,11 @@ def test_to_dict(self, inline_query_result_photo):
         )
 
     def test_equality(self):
-        a = InlineQueryResultPhoto(self.id_, self.photo_url, self.thumb_url)
-        b = InlineQueryResultPhoto(self.id_, self.photo_url, self.thumb_url)
-        c = InlineQueryResultPhoto(self.id_, "", self.thumb_url)
-        d = InlineQueryResultPhoto("", self.photo_url, self.thumb_url)
-        e = InlineQueryResultVoice(self.id_, "", "")
+        a = InlineQueryResultPhoto(Space.id_, Space.photo_url, Space.thumb_url)
+        b = InlineQueryResultPhoto(Space.id_, Space.photo_url, Space.thumb_url)
+        c = InlineQueryResultPhoto(Space.id_, "", Space.thumb_url)
+        d = InlineQueryResultPhoto("", Space.photo_url, Space.thumb_url)
+        e = InlineQueryResultVoice(Space.id_, "", "")
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inlinequeryresultvenue.py b/tests/test_inlinequeryresultvenue.py
index f9e4f6ab096..015b8615fbb 100644
--- a/tests/test_inlinequeryresultvenue.py
+++ b/tests/test_inlinequeryresultvenue.py
@@ -27,27 +27,27 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query_result_venue():
     return InlineQueryResultVenue(
-        TestInlineQueryResultVenue.id_,
-        TestInlineQueryResultVenue.latitude,
-        TestInlineQueryResultVenue.longitude,
-        TestInlineQueryResultVenue.title,
-        TestInlineQueryResultVenue.address,
-        foursquare_id=TestInlineQueryResultVenue.foursquare_id,
-        foursquare_type=TestInlineQueryResultVenue.foursquare_type,
-        thumb_url=TestInlineQueryResultVenue.thumb_url,
-        thumb_width=TestInlineQueryResultVenue.thumb_width,
-        thumb_height=TestInlineQueryResultVenue.thumb_height,
-        input_message_content=TestInlineQueryResultVenue.input_message_content,
-        reply_markup=TestInlineQueryResultVenue.reply_markup,
-        google_place_id=TestInlineQueryResultVenue.google_place_id,
-        google_place_type=TestInlineQueryResultVenue.google_place_type,
+        Space.id_,
+        Space.latitude,
+        Space.longitude,
+        Space.title,
+        Space.address,
+        foursquare_id=Space.foursquare_id,
+        foursquare_type=Space.foursquare_type,
+        thumb_url=Space.thumb_url,
+        thumb_width=Space.thumb_width,
+        thumb_height=Space.thumb_height,
+        input_message_content=Space.input_message_content,
+        reply_markup=Space.reply_markup,
+        google_place_id=Space.google_place_id,
+        google_place_type=Space.google_place_type,
     )
 
 
-class TestInlineQueryResultVenue:
+class Space:
     id_ = "id"
     type_ = "venue"
     latitude = "latitude"
@@ -64,6 +64,8 @@ class TestInlineQueryResultVenue:
     input_message_content = InputTextMessageContent("input_message_content")
     reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
 
+
+class TestInlineQueryResultVenueNoReq:
     def test_slot_behaviour(self, inline_query_result_venue, mro_slots):
         inst = inline_query_result_venue
         for attr in inst.__slots__:
@@ -71,24 +73,24 @@ def test_slot_behaviour(self, inline_query_result_venue, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, inline_query_result_venue):
-        assert inline_query_result_venue.id == self.id_
-        assert inline_query_result_venue.type == self.type_
-        assert inline_query_result_venue.latitude == self.latitude
-        assert inline_query_result_venue.longitude == self.longitude
-        assert inline_query_result_venue.title == self.title
-        assert inline_query_result_venue.address == self.address
-        assert inline_query_result_venue.foursquare_id == self.foursquare_id
-        assert inline_query_result_venue.foursquare_type == self.foursquare_type
-        assert inline_query_result_venue.google_place_id == self.google_place_id
-        assert inline_query_result_venue.google_place_type == self.google_place_type
-        assert inline_query_result_venue.thumb_url == self.thumb_url
-        assert inline_query_result_venue.thumb_width == self.thumb_width
-        assert inline_query_result_venue.thumb_height == self.thumb_height
+        assert inline_query_result_venue.id == Space.id_
+        assert inline_query_result_venue.type == Space.type_
+        assert inline_query_result_venue.latitude == Space.latitude
+        assert inline_query_result_venue.longitude == Space.longitude
+        assert inline_query_result_venue.title == Space.title
+        assert inline_query_result_venue.address == Space.address
+        assert inline_query_result_venue.foursquare_id == Space.foursquare_id
+        assert inline_query_result_venue.foursquare_type == Space.foursquare_type
+        assert inline_query_result_venue.google_place_id == Space.google_place_id
+        assert inline_query_result_venue.google_place_type == Space.google_place_type
+        assert inline_query_result_venue.thumb_url == Space.thumb_url
+        assert inline_query_result_venue.thumb_width == Space.thumb_width
+        assert inline_query_result_venue.thumb_height == Space.thumb_height
         assert (
             inline_query_result_venue.input_message_content.to_dict()
-            == self.input_message_content.to_dict()
+            == Space.input_message_content.to_dict()
         )
-        assert inline_query_result_venue.reply_markup.to_dict() == self.reply_markup.to_dict()
+        assert inline_query_result_venue.reply_markup.to_dict() == Space.reply_markup.to_dict()
 
     def test_to_dict(self, inline_query_result_venue):
         inline_query_result_venue_dict = inline_query_result_venue.to_dict()
@@ -135,14 +137,14 @@ def test_to_dict(self, inline_query_result_venue):
 
     def test_equality(self):
         a = InlineQueryResultVenue(
-            self.id_, self.longitude, self.latitude, self.title, self.address
+            Space.id_, Space.longitude, Space.latitude, Space.title, Space.address
         )
         b = InlineQueryResultVenue(
-            self.id_, self.longitude, self.latitude, self.title, self.address
+            Space.id_, Space.longitude, Space.latitude, Space.title, Space.address
         )
-        c = InlineQueryResultVenue(self.id_, "", self.latitude, self.title, self.address)
-        d = InlineQueryResultVenue("", self.longitude, self.latitude, self.title, self.address)
-        e = InlineQueryResultVoice(self.id_, "", "")
+        c = InlineQueryResultVenue(Space.id_, "", Space.latitude, Space.title, Space.address)
+        d = InlineQueryResultVenue("", Space.longitude, Space.latitude, Space.title, Space.address)
+        e = InlineQueryResultVoice(Space.id_, "", "")
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inlinequeryresultvideo.py b/tests/test_inlinequeryresultvideo.py
index dad63f132be..09cfb722541 100644
--- a/tests/test_inlinequeryresultvideo.py
+++ b/tests/test_inlinequeryresultvideo.py
@@ -28,27 +28,27 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query_result_video():
     return InlineQueryResultVideo(
-        TestInlineQueryResultVideo.id_,
-        TestInlineQueryResultVideo.video_url,
-        TestInlineQueryResultVideo.mime_type,
-        TestInlineQueryResultVideo.thumb_url,
-        TestInlineQueryResultVideo.title,
-        video_width=TestInlineQueryResultVideo.video_width,
-        video_height=TestInlineQueryResultVideo.video_height,
-        video_duration=TestInlineQueryResultVideo.video_duration,
-        caption=TestInlineQueryResultVideo.caption,
-        parse_mode=TestInlineQueryResultVideo.parse_mode,
-        caption_entities=TestInlineQueryResultVideo.caption_entities,
-        description=TestInlineQueryResultVideo.description,
-        input_message_content=TestInlineQueryResultVideo.input_message_content,
-        reply_markup=TestInlineQueryResultVideo.reply_markup,
+        Space.id_,
+        Space.video_url,
+        Space.mime_type,
+        Space.thumb_url,
+        Space.title,
+        video_width=Space.video_width,
+        video_height=Space.video_height,
+        video_duration=Space.video_duration,
+        caption=Space.caption,
+        parse_mode=Space.parse_mode,
+        caption_entities=Space.caption_entities,
+        description=Space.description,
+        input_message_content=Space.input_message_content,
+        reply_markup=Space.reply_markup,
     )
 
 
-class TestInlineQueryResultVideo:
+class Space:
     id_ = "id"
     type_ = "video"
     video_url = "video url"
@@ -65,6 +65,8 @@ class TestInlineQueryResultVideo:
     input_message_content = InputTextMessageContent("input_message_content")
     reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
 
+
+class TestInlineQueryResultVideoNoReq:
     def test_slot_behaviour(self, inline_query_result_video, mro_slots):
         inst = inline_query_result_video
         for attr in inst.__slots__:
@@ -72,28 +74,28 @@ def test_slot_behaviour(self, inline_query_result_video, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, inline_query_result_video):
-        assert inline_query_result_video.type == self.type_
-        assert inline_query_result_video.id == self.id_
-        assert inline_query_result_video.video_url == self.video_url
-        assert inline_query_result_video.mime_type == self.mime_type
-        assert inline_query_result_video.video_width == self.video_width
-        assert inline_query_result_video.video_height == self.video_height
-        assert inline_query_result_video.video_duration == self.video_duration
-        assert inline_query_result_video.thumb_url == self.thumb_url
-        assert inline_query_result_video.title == self.title
-        assert inline_query_result_video.description == self.description
-        assert inline_query_result_video.caption == self.caption
-        assert inline_query_result_video.parse_mode == self.parse_mode
-        assert inline_query_result_video.caption_entities == tuple(self.caption_entities)
+        assert inline_query_result_video.type == Space.type_
+        assert inline_query_result_video.id == Space.id_
+        assert inline_query_result_video.video_url == Space.video_url
+        assert inline_query_result_video.mime_type == Space.mime_type
+        assert inline_query_result_video.video_width == Space.video_width
+        assert inline_query_result_video.video_height == Space.video_height
+        assert inline_query_result_video.video_duration == Space.video_duration
+        assert inline_query_result_video.thumb_url == Space.thumb_url
+        assert inline_query_result_video.title == Space.title
+        assert inline_query_result_video.description == Space.description
+        assert inline_query_result_video.caption == Space.caption
+        assert inline_query_result_video.parse_mode == Space.parse_mode
+        assert inline_query_result_video.caption_entities == tuple(Space.caption_entities)
         assert (
             inline_query_result_video.input_message_content.to_dict()
-            == self.input_message_content.to_dict()
+            == Space.input_message_content.to_dict()
         )
-        assert inline_query_result_video.reply_markup.to_dict() == self.reply_markup.to_dict()
+        assert inline_query_result_video.reply_markup.to_dict() == Space.reply_markup.to_dict()
 
     def test_caption_entities_always_tuple(self):
         video = InlineQueryResultVideo(
-            self.id_, self.video_url, self.mime_type, self.thumb_url, self.title
+            Space.id_, Space.video_url, Space.mime_type, Space.thumb_url, Space.title
         )
         assert video.caption_entities == ()
 
@@ -137,14 +139,16 @@ def test_to_dict(self, inline_query_result_video):
 
     def test_equality(self):
         a = InlineQueryResultVideo(
-            self.id_, self.video_url, self.mime_type, self.thumb_url, self.title
+            Space.id_, Space.video_url, Space.mime_type, Space.thumb_url, Space.title
         )
         b = InlineQueryResultVideo(
-            self.id_, self.video_url, self.mime_type, self.thumb_url, self.title
+            Space.id_, Space.video_url, Space.mime_type, Space.thumb_url, Space.title
+        )
+        c = InlineQueryResultVideo(Space.id_, "", Space.mime_type, Space.thumb_url, Space.title)
+        d = InlineQueryResultVideo(
+            "", Space.video_url, Space.mime_type, Space.thumb_url, Space.title
         )
-        c = InlineQueryResultVideo(self.id_, "", self.mime_type, self.thumb_url, self.title)
-        d = InlineQueryResultVideo("", self.video_url, self.mime_type, self.thumb_url, self.title)
-        e = InlineQueryResultVoice(self.id_, "", "")
+        e = InlineQueryResultVoice(Space.id_, "", "")
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inlinequeryresultvoice.py b/tests/test_inlinequeryresultvoice.py
index 0a42aa86402..45046cc0200 100644
--- a/tests/test_inlinequeryresultvoice.py
+++ b/tests/test_inlinequeryresultvoice.py
@@ -28,22 +28,22 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def inline_query_result_voice():
     return InlineQueryResultVoice(
-        id=TestInlineQueryResultVoice.id_,
-        voice_url=TestInlineQueryResultVoice.voice_url,
-        title=TestInlineQueryResultVoice.title,
-        voice_duration=TestInlineQueryResultVoice.voice_duration,
-        caption=TestInlineQueryResultVoice.caption,
-        parse_mode=TestInlineQueryResultVoice.parse_mode,
-        caption_entities=TestInlineQueryResultVoice.caption_entities,
-        input_message_content=TestInlineQueryResultVoice.input_message_content,
-        reply_markup=TestInlineQueryResultVoice.reply_markup,
+        id=Space.id_,
+        voice_url=Space.voice_url,
+        title=Space.title,
+        voice_duration=Space.voice_duration,
+        caption=Space.caption,
+        parse_mode=Space.parse_mode,
+        caption_entities=Space.caption_entities,
+        input_message_content=Space.input_message_content,
+        reply_markup=Space.reply_markup,
     )
 
 
-class TestInlineQueryResultVoice:
+class Space:
     id_ = "id"
     type_ = "voice"
     voice_url = "voice url"
@@ -55,6 +55,8 @@ class TestInlineQueryResultVoice:
     input_message_content = InputTextMessageContent("input_message_content")
     reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("reply_markup")]])
 
+
+class TestInlineQueryResultVoiceNoReq:
     def test_slot_behaviour(self, inline_query_result_voice, mro_slots):
         inst = inline_query_result_voice
         for attr in inst.__slots__:
@@ -62,25 +64,25 @@ def test_slot_behaviour(self, inline_query_result_voice, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, inline_query_result_voice):
-        assert inline_query_result_voice.type == self.type_
-        assert inline_query_result_voice.id == self.id_
-        assert inline_query_result_voice.voice_url == self.voice_url
-        assert inline_query_result_voice.title == self.title
-        assert inline_query_result_voice.voice_duration == self.voice_duration
-        assert inline_query_result_voice.caption == self.caption
-        assert inline_query_result_voice.parse_mode == self.parse_mode
-        assert inline_query_result_voice.caption_entities == tuple(self.caption_entities)
+        assert inline_query_result_voice.type == Space.type_
+        assert inline_query_result_voice.id == Space.id_
+        assert inline_query_result_voice.voice_url == Space.voice_url
+        assert inline_query_result_voice.title == Space.title
+        assert inline_query_result_voice.voice_duration == Space.voice_duration
+        assert inline_query_result_voice.caption == Space.caption
+        assert inline_query_result_voice.parse_mode == Space.parse_mode
+        assert inline_query_result_voice.caption_entities == tuple(Space.caption_entities)
         assert (
             inline_query_result_voice.input_message_content.to_dict()
-            == self.input_message_content.to_dict()
+            == Space.input_message_content.to_dict()
         )
-        assert inline_query_result_voice.reply_markup.to_dict() == self.reply_markup.to_dict()
+        assert inline_query_result_voice.reply_markup.to_dict() == Space.reply_markup.to_dict()
 
     def test_caption_entities_always_tuple(self):
         result = InlineQueryResultVoice(
-            self.id_,
-            self.voice_url,
-            self.title,
+            Space.id_,
+            Space.voice_url,
+            Space.title,
         )
 
         assert result.caption_entities == ()
@@ -112,11 +114,11 @@ def test_to_dict(self, inline_query_result_voice):
         )
 
     def test_equality(self):
-        a = InlineQueryResultVoice(self.id_, self.voice_url, self.title)
-        b = InlineQueryResultVoice(self.id_, self.voice_url, self.title)
-        c = InlineQueryResultVoice(self.id_, "", self.title)
-        d = InlineQueryResultVoice("", self.voice_url, self.title)
-        e = InlineQueryResultAudio(self.id_, "", "")
+        a = InlineQueryResultVoice(Space.id_, Space.voice_url, Space.title)
+        b = InlineQueryResultVoice(Space.id_, Space.voice_url, Space.title)
+        c = InlineQueryResultVoice(Space.id_, "", Space.title)
+        d = InlineQueryResultVoice("", Space.voice_url, Space.title)
+        e = InlineQueryResultAudio(Space.id_, "", "")
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_inputcontactmessagecontent.py b/tests/test_inputcontactmessagecontent.py
index e06454afd9f..dad710d20d6 100644
--- a/tests/test_inputcontactmessagecontent.py
+++ b/tests/test_inputcontactmessagecontent.py
@@ -21,20 +21,18 @@
 from telegram import InputContactMessageContent, User
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def input_contact_message_content():
-    return InputContactMessageContent(
-        TestInputContactMessageContent.phone_number,
-        TestInputContactMessageContent.first_name,
-        last_name=TestInputContactMessageContent.last_name,
-    )
+    return InputContactMessageContent(Space.phone_number, Space.first_name, Space.last_name)
 
 
-class TestInputContactMessageContent:
+class Space:
     phone_number = "phone number"
     first_name = "first name"
     last_name = "last name"
 
+
+class TestInputContactMessageContentNoReq:
     def test_slot_behaviour(self, input_contact_message_content, mro_slots):
         inst = input_contact_message_content
         for attr in inst.__slots__:
@@ -42,9 +40,9 @@ def test_slot_behaviour(self, input_contact_message_content, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, input_contact_message_content):
-        assert input_contact_message_content.first_name == self.first_name
-        assert input_contact_message_content.phone_number == self.phone_number
-        assert input_contact_message_content.last_name == self.last_name
+        assert input_contact_message_content.first_name == Space.first_name
+        assert input_contact_message_content.phone_number == Space.phone_number
+        assert input_contact_message_content.last_name == Space.last_name
 
     def test_to_dict(self, input_contact_message_content):
         input_contact_message_content_dict = input_contact_message_content.to_dict()
diff --git a/tests/test_inputfile.py b/tests/test_inputfile.py
index 1de2f4e4721..bde7c935b00 100644
--- a/tests/test_inputfile.py
+++ b/tests/test_inputfile.py
@@ -26,12 +26,12 @@
 from tests.conftest import data_file
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def png_file():
     return data_file("game.png")
 
 
-class TestInputFile:
+class TestInputFileNoReq:
     def test_slot_behaviour(self, mro_slots):
         inst = InputFile(BytesIO(b"blah"), filename="tg.jpg")
         for attr in inst.__slots__:
@@ -139,6 +139,8 @@ def read(self):
             == "blah.jpg"
         )
 
+
+class TestInputFileReq:
     async def test_send_bytes(self, bot, chat_id):
         # We test this here and not at the respective test modules because it's not worth
         # duplicating the test for the different methods
diff --git a/tests/test_inputinvoicemessagecontent.py b/tests/test_inputinvoicemessagecontent.py
index 93b79d4cc73..3672be28806 100644
--- a/tests/test_inputinvoicemessagecontent.py
+++ b/tests/test_inputinvoicemessagecontent.py
@@ -22,33 +22,33 @@
 from telegram import InputInvoiceMessageContent, InputTextMessageContent, LabeledPrice
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def input_invoice_message_content():
     return InputInvoiceMessageContent(
-        title=TestInputInvoiceMessageContent.title,
-        description=TestInputInvoiceMessageContent.description,
-        payload=TestInputInvoiceMessageContent.payload,
-        provider_token=TestInputInvoiceMessageContent.provider_token,
-        currency=TestInputInvoiceMessageContent.currency,
-        prices=TestInputInvoiceMessageContent.prices,
-        max_tip_amount=TestInputInvoiceMessageContent.max_tip_amount,
-        suggested_tip_amounts=TestInputInvoiceMessageContent.suggested_tip_amounts,
-        provider_data=TestInputInvoiceMessageContent.provider_data,
-        photo_url=TestInputInvoiceMessageContent.photo_url,
-        photo_size=TestInputInvoiceMessageContent.photo_size,
-        photo_width=TestInputInvoiceMessageContent.photo_width,
-        photo_height=TestInputInvoiceMessageContent.photo_height,
-        need_name=TestInputInvoiceMessageContent.need_name,
-        need_phone_number=TestInputInvoiceMessageContent.need_phone_number,
-        need_email=TestInputInvoiceMessageContent.need_email,
-        need_shipping_address=TestInputInvoiceMessageContent.need_shipping_address,
-        send_phone_number_to_provider=TestInputInvoiceMessageContent.send_phone_number_to_provider,
-        send_email_to_provider=TestInputInvoiceMessageContent.send_email_to_provider,
-        is_flexible=TestInputInvoiceMessageContent.is_flexible,
+        title=Space.title,
+        description=Space.description,
+        payload=Space.payload,
+        provider_token=Space.provider_token,
+        currency=Space.currency,
+        prices=Space.prices,
+        max_tip_amount=Space.max_tip_amount,
+        suggested_tip_amounts=Space.suggested_tip_amounts,
+        provider_data=Space.provider_data,
+        photo_url=Space.photo_url,
+        photo_size=Space.photo_size,
+        photo_width=Space.photo_width,
+        photo_height=Space.photo_height,
+        need_name=Space.need_name,
+        need_phone_number=Space.need_phone_number,
+        need_email=Space.need_email,
+        need_shipping_address=Space.need_shipping_address,
+        send_phone_number_to_provider=Space.send_phone_number_to_provider,
+        send_email_to_provider=Space.send_email_to_provider,
+        is_flexible=Space.is_flexible,
     )
 
 
-class TestInputInvoiceMessageContent:
+class Space:
     title = "invoice title"
     description = "invoice description"
     payload = "invoice payload"
@@ -70,6 +70,8 @@ class TestInputInvoiceMessageContent:
     send_email_to_provider = True
     is_flexible = True
 
+
+class TestInputInvoiceMessageContentNoReq:
     def test_slot_behaviour(self, input_invoice_message_content, mro_slots):
         inst = input_invoice_message_content
         for attr in inst.__slots__:
@@ -77,67 +79,67 @@ def test_slot_behaviour(self, input_invoice_message_content, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, input_invoice_message_content):
-        assert input_invoice_message_content.title == self.title
-        assert input_invoice_message_content.description == self.description
-        assert input_invoice_message_content.payload == self.payload
-        assert input_invoice_message_content.provider_token == self.provider_token
-        assert input_invoice_message_content.currency == self.currency
-        assert input_invoice_message_content.prices == tuple(self.prices)
-        assert input_invoice_message_content.max_tip_amount == self.max_tip_amount
+        assert input_invoice_message_content.title == Space.title
+        assert input_invoice_message_content.description == Space.description
+        assert input_invoice_message_content.payload == Space.payload
+        assert input_invoice_message_content.provider_token == Space.provider_token
+        assert input_invoice_message_content.currency == Space.currency
+        assert input_invoice_message_content.prices == tuple(Space.prices)
+        assert input_invoice_message_content.max_tip_amount == Space.max_tip_amount
         assert input_invoice_message_content.suggested_tip_amounts == tuple(
-            int(amount) for amount in self.suggested_tip_amounts
+            int(amount) for amount in Space.suggested_tip_amounts
         )
-        assert input_invoice_message_content.provider_data == self.provider_data
-        assert input_invoice_message_content.photo_url == self.photo_url
-        assert input_invoice_message_content.photo_size == int(self.photo_size)
-        assert input_invoice_message_content.photo_width == int(self.photo_width)
-        assert input_invoice_message_content.photo_height == int(self.photo_height)
-        assert input_invoice_message_content.need_name == self.need_name
-        assert input_invoice_message_content.need_phone_number == self.need_phone_number
-        assert input_invoice_message_content.need_email == self.need_email
-        assert input_invoice_message_content.need_shipping_address == self.need_shipping_address
+        assert input_invoice_message_content.provider_data == Space.provider_data
+        assert input_invoice_message_content.photo_url == Space.photo_url
+        assert input_invoice_message_content.photo_size == int(Space.photo_size)
+        assert input_invoice_message_content.photo_width == int(Space.photo_width)
+        assert input_invoice_message_content.photo_height == int(Space.photo_height)
+        assert input_invoice_message_content.need_name == Space.need_name
+        assert input_invoice_message_content.need_phone_number == Space.need_phone_number
+        assert input_invoice_message_content.need_email == Space.need_email
+        assert input_invoice_message_content.need_shipping_address == Space.need_shipping_address
         assert (
             input_invoice_message_content.send_phone_number_to_provider
-            == self.send_phone_number_to_provider
+            == Space.send_phone_number_to_provider
         )
-        assert input_invoice_message_content.send_email_to_provider == self.send_email_to_provider
-        assert input_invoice_message_content.is_flexible == self.is_flexible
+        assert input_invoice_message_content.send_email_to_provider == Space.send_email_to_provider
+        assert input_invoice_message_content.is_flexible == Space.is_flexible
 
     def test_suggested_tip_amonuts_always_tuple(self):
         input_invoice_message_content = InputInvoiceMessageContent(
-            title=self.title,
-            description=self.description,
-            payload=self.payload,
-            provider_token=self.provider_token,
-            currency=self.currency,
-            prices=self.prices,
-            max_tip_amount=self.max_tip_amount,
-            suggested_tip_amounts=self.suggested_tip_amounts,
-            provider_data=self.provider_data,
-            photo_url=self.photo_url,
-            photo_size=self.photo_size,
-            photo_width=self.photo_width,
-            photo_height=self.photo_height,
-            need_name=self.need_name,
-            need_phone_number=self.need_phone_number,
-            need_email=self.need_email,
-            need_shipping_address=self.need_shipping_address,
-            send_phone_number_to_provider=self.send_phone_number_to_provider,
-            send_email_to_provider=self.send_email_to_provider,
-            is_flexible=self.is_flexible,
+            title=Space.title,
+            description=Space.description,
+            payload=Space.payload,
+            provider_token=Space.provider_token,
+            currency=Space.currency,
+            prices=Space.prices,
+            max_tip_amount=Space.max_tip_amount,
+            suggested_tip_amounts=Space.suggested_tip_amounts,
+            provider_data=Space.provider_data,
+            photo_url=Space.photo_url,
+            photo_size=Space.photo_size,
+            photo_width=Space.photo_width,
+            photo_height=Space.photo_height,
+            need_name=Space.need_name,
+            need_phone_number=Space.need_phone_number,
+            need_email=Space.need_email,
+            need_shipping_address=Space.need_shipping_address,
+            send_phone_number_to_provider=Space.send_phone_number_to_provider,
+            send_email_to_provider=Space.send_email_to_provider,
+            is_flexible=Space.is_flexible,
         )
         assert isinstance(input_invoice_message_content.suggested_tip_amounts, tuple)
         assert input_invoice_message_content.suggested_tip_amounts == tuple(
-            int(amount) for amount in self.suggested_tip_amounts
+            int(amount) for amount in Space.suggested_tip_amounts
         )
 
         input_invoice_message_content = InputInvoiceMessageContent(
-            title=self.title,
-            description=self.description,
-            payload=self.payload,
-            provider_token=self.provider_token,
-            currency=self.currency,
-            prices=self.prices,
+            title=Space.title,
+            description=Space.description,
+            payload=Space.payload,
+            provider_token=Space.provider_token,
+            currency=Space.currency,
+            prices=Space.prices,
         )
         assert input_invoice_message_content.suggested_tip_amounts == tuple()
 
@@ -224,92 +226,92 @@ def test_de_json(self, bot):
         assert InputInvoiceMessageContent.de_json({}, bot=bot) is None
 
         json_dict = {
-            "title": self.title,
-            "description": self.description,
-            "payload": self.payload,
-            "provider_token": self.provider_token,
-            "currency": self.currency,
-            "prices": [price.to_dict() for price in self.prices],
-            "max_tip_amount": self.max_tip_amount,
-            "suggested_tip_amounts": self.suggested_tip_amounts,
-            "provider_data": self.provider_data,
-            "photo_url": self.photo_url,
-            "photo_size": self.photo_size,
-            "photo_width": self.photo_width,
-            "photo_height": self.photo_height,
-            "need_name": self.need_name,
-            "need_phone_number": self.need_phone_number,
-            "need_email": self.need_email,
-            "need_shipping_address": self.need_shipping_address,
-            "send_phone_number_to_provider": self.send_phone_number_to_provider,
-            "send_email_to_provider": self.send_email_to_provider,
-            "is_flexible": self.is_flexible,
+            "title": Space.title,
+            "description": Space.description,
+            "payload": Space.payload,
+            "provider_token": Space.provider_token,
+            "currency": Space.currency,
+            "prices": [price.to_dict() for price in Space.prices],
+            "max_tip_amount": Space.max_tip_amount,
+            "suggested_tip_amounts": Space.suggested_tip_amounts,
+            "provider_data": Space.provider_data,
+            "photo_url": Space.photo_url,
+            "photo_size": Space.photo_size,
+            "photo_width": Space.photo_width,
+            "photo_height": Space.photo_height,
+            "need_name": Space.need_name,
+            "need_phone_number": Space.need_phone_number,
+            "need_email": Space.need_email,
+            "need_shipping_address": Space.need_shipping_address,
+            "send_phone_number_to_provider": Space.send_phone_number_to_provider,
+            "send_email_to_provider": Space.send_email_to_provider,
+            "is_flexible": Space.is_flexible,
         }
 
         input_invoice_message_content = InputInvoiceMessageContent.de_json(json_dict, bot=bot)
         assert input_invoice_message_content.api_kwargs == {}
 
-        assert input_invoice_message_content.title == self.title
-        assert input_invoice_message_content.description == self.description
-        assert input_invoice_message_content.payload == self.payload
-        assert input_invoice_message_content.provider_token == self.provider_token
-        assert input_invoice_message_content.currency == self.currency
-        assert input_invoice_message_content.prices == tuple(self.prices)
-        assert input_invoice_message_content.max_tip_amount == self.max_tip_amount
+        assert input_invoice_message_content.title == Space.title
+        assert input_invoice_message_content.description == Space.description
+        assert input_invoice_message_content.payload == Space.payload
+        assert input_invoice_message_content.provider_token == Space.provider_token
+        assert input_invoice_message_content.currency == Space.currency
+        assert input_invoice_message_content.prices == tuple(Space.prices)
+        assert input_invoice_message_content.max_tip_amount == Space.max_tip_amount
         assert input_invoice_message_content.suggested_tip_amounts == tuple(
-            int(amount) for amount in self.suggested_tip_amounts
+            int(amount) for amount in Space.suggested_tip_amounts
         )
-        assert input_invoice_message_content.provider_data == self.provider_data
-        assert input_invoice_message_content.photo_url == self.photo_url
-        assert input_invoice_message_content.photo_size == int(self.photo_size)
-        assert input_invoice_message_content.photo_width == int(self.photo_width)
-        assert input_invoice_message_content.photo_height == int(self.photo_height)
-        assert input_invoice_message_content.need_name == self.need_name
-        assert input_invoice_message_content.need_phone_number == self.need_phone_number
-        assert input_invoice_message_content.need_email == self.need_email
-        assert input_invoice_message_content.need_shipping_address == self.need_shipping_address
+        assert input_invoice_message_content.provider_data == Space.provider_data
+        assert input_invoice_message_content.photo_url == Space.photo_url
+        assert input_invoice_message_content.photo_size == int(Space.photo_size)
+        assert input_invoice_message_content.photo_width == int(Space.photo_width)
+        assert input_invoice_message_content.photo_height == int(Space.photo_height)
+        assert input_invoice_message_content.need_name == Space.need_name
+        assert input_invoice_message_content.need_phone_number == Space.need_phone_number
+        assert input_invoice_message_content.need_email == Space.need_email
+        assert input_invoice_message_content.need_shipping_address == Space.need_shipping_address
         assert (
             input_invoice_message_content.send_phone_number_to_provider
-            == self.send_phone_number_to_provider
+            == Space.send_phone_number_to_provider
         )
-        assert input_invoice_message_content.send_email_to_provider == self.send_email_to_provider
-        assert input_invoice_message_content.is_flexible == self.is_flexible
+        assert input_invoice_message_content.send_email_to_provider == Space.send_email_to_provider
+        assert input_invoice_message_content.is_flexible == Space.is_flexible
 
     def test_equality(self):
         a = InputInvoiceMessageContent(
-            self.title,
-            self.description,
-            self.payload,
-            self.provider_token,
-            self.currency,
-            self.prices,
+            Space.title,
+            Space.description,
+            Space.payload,
+            Space.provider_token,
+            Space.currency,
+            Space.prices,
         )
         b = InputInvoiceMessageContent(
-            self.title,
-            self.description,
-            self.payload,
-            self.provider_token,
-            self.currency,
-            self.prices,
+            Space.title,
+            Space.description,
+            Space.payload,
+            Space.provider_token,
+            Space.currency,
+            Space.prices,
             max_tip_amount=100,
             provider_data="foobar",
         )
         c = InputInvoiceMessageContent(
-            self.title,
-            self.description,
-            self.payload,
-            self.provider_token,
-            self.currency,
+            Space.title,
+            Space.description,
+            Space.payload,
+            Space.provider_token,
+            Space.currency,
             # the first prices amount & the second lebal changed
             [LabeledPrice("label1", 24), LabeledPrice("label22", 314)],
         )
         d = InputInvoiceMessageContent(
-            self.title,
-            self.description,
+            Space.title,
+            Space.description,
             "different_payload",
-            self.provider_token,
-            self.currency,
-            self.prices,
+            Space.provider_token,
+            Space.currency,
+            Space.prices,
         )
         e = InputTextMessageContent("text")
 
diff --git a/tests/test_inputlocationmessagecontent.py b/tests/test_inputlocationmessagecontent.py
index 6c7249ac96c..06aef05d915 100644
--- a/tests/test_inputlocationmessagecontent.py
+++ b/tests/test_inputlocationmessagecontent.py
@@ -21,19 +21,19 @@
 from telegram import InputLocationMessageContent, Location
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def input_location_message_content():
     return InputLocationMessageContent(
-        TestInputLocationMessageContent.latitude,
-        TestInputLocationMessageContent.longitude,
-        live_period=TestInputLocationMessageContent.live_period,
-        horizontal_accuracy=TestInputLocationMessageContent.horizontal_accuracy,
-        heading=TestInputLocationMessageContent.heading,
-        proximity_alert_radius=TestInputLocationMessageContent.proximity_alert_radius,
+        Space.latitude,
+        Space.longitude,
+        live_period=Space.live_period,
+        horizontal_accuracy=Space.horizontal_accuracy,
+        heading=Space.heading,
+        proximity_alert_radius=Space.proximity_alert_radius,
     )
 
 
-class TestInputLocationMessageContent:
+class Space:
     latitude = -23.691288
     longitude = -46.788279
     live_period = 80
@@ -41,6 +41,8 @@ class TestInputLocationMessageContent:
     heading = 90
     proximity_alert_radius = 999
 
+
+class TestInputLocationMessageContentNoReq:
     def test_slot_behaviour(self, input_location_message_content, mro_slots):
         inst = input_location_message_content
         for attr in inst.__slots__:
@@ -48,12 +50,14 @@ def test_slot_behaviour(self, input_location_message_content, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, input_location_message_content):
-        assert input_location_message_content.longitude == self.longitude
-        assert input_location_message_content.latitude == self.latitude
-        assert input_location_message_content.live_period == self.live_period
-        assert input_location_message_content.horizontal_accuracy == self.horizontal_accuracy
-        assert input_location_message_content.heading == self.heading
-        assert input_location_message_content.proximity_alert_radius == self.proximity_alert_radius
+        assert input_location_message_content.longitude == Space.longitude
+        assert input_location_message_content.latitude == Space.latitude
+        assert input_location_message_content.live_period == Space.live_period
+        assert input_location_message_content.horizontal_accuracy == Space.horizontal_accuracy
+        assert input_location_message_content.heading == Space.heading
+        assert (
+            input_location_message_content.proximity_alert_radius == Space.proximity_alert_radius
+        )
 
     def test_to_dict(self, input_location_message_content):
         input_location_message_content_dict = input_location_message_content.to_dict()
diff --git a/tests/test_inputmedia.py b/tests/test_inputmedia.py
index d7f0e96789d..d0690b8d8c2 100644
--- a/tests/test_inputmedia.py
+++ b/tests/test_inputmedia.py
@@ -16,6 +16,7 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see [http://www.gnu.org/licenses/].
+import asyncio
 import copy
 
 import pytest
@@ -55,72 +56,72 @@
 from .test_video import video, video_file  # noqa: F401
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def input_media_video(class_thumb_file):
     return InputMediaVideo(
-        media=TestInputMediaVideo.media,
-        caption=TestInputMediaVideo.caption,
-        width=TestInputMediaVideo.width,
-        height=TestInputMediaVideo.height,
-        duration=TestInputMediaVideo.duration,
-        parse_mode=TestInputMediaVideo.parse_mode,
-        caption_entities=TestInputMediaVideo.caption_entities,
+        media=VideoSpace.media,
+        caption=VideoSpace.caption,
+        width=VideoSpace.width,
+        height=VideoSpace.height,
+        duration=VideoSpace.duration,
+        parse_mode=VideoSpace.parse_mode,
+        caption_entities=VideoSpace.caption_entities,
         thumb=class_thumb_file,
-        supports_streaming=TestInputMediaVideo.supports_streaming,
+        supports_streaming=VideoSpace.supports_streaming,
     )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def input_media_photo(class_thumb_file):
     return InputMediaPhoto(
-        media=TestInputMediaPhoto.media,
-        caption=TestInputMediaPhoto.caption,
-        parse_mode=TestInputMediaPhoto.parse_mode,
-        caption_entities=TestInputMediaPhoto.caption_entities,
+        media=PhotoSpace.media,
+        caption=PhotoSpace.caption,
+        parse_mode=PhotoSpace.parse_mode,
+        caption_entities=PhotoSpace.caption_entities,
     )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def input_media_animation(class_thumb_file):
     return InputMediaAnimation(
-        media=TestInputMediaAnimation.media,
-        caption=TestInputMediaAnimation.caption,
-        parse_mode=TestInputMediaAnimation.parse_mode,
-        caption_entities=TestInputMediaAnimation.caption_entities,
-        width=TestInputMediaAnimation.width,
-        height=TestInputMediaAnimation.height,
+        media=AnimationSpace.media,
+        caption=AnimationSpace.caption,
+        parse_mode=AnimationSpace.parse_mode,
+        caption_entities=AnimationSpace.caption_entities,
+        width=AnimationSpace.width,
+        height=AnimationSpace.height,
         thumb=class_thumb_file,
-        duration=TestInputMediaAnimation.duration,
+        duration=AnimationSpace.duration,
     )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def input_media_audio(class_thumb_file):
     return InputMediaAudio(
-        media=TestInputMediaAudio.media,
-        caption=TestInputMediaAudio.caption,
-        duration=TestInputMediaAudio.duration,
-        performer=TestInputMediaAudio.performer,
-        title=TestInputMediaAudio.title,
+        media=AudioSpace.media,
+        caption=AudioSpace.caption,
+        duration=AudioSpace.duration,
+        performer=AudioSpace.performer,
+        title=AudioSpace.title,
         thumb=class_thumb_file,
-        parse_mode=TestInputMediaAudio.parse_mode,
-        caption_entities=TestInputMediaAudio.caption_entities,
+        parse_mode=AudioSpace.parse_mode,
+        caption_entities=AudioSpace.caption_entities,
     )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def input_media_document(class_thumb_file):
     return InputMediaDocument(
-        media=TestInputMediaDocument.media,
-        caption=TestInputMediaDocument.caption,
+        media=DocumentSpace.media,
+        caption=DocumentSpace.caption,
         thumb=class_thumb_file,
-        parse_mode=TestInputMediaDocument.parse_mode,
-        caption_entities=TestInputMediaDocument.caption_entities,
-        disable_content_type_detection=TestInputMediaDocument.disable_content_type_detection,
+        parse_mode=DocumentSpace.parse_mode,
+        caption_entities=DocumentSpace.caption_entities,
+        disable_content_type_detection=DocumentSpace.disable_content_type_detection,
     )
 
 
-class TestInputMediaVideo:
+class VideoSpace:
     type_ = "video"
     media = "NOTAREALFILEID"
     caption = "My Caption"
@@ -131,6 +132,8 @@ class TestInputMediaVideo:
     supports_streaming = True
     caption_entities = [MessageEntity(MessageEntity.BOLD, 0, 2)]
 
+
+class TestInputMediaVideoNoReq:
     def test_slot_behaviour(self, input_media_video, mro_slots):
         inst = input_media_video
         for attr in inst.__slots__:
@@ -138,19 +141,19 @@ def test_slot_behaviour(self, input_media_video, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, input_media_video):
-        assert input_media_video.type == self.type_
-        assert input_media_video.media == self.media
-        assert input_media_video.caption == self.caption
-        assert input_media_video.width == self.width
-        assert input_media_video.height == self.height
-        assert input_media_video.duration == self.duration
-        assert input_media_video.parse_mode == self.parse_mode
-        assert input_media_video.caption_entities == tuple(self.caption_entities)
-        assert input_media_video.supports_streaming == self.supports_streaming
+        assert input_media_video.type == VideoSpace.type_
+        assert input_media_video.media == VideoSpace.media
+        assert input_media_video.caption == VideoSpace.caption
+        assert input_media_video.width == VideoSpace.width
+        assert input_media_video.height == VideoSpace.height
+        assert input_media_video.duration == VideoSpace.duration
+        assert input_media_video.parse_mode == VideoSpace.parse_mode
+        assert input_media_video.caption_entities == tuple(VideoSpace.caption_entities)
+        assert input_media_video.supports_streaming == VideoSpace.supports_streaming
         assert isinstance(input_media_video.thumb, InputFile)
 
     def test_caption_entities_always_tuple(self):
-        input_media_video = InputMediaVideo(self.media)
+        input_media_video = InputMediaVideo(VideoSpace.media)
         assert input_media_video.caption_entities == ()
 
     def test_to_dict(self, input_media_video):
@@ -170,7 +173,7 @@ def test_to_dict(self, input_media_video):
     def test_with_video(self, video):  # noqa: F811
         # fixture found in test_video
         input_media_video = InputMediaVideo(video, caption="test 3")
-        assert input_media_video.type == self.type_
+        assert input_media_video.type == VideoSpace.type_
         assert input_media_video.media == video.file_id
         assert input_media_video.width == video.width
         assert input_media_video.height == video.height
@@ -180,7 +183,7 @@ def test_with_video(self, video):  # noqa: F811
     def test_with_video_file(self, video_file):  # noqa: F811
         # fixture found in test_video
         input_media_video = InputMediaVideo(video_file, caption="test 3")
-        assert input_media_video.type == self.type_
+        assert input_media_video.type == VideoSpace.type_
         assert isinstance(input_media_video.media, InputFile)
         assert input_media_video.caption == "test 3"
 
@@ -192,13 +195,15 @@ def test_with_local_files(self):
         assert input_media_video.thumb == data_file("telegram.jpg").as_uri()
 
 
-class TestInputMediaPhoto:
+class PhotoSpace:
     type_ = "photo"
     media = "NOTAREALFILEID"
     caption = "My Caption"
     parse_mode = "Markdown"
     caption_entities = [MessageEntity(MessageEntity.BOLD, 0, 2)]
 
+
+class TestInputMediaPhotoNoReq:
     def test_slot_behaviour(self, input_media_photo, mro_slots):
         inst = input_media_photo
         for attr in inst.__slots__:
@@ -206,14 +211,14 @@ def test_slot_behaviour(self, input_media_photo, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, input_media_photo):
-        assert input_media_photo.type == self.type_
-        assert input_media_photo.media == self.media
-        assert input_media_photo.caption == self.caption
-        assert input_media_photo.parse_mode == self.parse_mode
-        assert input_media_photo.caption_entities == tuple(self.caption_entities)
+        assert input_media_photo.type == PhotoSpace.type_
+        assert input_media_photo.media == PhotoSpace.media
+        assert input_media_photo.caption == PhotoSpace.caption
+        assert input_media_photo.parse_mode == PhotoSpace.parse_mode
+        assert input_media_photo.caption_entities == tuple(PhotoSpace.caption_entities)
 
     def test_caption_entities_always_tuple(self):
-        input_media_photo = InputMediaPhoto(self.media)
+        input_media_photo = InputMediaPhoto(PhotoSpace.media)
         assert input_media_photo.caption_entities == ()
 
     def test_to_dict(self, input_media_photo):
@@ -229,14 +234,14 @@ def test_to_dict(self, input_media_photo):
     def test_with_photo(self, photo):  # noqa: F811
         # fixture found in test_photo
         input_media_photo = InputMediaPhoto(photo, caption="test 2")
-        assert input_media_photo.type == self.type_
+        assert input_media_photo.type == PhotoSpace.type_
         assert input_media_photo.media == photo.file_id
         assert input_media_photo.caption == "test 2"
 
     def test_with_photo_file(self, photo_file):  # noqa: F811
         # fixture found in test_photo
         input_media_photo = InputMediaPhoto(photo_file, caption="test 2")
-        assert input_media_photo.type == self.type_
+        assert input_media_photo.type == PhotoSpace.type_
         assert isinstance(input_media_photo.media, InputFile)
         assert input_media_photo.caption == "test 2"
 
@@ -245,7 +250,7 @@ def test_with_local_files(self):
         assert input_media_photo.media == data_file("telegram.mp4").as_uri()
 
 
-class TestInputMediaAnimation:
+class AnimationSpace:
     type_ = "animation"
     media = "NOTAREALFILEID"
     caption = "My Caption"
@@ -255,6 +260,8 @@ class TestInputMediaAnimation:
     height = 30
     duration = 1
 
+
+class TestInputMediaAnimationNoReq:
     def test_slot_behaviour(self, input_media_animation, mro_slots):
         inst = input_media_animation
         for attr in inst.__slots__:
@@ -262,15 +269,15 @@ def test_slot_behaviour(self, input_media_animation, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, input_media_animation):
-        assert input_media_animation.type == self.type_
-        assert input_media_animation.media == self.media
-        assert input_media_animation.caption == self.caption
-        assert input_media_animation.parse_mode == self.parse_mode
-        assert input_media_animation.caption_entities == tuple(self.caption_entities)
+        assert input_media_animation.type == AnimationSpace.type_
+        assert input_media_animation.media == AnimationSpace.media
+        assert input_media_animation.caption == AnimationSpace.caption
+        assert input_media_animation.parse_mode == AnimationSpace.parse_mode
+        assert input_media_animation.caption_entities == tuple(AnimationSpace.caption_entities)
         assert isinstance(input_media_animation.thumb, InputFile)
 
     def test_caption_entities_always_tuple(self):
-        input_media_animation = InputMediaAnimation(self.media)
+        input_media_animation = InputMediaAnimation(AnimationSpace.media)
         assert input_media_animation.caption_entities == ()
 
     def test_to_dict(self, input_media_animation):
@@ -289,14 +296,14 @@ def test_to_dict(self, input_media_animation):
     def test_with_animation(self, animation):  # noqa: F811
         # fixture found in test_animation
         input_media_animation = InputMediaAnimation(animation, caption="test 2")
-        assert input_media_animation.type == self.type_
+        assert input_media_animation.type == AnimationSpace.type_
         assert input_media_animation.media == animation.file_id
         assert input_media_animation.caption == "test 2"
 
     def test_with_animation_file(self, animation_file):  # noqa: F811
         # fixture found in test_animation
         input_media_animation = InputMediaAnimation(animation_file, caption="test 2")
-        assert input_media_animation.type == self.type_
+        assert input_media_animation.type == AnimationSpace.type_
         assert isinstance(input_media_animation.media, InputFile)
         assert input_media_animation.caption == "test 2"
 
@@ -308,7 +315,7 @@ def test_with_local_files(self):
         assert input_media_animation.thumb == data_file("telegram.jpg").as_uri()
 
 
-class TestInputMediaAudio:
+class AudioSpace:
     type_ = "audio"
     media = "NOTAREALFILEID"
     caption = "My Caption"
@@ -318,6 +325,8 @@ class TestInputMediaAudio:
     parse_mode = "HTML"
     caption_entities = [MessageEntity(MessageEntity.BOLD, 0, 2)]
 
+
+class TestInputMediaAudioNoReq:
     def test_slot_behaviour(self, input_media_audio, mro_slots):
         inst = input_media_audio
         for attr in inst.__slots__:
@@ -325,18 +334,18 @@ def test_slot_behaviour(self, input_media_audio, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, input_media_audio):
-        assert input_media_audio.type == self.type_
-        assert input_media_audio.media == self.media
-        assert input_media_audio.caption == self.caption
-        assert input_media_audio.duration == self.duration
-        assert input_media_audio.performer == self.performer
-        assert input_media_audio.title == self.title
-        assert input_media_audio.parse_mode == self.parse_mode
-        assert input_media_audio.caption_entities == tuple(self.caption_entities)
+        assert input_media_audio.type == AudioSpace.type_
+        assert input_media_audio.media == AudioSpace.media
+        assert input_media_audio.caption == AudioSpace.caption
+        assert input_media_audio.duration == AudioSpace.duration
+        assert input_media_audio.performer == AudioSpace.performer
+        assert input_media_audio.title == AudioSpace.title
+        assert input_media_audio.parse_mode == AudioSpace.parse_mode
+        assert input_media_audio.caption_entities == tuple(AudioSpace.caption_entities)
         assert isinstance(input_media_audio.thumb, InputFile)
 
     def test_caption_entities_always_tuple(self):
-        input_media_audio = InputMediaAudio(self.media)
+        input_media_audio = InputMediaAudio(AudioSpace.media)
         assert input_media_audio.caption_entities == ()
 
     def test_to_dict(self, input_media_audio):
@@ -355,7 +364,7 @@ def test_to_dict(self, input_media_audio):
     def test_with_audio(self, audio):  # noqa: F811
         # fixture found in test_audio
         input_media_audio = InputMediaAudio(audio, caption="test 3")
-        assert input_media_audio.type == self.type_
+        assert input_media_audio.type == AudioSpace.type_
         assert input_media_audio.media == audio.file_id
         assert input_media_audio.duration == audio.duration
         assert input_media_audio.performer == audio.performer
@@ -365,7 +374,7 @@ def test_with_audio(self, audio):  # noqa: F811
     def test_with_audio_file(self, audio_file):  # noqa: F811
         # fixture found in test_audio
         input_media_audio = InputMediaAudio(audio_file, caption="test 3")
-        assert input_media_audio.type == self.type_
+        assert input_media_audio.type == AudioSpace.type_
         assert isinstance(input_media_audio.media, InputFile)
         assert input_media_audio.caption == "test 3"
 
@@ -377,7 +386,7 @@ def test_with_local_files(self):
         assert input_media_audio.thumb == data_file("telegram.jpg").as_uri()
 
 
-class TestInputMediaDocument:
+class DocumentSpace:
     type_ = "document"
     media = "NOTAREALFILEID"
     caption = "My Caption"
@@ -385,6 +394,8 @@ class TestInputMediaDocument:
     caption_entities = [MessageEntity(MessageEntity.BOLD, 0, 2)]
     disable_content_type_detection = True
 
+
+class TestInputMediaDocumentNoReq:
     def test_slot_behaviour(self, input_media_document, mro_slots):
         inst = input_media_document
         for attr in inst.__slots__:
@@ -392,19 +403,19 @@ def test_slot_behaviour(self, input_media_document, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, input_media_document):
-        assert input_media_document.type == self.type_
-        assert input_media_document.media == self.media
-        assert input_media_document.caption == self.caption
-        assert input_media_document.parse_mode == self.parse_mode
-        assert input_media_document.caption_entities == tuple(self.caption_entities)
+        assert input_media_document.type == DocumentSpace.type_
+        assert input_media_document.media == DocumentSpace.media
+        assert input_media_document.caption == DocumentSpace.caption
+        assert input_media_document.parse_mode == DocumentSpace.parse_mode
+        assert input_media_document.caption_entities == tuple(DocumentSpace.caption_entities)
         assert (
             input_media_document.disable_content_type_detection
-            == self.disable_content_type_detection
+            == DocumentSpace.disable_content_type_detection
         )
         assert isinstance(input_media_document.thumb, InputFile)
 
     def test_caption_entities_always_tuple(self):
-        input_media_document = InputMediaDocument(self.media)
+        input_media_document = InputMediaDocument(DocumentSpace.media)
         assert input_media_document.caption_entities == ()
 
     def test_to_dict(self, input_media_document):
@@ -424,14 +435,14 @@ def test_to_dict(self, input_media_document):
     def test_with_document(self, document):  # noqa: F811
         # fixture found in test_document
         input_media_document = InputMediaDocument(document, caption="test 3")
-        assert input_media_document.type == self.type_
+        assert input_media_document.type == DocumentSpace.type_
         assert input_media_document.media == document.file_id
         assert input_media_document.caption == "test 3"
 
     def test_with_document_file(self, document_file):  # noqa: F811
         # fixture found in test_document
         input_media_document = InputMediaDocument(document_file, caption="test 3")
-        assert input_media_document.type == self.type_
+        assert input_media_document.type == DocumentSpace.type_
         assert isinstance(input_media_document.media, InputFile)
         assert input_media_document.caption == "test 3"
 
@@ -443,7 +454,7 @@ def test_with_local_files(self):
         assert input_media_document.thumb == data_file("telegram.jpg").as_uri()
 
 
-@pytest.fixture(scope="function")  # noqa: F811
+@pytest.fixture(scope="module")  # noqa: F811
 def media_group(photo, thumb):  # noqa: F811
     return [
         InputMediaPhoto(photo, caption="*photo* 1", parse_mode="Markdown"),
@@ -454,12 +465,12 @@ def media_group(photo, thumb):  # noqa: F811
     ]
 
 
-@pytest.fixture(scope="function")  # noqa: F811
+@pytest.fixture(scope="module")  # noqa: F811
 def media_group_no_caption_args(photo, thumb):  # noqa: F811
     return [InputMediaPhoto(photo), InputMediaPhoto(thumb), InputMediaPhoto(photo)]
 
 
-@pytest.fixture(scope="function")  # noqa: F811
+@pytest.fixture(scope="module")  # noqa: F811
 def media_group_no_caption_only_caption_entities(photo, thumb):  # noqa: F811
     return [
         InputMediaPhoto(photo, caption_entities=[MessageEntity(MessageEntity.BOLD, 0, 5)]),
@@ -467,7 +478,7 @@ def media_group_no_caption_only_caption_entities(photo, thumb):  # noqa: F811
     ]
 
 
-@pytest.fixture(scope="function")  # noqa: F811
+@pytest.fixture(scope="module")  # noqa: F811
 def media_group_no_caption_only_parse_mode(photo, thumb):  # noqa: F811
     return [
         InputMediaPhoto(photo, parse_mode="Markdown"),
@@ -475,8 +486,90 @@ def media_group_no_caption_only_parse_mode(photo, thumb):  # noqa: F811
     ]
 
 
-class TestSendMediaGroup:
-    @pytest.mark.flaky(3, 1)
+class TestSendMediaGroupNoReq:
+    async def test_send_media_group_throws_error_with_group_caption_and_individual_captions(
+        self,
+        bot,
+        chat_id,
+        media_group,
+        media_group_no_caption_only_caption_entities,
+        media_group_no_caption_only_parse_mode,
+    ):
+        for group in (
+            media_group,
+            media_group_no_caption_only_caption_entities,
+            media_group_no_caption_only_parse_mode,
+        ):
+            with pytest.raises(
+                ValueError,
+                match="You can only supply either group caption or media with captions.",
+            ):
+                await bot.send_media_group(chat_id, group, caption="foo")
+
+    async def test_send_media_group_custom_filename(
+        self,
+        bot,
+        chat_id,
+        photo_file,  # noqa: F811
+        animation_file,  # noqa: F811
+        audio_file,  # noqa: F811
+        video_file,  # noqa: F811
+        monkeypatch,
+    ):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            result = all(
+                field_tuple[0] == "custom_filename"
+                for field_tuple in request_data.multipart_data.values()
+            )
+            if result is True:
+                raise Exception("Test was successful")
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+
+        media = [
+            InputMediaAnimation(animation_file, filename="custom_filename"),
+            InputMediaAudio(audio_file, filename="custom_filename"),
+            InputMediaPhoto(photo_file, filename="custom_filename"),
+            InputMediaVideo(video_file, filename="custom_filename"),
+        ]
+
+        with pytest.raises(Exception, match="Test was successful"):
+            await bot.send_media_group(chat_id, media)
+
+    async def test_send_media_group_with_thumbs(
+        self, bot, chat_id, video_file, photo_file, monkeypatch  # noqa: F811
+    ):
+        async def make_assertion(method, url, request_data: RequestData, *args, **kwargs):
+            files = request_data.multipart_data
+            video_check = files[input_video.media.attach_name] == input_video.media.field_tuple
+            thumb_check = files[input_video.thumb.attach_name] == input_video.thumb.field_tuple
+            result = video_check and thumb_check
+            raise Exception(f"Test was {'successful' if result else 'failing'}")
+
+        monkeypatch.setattr(bot.request, "_request_wrapper", make_assertion)
+        input_video = InputMediaVideo(video_file, thumb=photo_file)
+        with pytest.raises(Exception, match="Test was successful"):
+            await bot.send_media_group(chat_id, [input_video, input_video])
+
+    async def test_edit_message_media_with_thumb(
+        self, bot, chat_id, video_file, photo_file, monkeypatch  # noqa: F811
+    ):
+        async def make_assertion(
+            method: str, url: str, request_data: RequestData = None, *args, **kwargs
+        ):
+            files = request_data.multipart_data
+            video_check = files[input_video.media.attach_name] == input_video.media.field_tuple
+            thumb_check = files[input_video.thumb.attach_name] == input_video.thumb.field_tuple
+            result = video_check and thumb_check
+            raise Exception(f"Test was {'successful' if result else 'failing'}")
+
+        monkeypatch.setattr(bot.request, "_request_wrapper", make_assertion)
+        input_video = InputMediaVideo(video_file, thumb=photo_file)
+        with pytest.raises(Exception, match="Test was successful"):
+            await bot.edit_message_media(chat_id=chat_id, message_id=123, media=input_video)
+
+
+class TestSendMediaGroupReq:
     async def test_send_media_group_photo(self, bot, chat_id, media_group):
         messages = await bot.send_media_group(chat_id, media_group)
         assert isinstance(messages, tuple)
@@ -488,6 +581,33 @@ async def test_send_media_group_photo(self, bot, chat_id, media_group):
             mes.caption_entities == (MessageEntity(MessageEntity.BOLD, 0, 5),) for mes in messages
         )
 
+    async def test_send_media_group_new_files(
+        self,
+        bot,
+        chat_id,
+        video_file,  # noqa: F811
+        photo_file,  # noqa: F811
+        animation_file,  # noqa: F811
+    ):
+        async def func():
+            return await bot.send_media_group(
+                chat_id,
+                [
+                    InputMediaVideo(video_file),
+                    InputMediaPhoto(photo_file),
+                    InputMediaPhoto(data_file("telegram.jpg").read_bytes()),
+                ],
+            )
+
+        messages = await expect_bad_request(
+            func, "Type of file mismatch", "Telegram did not accept the file."
+        )
+
+        assert isinstance(messages, tuple)
+        assert len(messages) == 3
+        assert all(isinstance(mes, Message) for mes in messages)
+        assert all(mes.media_group_id == messages[0].media_group_id for mes in messages)
+
     async def test_send_media_group_with_message_thread_id(
         self, bot, real_topic, forum_group_id, media_group  # noqa: F811
     ):
@@ -501,25 +621,6 @@ async def test_send_media_group_with_message_thread_id(
         assert all(isinstance(mes, Message) for mes in messages)
         assert all(i.message_thread_id == real_topic.message_thread_id for i in messages)
 
-    async def test_send_media_group_throws_error_with_group_caption_and_individual_captions(
-        self,
-        bot,
-        chat_id,
-        media_group,
-        media_group_no_caption_only_caption_entities,
-        media_group_no_caption_only_parse_mode,
-    ):
-        for group in (
-            media_group,
-            media_group_no_caption_only_caption_entities,
-            media_group_no_caption_only_parse_mode,
-        ):
-            with pytest.raises(
-                ValueError,
-                match="You can only supply either group caption or media with captions.",
-            ):
-                await bot.send_media_group(chat_id, group, caption="foo")
-
     @pytest.mark.parametrize(
         "caption, parse_mode, caption_entities",
         [
@@ -529,7 +630,6 @@ async def test_send_media_group_throws_error_with_group_caption_and_individual_c
             ("photo 1", None, [MessageEntity(MessageEntity.BOLD, 0, 5)]),
         ],
     )
-    @pytest.mark.flaky(3, 1)
     async def test_send_media_group_with_group_caption(
         self,
         bot,
@@ -574,16 +674,15 @@ async def test_send_media_group_with_group_caption(
         assert all(mes.caption is None for mes in other_messages)
         assert not any(mes.caption_entities for mes in other_messages)
 
-    @pytest.mark.flaky(3, 1)
     async def test_send_media_group_all_args(self, bot, raw_bot, chat_id, media_group):
         ext_bot = bot
-        for bot in (ext_bot, raw_bot):
-            # We need to test 1) below both the bot and raw_bot and setting this up with
-            # pytest.parametrize appears to be difficult ...
-
-            m1 = await bot.send_message(chat_id, text="test")
+        # We need to test 1) below both the bot and raw_bot and setting this up with
+        # pytest.parametrize appears to be difficult ...
+        aws = {b.send_message(chat_id, text="test") for b in (ext_bot, raw_bot)}
+        for msg_task in asyncio.as_completed(aws):
+            m1 = await msg_task
             copied_media_group = copy.copy(media_group)
-            messages = await bot.send_media_group(
+            messages = await m1.get_bot().send_media_group(
                 chat_id,
                 media_group,
                 disable_notification=True,
@@ -609,81 +708,6 @@ async def test_send_media_group_all_args(self, bot, raw_bot, chat_id, media_grou
             )
             assert all(mes.has_protected_content for mes in messages)
 
-    @pytest.mark.flaky(3, 1)
-    async def test_send_media_group_custom_filename(
-        self,
-        bot,
-        chat_id,
-        photo_file,  # noqa: F811
-        animation_file,  # noqa: F811
-        audio_file,  # noqa: F811
-        video_file,  # noqa: F811
-        monkeypatch,
-    ):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            result = all(
-                field_tuple[0] == "custom_filename"
-                for field_tuple in request_data.multipart_data.values()
-            )
-            if result is True:
-                raise Exception("Test was successful")
-
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-
-        media = [
-            InputMediaAnimation(animation_file, filename="custom_filename"),
-            InputMediaAudio(audio_file, filename="custom_filename"),
-            InputMediaPhoto(photo_file, filename="custom_filename"),
-            InputMediaVideo(video_file, filename="custom_filename"),
-        ]
-
-        with pytest.raises(Exception, match="Test was successful"):
-            await bot.send_media_group(chat_id, media)
-
-    async def test_send_media_group_with_thumbs(
-        self, bot, chat_id, video_file, photo_file, monkeypatch  # noqa: F811
-    ):
-        async def make_assertion(method, url, request_data: RequestData, *args, **kwargs):
-            files = request_data.multipart_data
-            video_check = files[input_video.media.attach_name] == input_video.media.field_tuple
-            thumb_check = files[input_video.thumb.attach_name] == input_video.thumb.field_tuple
-            result = video_check and thumb_check
-            raise Exception(f"Test was {'successful' if result else 'failing'}")
-
-        monkeypatch.setattr(bot.request, "_request_wrapper", make_assertion)
-        input_video = InputMediaVideo(video_file, thumb=photo_file)
-        with pytest.raises(Exception, match="Test was successful"):
-            await bot.send_media_group(chat_id, [input_video, input_video])
-
-    @pytest.mark.flaky(3, 1)  # noqa: F811
-    async def test_send_media_group_new_files(
-        self,
-        bot,
-        chat_id,
-        video_file,  # noqa: F811
-        photo_file,  # noqa: F811
-        animation_file,  # noqa: F811
-    ):
-        async def func():
-            return await bot.send_media_group(
-                chat_id,
-                [
-                    InputMediaVideo(video_file),
-                    InputMediaPhoto(photo_file),
-                    InputMediaPhoto(data_file("telegram.jpg").read_bytes()),
-                ],
-            )
-
-        messages = await expect_bad_request(
-            func, "Type of file mismatch", "Telegram did not accept the file."
-        )
-
-        assert isinstance(messages, tuple)
-        assert len(messages) == 3
-        assert all(isinstance(mes, Message) for mes in messages)
-        assert all(mes.media_group_id == messages[0].media_group_id for mes in messages)
-
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize(
         "default_bot,custom",
         [
@@ -717,19 +741,18 @@ async def test_send_media_group_default_allow_sending_without_reply(
                     chat_id, media_group, reply_to_message_id=reply_to_message.message_id
                 )
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
     async def test_send_media_group_default_protect_content(
         self, chat_id, media_group, default_bot
     ):
-        protected = await default_bot.send_media_group(chat_id, media_group)
-        assert all(msg.has_protected_content for msg in protected)
-        unprotected = await default_bot.send_media_group(
-            chat_id, media_group, protect_content=False
+        tasks = asyncio.gather(
+            default_bot.send_media_group(chat_id, media_group),
+            default_bot.send_media_group(chat_id, media_group, protect_content=False),
         )
+        protected, unprotected = await tasks
+        assert all(msg.has_protected_content for msg in protected)
         assert not all(msg.has_protected_content for msg in unprotected)
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": ParseMode.HTML}], indirect=True)
     async def test_send_media_group_default_parse_mode(
         self, chat_id, media_group_no_caption_args, default_bot
@@ -741,19 +764,21 @@ async def test_send_media_group_default_parse_mode(
         # make sure no parse_mode was set as a side effect
         assert not any(item.parse_mode for item in media_group_no_caption_args)
 
-        overridden_markdown_v2 = await default_bot.send_media_group(
-            chat_id,
-            media_group_no_caption_args.copy(),
-            caption="*photo* 1",
-            parse_mode=ParseMode.MARKDOWN_V2,
-        )
-
-        overridden_none = await default_bot.send_media_group(
-            chat_id,
-            media_group_no_caption_args.copy(),
-            caption="<b>photo</b> 1",
-            parse_mode=None,
+        tasks = asyncio.gather(
+            default_bot.send_media_group(
+                chat_id,
+                media_group_no_caption_args.copy(),
+                caption="*photo* 1",
+                parse_mode=ParseMode.MARKDOWN_V2,
+            ),
+            default_bot.send_media_group(
+                chat_id,
+                media_group_no_caption_args.copy(),
+                caption="<b>photo</b> 1",
+                parse_mode=None,
+            ),
         )
+        overridden_markdown_v2, overridden_none = await tasks
 
         # Make sure first message got the caption, which will lead to Telegram
         # displaying its caption as group caption
@@ -774,18 +799,20 @@ async def test_send_media_group_default_parse_mode(
             assert all(mes.caption is None for mes in other_messages)
             assert not any(mes.caption_entities for mes in other_messages)
 
-    @pytest.mark.flaky(3, 1)
     async def test_edit_message_media(self, bot, raw_bot, chat_id, media_group):
         ext_bot = bot
-        for bot in (ext_bot, raw_bot):
-            # We need to test 1) below both the bot and raw_bot and setting this up with
-            # pytest.parametrize appears to be difficult ...
-            messages = await bot.send_media_group(chat_id, media_group)
+        # We need to test 1) below both the bot and raw_bot and setting this up with
+        # pytest.parametrize appears to be difficult ...
+        aws = {b.send_media_group(chat_id, media_group) for b in (ext_bot, raw_bot)}
+        for msg_task in asyncio.as_completed(aws):
+            messages = await msg_task
             cid = messages[-1].chat.id
             mid = messages[-1].message_id
             copied_media = copy.copy(media_group[0])
-            new_message = await bot.edit_message_media(
-                chat_id=cid, message_id=mid, media=media_group[0]
+            new_message = (
+                await messages[-1]
+                .get_bot()
+                .edit_message_media(chat_id=cid, message_id=mid, media=media_group[0])
             )
             assert isinstance(new_message, Message)
 
@@ -793,7 +820,6 @@ async def test_edit_message_media(self, bot, raw_bot, chat_id, media_group):
             # make sure that the media was not modified
             assert media_group[0].parse_mode == copied_media.parse_mode
 
-    @pytest.mark.flaky(3, 1)
     async def test_edit_message_media_new_file(self, bot, chat_id, media_group, thumb_file):
         messages = await bot.send_media_group(chat_id, media_group)
         cid = messages[-1].chat.id
@@ -803,24 +829,6 @@ async def test_edit_message_media_new_file(self, bot, chat_id, media_group, thum
         )
         assert isinstance(new_message, Message)
 
-    async def test_edit_message_media_with_thumb(
-        self, bot, chat_id, video_file, photo_file, monkeypatch  # noqa: F811
-    ):
-        async def make_assertion(
-            method: str, url: str, request_data: RequestData = None, *args, **kwargs
-        ):
-            files = request_data.multipart_data
-            video_check = files[input_video.media.attach_name] == input_video.media.field_tuple
-            thumb_check = files[input_video.thumb.attach_name] == input_video.thumb.field_tuple
-            result = video_check and thumb_check
-            raise Exception(f"Test was {'successful' if result else 'failing'}")
-
-        monkeypatch.setattr(bot.request, "_request_wrapper", make_assertion)
-        input_video = InputMediaVideo(video_file, thumb=photo_file)
-        with pytest.raises(Exception, match="Test was successful"):
-            await bot.edit_message_media(chat_id=chat_id, message_id=123, media=input_video)
-
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize(
         "default_bot", [{"parse_mode": ParseMode.HTML}], indirect=True, ids=["HTML-Bot"]
     )
diff --git a/tests/test_inputtextmessagecontent.py b/tests/test_inputtextmessagecontent.py
index 6f288deebe2..cf2d5cc4e4d 100644
--- a/tests/test_inputtextmessagecontent.py
+++ b/tests/test_inputtextmessagecontent.py
@@ -22,22 +22,24 @@
 from telegram.constants import ParseMode
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def input_text_message_content():
     return InputTextMessageContent(
-        TestInputTextMessageContent.message_text,
-        parse_mode=TestInputTextMessageContent.parse_mode,
-        entities=TestInputTextMessageContent.entities,
-        disable_web_page_preview=TestInputTextMessageContent.disable_web_page_preview,
+        Space.message_text,
+        parse_mode=Space.parse_mode,
+        entities=Space.entities,
+        disable_web_page_preview=Space.disable_web_page_preview,
     )
 
 
-class TestInputTextMessageContent:
+class Space:
     message_text = "*message text*"
     parse_mode = ParseMode.MARKDOWN
     entities = [MessageEntity(MessageEntity.ITALIC, 0, 7)]
     disable_web_page_preview = True
 
+
+class TestInputTextMessageContentNoReq:
     def test_slot_behaviour(self, input_text_message_content, mro_slots):
         inst = input_text_message_content
         for attr in inst.__slots__:
@@ -45,10 +47,12 @@ def test_slot_behaviour(self, input_text_message_content, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, input_text_message_content):
-        assert input_text_message_content.parse_mode == self.parse_mode
-        assert input_text_message_content.message_text == self.message_text
-        assert input_text_message_content.disable_web_page_preview == self.disable_web_page_preview
-        assert input_text_message_content.entities == tuple(self.entities)
+        assert input_text_message_content.parse_mode == Space.parse_mode
+        assert input_text_message_content.message_text == Space.message_text
+        assert (
+            input_text_message_content.disable_web_page_preview == Space.disable_web_page_preview
+        )
+        assert input_text_message_content.entities == tuple(Space.entities)
 
     def test_entities_always_tuple(self):
         input_text_message_content = InputTextMessageContent("text")
diff --git a/tests/test_inputvenuemessagecontent.py b/tests/test_inputvenuemessagecontent.py
index c29edaa5814..00006c1bfbf 100644
--- a/tests/test_inputvenuemessagecontent.py
+++ b/tests/test_inputvenuemessagecontent.py
@@ -21,21 +21,21 @@
 from telegram import InputVenueMessageContent, Location
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def input_venue_message_content():
     return InputVenueMessageContent(
-        TestInputVenueMessageContent.latitude,
-        TestInputVenueMessageContent.longitude,
-        TestInputVenueMessageContent.title,
-        TestInputVenueMessageContent.address,
-        foursquare_id=TestInputVenueMessageContent.foursquare_id,
-        foursquare_type=TestInputVenueMessageContent.foursquare_type,
-        google_place_id=TestInputVenueMessageContent.google_place_id,
-        google_place_type=TestInputVenueMessageContent.google_place_type,
+        Space.latitude,
+        Space.longitude,
+        Space.title,
+        Space.address,
+        foursquare_id=Space.foursquare_id,
+        foursquare_type=Space.foursquare_type,
+        google_place_id=Space.google_place_id,
+        google_place_type=Space.google_place_type,
     )
 
 
-class TestInputVenueMessageContent:
+class Space:
     latitude = 1.0
     longitude = 2.0
     title = "title"
@@ -45,6 +45,8 @@ class TestInputVenueMessageContent:
     google_place_id = "google place id"
     google_place_type = "google place type"
 
+
+class TestInputVenueMessageContentNoReq:
     def test_slot_behaviour(self, input_venue_message_content, mro_slots):
         inst = input_venue_message_content
         for attr in inst.__slots__:
@@ -52,14 +54,14 @@ def test_slot_behaviour(self, input_venue_message_content, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, input_venue_message_content):
-        assert input_venue_message_content.longitude == self.longitude
-        assert input_venue_message_content.latitude == self.latitude
-        assert input_venue_message_content.title == self.title
-        assert input_venue_message_content.address == self.address
-        assert input_venue_message_content.foursquare_id == self.foursquare_id
-        assert input_venue_message_content.foursquare_type == self.foursquare_type
-        assert input_venue_message_content.google_place_id == self.google_place_id
-        assert input_venue_message_content.google_place_type == self.google_place_type
+        assert input_venue_message_content.longitude == Space.longitude
+        assert input_venue_message_content.latitude == Space.latitude
+        assert input_venue_message_content.title == Space.title
+        assert input_venue_message_content.address == Space.address
+        assert input_venue_message_content.foursquare_id == Space.foursquare_id
+        assert input_venue_message_content.foursquare_type == Space.foursquare_type
+        assert input_venue_message_content.google_place_id == Space.google_place_id
+        assert input_venue_message_content.google_place_type == Space.google_place_type
 
     def test_to_dict(self, input_venue_message_content):
         input_venue_message_content_dict = input_venue_message_content.to_dict()
diff --git a/tests/test_invoice.py b/tests/test_invoice.py
index 299afc59591..298b8eea77a 100644
--- a/tests/test_invoice.py
+++ b/tests/test_invoice.py
@@ -16,6 +16,8 @@
 #
 # You should have received a copy of the GNU Lesser Public License
 # along with this program.  If not, see [http://www.gnu.org/licenses/].
+import asyncio
+
 import pytest
 
 from telegram import Invoice, LabeledPrice
@@ -23,18 +25,18 @@
 from telegram.request import RequestData
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def invoice():
     return Invoice(
-        TestInvoice.title,
-        TestInvoice.description,
-        TestInvoice.start_parameter,
-        TestInvoice.currency,
-        TestInvoice.total_amount,
+        Space.title,
+        Space.description,
+        Space.start_parameter,
+        Space.currency,
+        Space.total_amount,
     )
 
 
-class TestInvoice:
+class Space:
     payload = "payload"
     prices = [LabeledPrice("Fish", 100), LabeledPrice("Fish Tax", 1000)]
     provider_data = """{"test":"test"}"""
@@ -46,6 +48,8 @@ class TestInvoice:
     max_tip_amount = 42
     suggested_tip_amounts = [13, 42]
 
+
+class TestInvoiceNoReq:
     def test_slot_behaviour(self, invoice, mro_slots):
         for attr in invoice.__slots__:
             assert getattr(invoice, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -54,21 +58,21 @@ def test_slot_behaviour(self, invoice, mro_slots):
     def test_de_json(self, bot):
         invoice_json = Invoice.de_json(
             {
-                "title": TestInvoice.title,
-                "description": TestInvoice.description,
-                "start_parameter": TestInvoice.start_parameter,
-                "currency": TestInvoice.currency,
-                "total_amount": TestInvoice.total_amount,
+                "title": Space.title,
+                "description": Space.description,
+                "start_parameter": Space.start_parameter,
+                "currency": Space.currency,
+                "total_amount": Space.total_amount,
             },
             bot,
         )
         assert invoice_json.api_kwargs == {}
 
-        assert invoice_json.title == self.title
-        assert invoice_json.description == self.description
-        assert invoice_json.start_parameter == self.start_parameter
-        assert invoice_json.currency == self.currency
-        assert invoice_json.total_amount == self.total_amount
+        assert invoice_json.title == Space.title
+        assert invoice_json.description == Space.description
+        assert invoice_json.start_parameter == Space.start_parameter
+        assert invoice_json.currency == Space.currency
+        assert invoice_json.total_amount == Space.total_amount
 
     def test_to_dict(self, invoice):
         invoice_dict = invoice.to_dict()
@@ -80,129 +84,6 @@ def test_to_dict(self, invoice):
         assert invoice_dict["currency"] == invoice.currency
         assert invoice_dict["total_amount"] == invoice.total_amount
 
-    @pytest.mark.flaky(3, 1)
-    async def test_send_required_args_only(self, bot, chat_id, provider_token):
-        message = await bot.send_invoice(
-            chat_id=chat_id,
-            title=self.title,
-            description=self.description,
-            payload=self.payload,
-            provider_token=provider_token,
-            currency=self.currency,
-            prices=self.prices,
-        )
-
-        assert message.invoice.currency == self.currency
-        assert message.invoice.start_parameter == ""
-        assert message.invoice.description == self.description
-        assert message.invoice.title == self.title
-        assert message.invoice.total_amount == self.total_amount
-
-        link = await bot.create_invoice_link(
-            title=self.title,
-            description=self.description,
-            payload=self.payload,
-            provider_token=provider_token,
-            currency=self.currency,
-            prices=self.prices,
-        )
-        assert isinstance(link, str)
-        assert link != ""
-
-    async def test_send_all_args_send_invoice(self, bot, chat_id, provider_token, monkeypatch):
-        message = await bot.send_invoice(
-            chat_id,
-            self.title,
-            self.description,
-            self.payload,
-            provider_token,
-            self.currency,
-            self.prices,
-            max_tip_amount=self.max_tip_amount,
-            suggested_tip_amounts=self.suggested_tip_amounts,
-            start_parameter=self.start_parameter,
-            provider_data=self.provider_data,
-            photo_url="https://raw.githubusercontent.com/"
-            "python-telegram-bot/logos/master/"
-            "logo/png/ptb-logo_240.png",
-            photo_size=240,
-            photo_width=240,
-            photo_height=240,
-            need_name=True,
-            need_phone_number=True,
-            need_email=True,
-            need_shipping_address=True,
-            send_phone_number_to_provider=True,
-            send_email_to_provider=True,
-            is_flexible=True,
-            disable_notification=True,
-            protect_content=True,
-        )
-
-        assert message.invoice.currency == self.currency
-        assert message.invoice.start_parameter == self.start_parameter
-        assert message.invoice.description == self.description
-        assert message.invoice.title == self.title
-        assert message.invoice.total_amount == self.total_amount
-        assert message.has_protected_content
-
-        # We do this next one as safety guard to make sure that we pass all of the optional
-        # parameters correctly because #2526 went unnoticed for 3 years …
-        async def make_assertion(*args, **_):
-            kwargs = args[1]
-            return (
-                kwargs["chat_id"] == "chat_id"
-                and kwargs["title"] == "title"
-                and kwargs["description"] == "description"
-                and kwargs["payload"] == "payload"
-                and kwargs["provider_token"] == "provider_token"
-                and kwargs["currency"] == "currency"
-                and kwargs["prices"] == self.prices
-                and kwargs["max_tip_amount"] == "max_tip_amount"
-                and kwargs["suggested_tip_amounts"] == "suggested_tip_amounts"
-                and kwargs["start_parameter"] == "start_parameter"
-                and kwargs["provider_data"] == "provider_data"
-                and kwargs["photo_url"] == "photo_url"
-                and kwargs["photo_size"] == "photo_size"
-                and kwargs["photo_width"] == "photo_width"
-                and kwargs["photo_height"] == "photo_height"
-                and kwargs["need_name"] == "need_name"
-                and kwargs["need_phone_number"] == "need_phone_number"
-                and kwargs["need_email"] == "need_email"
-                and kwargs["need_shipping_address"] == "need_shipping_address"
-                and kwargs["send_phone_number_to_provider"] == "send_phone_number_to_provider"
-                and kwargs["send_email_to_provider"] == "send_email_to_provider"
-                and kwargs["is_flexible"] == "is_flexible"
-            )
-
-        monkeypatch.setattr(bot, "_send_message", make_assertion)
-        assert await bot.send_invoice(
-            chat_id="chat_id",
-            title="title",
-            description="description",
-            payload="payload",
-            provider_token="provider_token",
-            currency="currency",
-            prices=self.prices,
-            max_tip_amount="max_tip_amount",
-            suggested_tip_amounts="suggested_tip_amounts",
-            start_parameter="start_parameter",
-            provider_data="provider_data",
-            photo_url="photo_url",
-            photo_size="photo_size",
-            photo_width="photo_width",
-            photo_height="photo_height",
-            need_name="need_name",
-            need_phone_number="need_phone_number",
-            need_email="need_email",
-            need_shipping_address="need_shipping_address",
-            send_phone_number_to_provider="send_phone_number_to_provider",
-            send_email_to_provider="send_email_to_provider",
-            is_flexible="is_flexible",
-            disable_notification=True,
-            protect_content=True,
-        )
-
     async def test_send_all_args_create_invoice_link(
         self, bot, chat_id, provider_token, monkeypatch
     ):
@@ -214,7 +95,7 @@ async def make_assertion(*args, **_):
                 and kwargs["payload"] == "payload"
                 and kwargs["provider_token"] == "provider_token"
                 and kwargs["currency"] == "currency"
-                and kwargs["prices"] == self.prices
+                and kwargs["prices"] == Space.prices
                 and kwargs["max_tip_amount"] == "max_tip_amount"
                 and kwargs["suggested_tip_amounts"] == "suggested_tip_amounts"
                 and kwargs["provider_data"] == "provider_data"
@@ -238,7 +119,7 @@ async def make_assertion(*args, **_):
             payload="payload",
             provider_token="provider_token",
             currency="currency",
-            prices=self.prices,
+            prices=Space.prices,
             max_tip_amount="max_tip_amount",
             suggested_tip_amounts="suggested_tip_amounts",
             provider_data="provider_data",
@@ -263,17 +144,91 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs):
 
         assert await bot.send_invoice(
             chat_id,
-            self.title,
-            self.description,
-            self.payload,
+            Space.title,
+            Space.description,
+            Space.payload,
             provider_token,
-            self.currency,
-            self.prices,
+            Space.currency,
+            Space.prices,
             provider_data={"test_data": 123456789},
-            start_parameter=self.start_parameter,
+            start_parameter=Space.start_parameter,
         )
 
-    @pytest.mark.flaky(3, 1)
+    def test_equality(self):
+        a = Invoice("invoice", "desc", "start", "EUR", 7)
+        b = Invoice("invoice", "desc", "start", "EUR", 7)
+        c = Invoice("invoices", "description", "stop", "USD", 8)
+        d = LabeledPrice("label", 5)
+
+        assert a == b
+        assert hash(a) == hash(b)
+
+        assert a != c
+        assert hash(a) != hash(c)
+
+        assert a != d
+        assert hash(a) != hash(d)
+
+
+class TestInvoiceReq:
+    async def test_send_required_args_only(self, bot, chat_id, provider_token):
+        send_inv_task = asyncio.create_task(
+            bot.send_invoice(
+                chat_id=chat_id,
+                title=Space.title,
+                description=Space.description,
+                payload=Space.payload,
+                provider_token=provider_token,
+                currency=Space.currency,
+                prices=Space.prices,
+            )
+        )
+        create_inv_link_task = asyncio.create_task(
+            bot.create_invoice_link(
+                title=Space.title,
+                description=Space.description,
+                payload=Space.payload,
+                provider_token=provider_token,
+                currency=Space.currency,
+                prices=Space.prices,
+            )
+        )
+
+        message = await send_inv_task
+        assert message.invoice.currency == Space.currency
+        assert message.invoice.start_parameter == ""
+        assert message.invoice.description == Space.description
+        assert message.invoice.title == Space.title
+        assert message.invoice.total_amount == Space.total_amount
+
+        link = await create_inv_link_task
+        assert isinstance(link, str)
+        assert link != ""
+        assert send_inv_task.done() and create_inv_link_task.done()
+
+    @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
+    async def test_send_invoice_default_protect_content(
+        self, chat_id, default_bot, provider_token
+    ):
+        tasks = asyncio.gather(
+            *(
+                default_bot.send_invoice(
+                    chat_id,
+                    Space.title,
+                    Space.description,
+                    Space.payload,
+                    provider_token,
+                    Space.currency,
+                    Space.prices,
+                    **i,
+                )
+                for i in ({}, {"protect_content": False})
+            )
+        )
+        protected, unprotected = await tasks
+        assert protected.has_protected_content
+        assert not unprotected.has_protected_content
+
     @pytest.mark.parametrize(
         "default_bot,custom",
         [
@@ -291,12 +246,12 @@ async def test_send_invoice_default_allow_sending_without_reply(
         if custom is not None:
             message = await default_bot.send_invoice(
                 chat_id,
-                self.title,
-                self.description,
-                self.payload,
+                Space.title,
+                Space.description,
+                Space.payload,
                 provider_token,
-                self.currency,
-                self.prices,
+                Space.currency,
+                Space.prices,
                 allow_sending_without_reply=custom,
                 reply_to_message_id=reply_to_message.message_id,
             )
@@ -304,12 +259,12 @@ async def test_send_invoice_default_allow_sending_without_reply(
         elif default_bot.defaults.allow_sending_without_reply:
             message = await default_bot.send_invoice(
                 chat_id,
-                self.title,
-                self.description,
-                self.payload,
+                Space.title,
+                Space.description,
+                Space.payload,
                 provider_token,
-                self.currency,
-                self.prices,
+                Space.currency,
+                Space.prices,
                 reply_to_message_id=reply_to_message.message_id,
             )
             assert message.reply_to_message is None
@@ -317,53 +272,105 @@ async def test_send_invoice_default_allow_sending_without_reply(
             with pytest.raises(BadRequest, match="message not found"):
                 await default_bot.send_invoice(
                     chat_id,
-                    self.title,
-                    self.description,
-                    self.payload,
+                    Space.title,
+                    Space.description,
+                    Space.payload,
                     provider_token,
-                    self.currency,
-                    self.prices,
+                    Space.currency,
+                    Space.prices,
                     reply_to_message_id=reply_to_message.message_id,
                 )
 
-    @pytest.mark.flaky(3, 1)
-    @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
-    async def test_send_invoice_default_protect_content(
-        self, chat_id, default_bot, provider_token
-    ):
-        protected = await default_bot.send_invoice(
-            chat_id,
-            self.title,
-            self.description,
-            self.payload,
-            provider_token,
-            self.currency,
-            self.prices,
-        )
-        assert protected.has_protected_content
-        unprotected = await default_bot.send_invoice(
+    async def test_send_all_args_send_invoice(self, bot, chat_id, provider_token, monkeypatch):
+        message = await bot.send_invoice(
             chat_id,
-            self.title,
-            self.description,
-            self.payload,
+            Space.title,
+            Space.description,
+            Space.payload,
             provider_token,
-            self.currency,
-            self.prices,
-            protect_content=False,
+            Space.currency,
+            Space.prices,
+            max_tip_amount=Space.max_tip_amount,
+            suggested_tip_amounts=Space.suggested_tip_amounts,
+            start_parameter=Space.start_parameter,
+            provider_data=Space.provider_data,
+            photo_url="https://raw.githubusercontent.com/"
+            "python-telegram-bot/logos/master/"
+            "logo/png/ptb-logo_240.png",
+            photo_size=240,
+            photo_width=240,
+            photo_height=240,
+            need_name=True,
+            need_phone_number=True,
+            need_email=True,
+            need_shipping_address=True,
+            send_phone_number_to_provider=True,
+            send_email_to_provider=True,
+            is_flexible=True,
+            disable_notification=True,
+            protect_content=True,
         )
-        assert not unprotected.has_protected_content
 
-    def test_equality(self):
-        a = Invoice("invoice", "desc", "start", "EUR", 7)
-        b = Invoice("invoice", "desc", "start", "EUR", 7)
-        c = Invoice("invoices", "description", "stop", "USD", 8)
-        d = LabeledPrice("label", 5)
-
-        assert a == b
-        assert hash(a) == hash(b)
+        assert message.invoice.currency == Space.currency
+        assert message.invoice.start_parameter == Space.start_parameter
+        assert message.invoice.description == Space.description
+        assert message.invoice.title == Space.title
+        assert message.invoice.total_amount == Space.total_amount
+        assert message.has_protected_content
 
-        assert a != c
-        assert hash(a) != hash(c)
+        # We do this next one as safety guard to make sure that we pass all of the optional
+        # parameters correctly because #2526 went unnoticed for 3 years …
+        async def make_assertion(*args, **_):
+            kwargs = args[1]
+            return (
+                kwargs["chat_id"] == "chat_id"
+                and kwargs["title"] == "title"
+                and kwargs["description"] == "description"
+                and kwargs["payload"] == "payload"
+                and kwargs["provider_token"] == "provider_token"
+                and kwargs["currency"] == "currency"
+                and kwargs["prices"] == Space.prices
+                and kwargs["max_tip_amount"] == "max_tip_amount"
+                and kwargs["suggested_tip_amounts"] == "suggested_tip_amounts"
+                and kwargs["start_parameter"] == "start_parameter"
+                and kwargs["provider_data"] == "provider_data"
+                and kwargs["photo_url"] == "photo_url"
+                and kwargs["photo_size"] == "photo_size"
+                and kwargs["photo_width"] == "photo_width"
+                and kwargs["photo_height"] == "photo_height"
+                and kwargs["need_name"] == "need_name"
+                and kwargs["need_phone_number"] == "need_phone_number"
+                and kwargs["need_email"] == "need_email"
+                and kwargs["need_shipping_address"] == "need_shipping_address"
+                and kwargs["send_phone_number_to_provider"] == "send_phone_number_to_provider"
+                and kwargs["send_email_to_provider"] == "send_email_to_provider"
+                and kwargs["is_flexible"] == "is_flexible"
+            )
 
-        assert a != d
-        assert hash(a) != hash(d)
+        monkeypatch.setattr(bot, "_send_message", make_assertion)
+        assert await bot.send_invoice(
+            chat_id="chat_id",
+            title="title",
+            description="description",
+            payload="payload",
+            provider_token="provider_token",
+            currency="currency",
+            prices=Space.prices,
+            max_tip_amount="max_tip_amount",
+            suggested_tip_amounts="suggested_tip_amounts",
+            start_parameter="start_parameter",
+            provider_data="provider_data",
+            photo_url="photo_url",
+            photo_size="photo_size",
+            photo_width="photo_width",
+            photo_height="photo_height",
+            need_name="need_name",
+            need_phone_number="need_phone_number",
+            need_email="need_email",
+            need_shipping_address="need_shipping_address",
+            send_phone_number_to_provider="send_phone_number_to_provider",
+            send_email_to_provider="send_email_to_provider",
+            is_flexible="is_flexible",
+            disable_notification=True,
+            protect_content=True,
+        )
diff --git a/tests/test_jobqueue.py b/tests/test_jobqueue.py
index 5488eb476b8..16d80216f27 100644
--- a/tests/test_jobqueue.py
+++ b/tests/test_jobqueue.py
@@ -27,9 +27,7 @@
 import pytest
 
 from telegram.ext import ApplicationBuilder, CallbackContext, ContextTypes, Job, JobQueue
-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))
+from tests.conftest import TEST_WITH_OPT_DEPS, make_bot
 
 if TEST_WITH_OPT_DEPS:
     import pytz
@@ -268,8 +266,8 @@ async def test_error(self, job_queue):
         await asyncio.sleep(0.3)
         assert self.result == 1
 
-    async def test_in_application(self, bot):
-        app = ApplicationBuilder().token(bot.token).build()
+    async def test_in_application(self, bot_info):
+        app = ApplicationBuilder().bot(make_bot(bot_info)).build()
         async with app:
             assert not app.job_queue.scheduler.running
             await app.start()
@@ -568,7 +566,7 @@ async def test_custom_context(self, bot, job_queue):
         )
         job_queue.set_application(application)
 
-        def callback(context):
+        async def callback(context):
             self.result = (
                 type(context),
                 context.user_data,
diff --git a/tests/test_keyboardbutton.py b/tests/test_keyboardbutton.py
index 87673b87412..d9f14126213 100644
--- a/tests/test_keyboardbutton.py
+++ b/tests/test_keyboardbutton.py
@@ -21,24 +21,26 @@
 from telegram import InlineKeyboardButton, KeyboardButton, KeyboardButtonPollType, WebAppInfo
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def keyboard_button():
     return KeyboardButton(
-        TestKeyboardButton.text,
-        request_location=TestKeyboardButton.request_location,
-        request_contact=TestKeyboardButton.request_contact,
-        request_poll=TestKeyboardButton.request_poll,
-        web_app=TestKeyboardButton.web_app,
+        Space.text,
+        request_location=Space.request_location,
+        request_contact=Space.request_contact,
+        request_poll=Space.request_poll,
+        web_app=Space.web_app,
     )
 
 
-class TestKeyboardButton:
+class Space:
     text = "text"
     request_location = True
     request_contact = True
     request_poll = KeyboardButtonPollType("quiz")
     web_app = WebAppInfo(url="https://example.com")
 
+
+class TestKeyboardButtonNoReq:
     def test_slot_behaviour(self, keyboard_button, mro_slots):
         inst = keyboard_button
         for attr in inst.__slots__:
@@ -46,11 +48,11 @@ def test_slot_behaviour(self, keyboard_button, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, keyboard_button):
-        assert keyboard_button.text == self.text
-        assert keyboard_button.request_location == self.request_location
-        assert keyboard_button.request_contact == self.request_contact
-        assert keyboard_button.request_poll == self.request_poll
-        assert keyboard_button.web_app == self.web_app
+        assert keyboard_button.text == Space.text
+        assert keyboard_button.request_location == Space.request_location
+        assert keyboard_button.request_contact == Space.request_contact
+        assert keyboard_button.request_poll == Space.request_poll
+        assert keyboard_button.web_app == Space.web_app
 
     def test_to_dict(self, keyboard_button):
         keyboard_button_dict = keyboard_button.to_dict()
@@ -64,20 +66,20 @@ def test_to_dict(self, keyboard_button):
 
     def test_de_json(self, bot):
         json_dict = {
-            "text": self.text,
-            "request_location": self.request_location,
-            "request_contact": self.request_contact,
-            "request_poll": self.request_poll.to_dict(),
-            "web_app": self.web_app.to_dict(),
+            "text": Space.text,
+            "request_location": Space.request_location,
+            "request_contact": Space.request_contact,
+            "request_poll": Space.request_poll.to_dict(),
+            "web_app": Space.web_app.to_dict(),
         }
 
         inline_keyboard_button = KeyboardButton.de_json(json_dict, None)
         assert inline_keyboard_button.api_kwargs == {}
-        assert inline_keyboard_button.text == self.text
-        assert inline_keyboard_button.request_location == self.request_location
-        assert inline_keyboard_button.request_contact == self.request_contact
-        assert inline_keyboard_button.request_poll == self.request_poll
-        assert inline_keyboard_button.web_app == self.web_app
+        assert inline_keyboard_button.text == Space.text
+        assert inline_keyboard_button.request_location == Space.request_location
+        assert inline_keyboard_button.request_contact == Space.request_contact
+        assert inline_keyboard_button.request_poll == Space.request_poll
+        assert inline_keyboard_button.web_app == Space.web_app
 
         none = KeyboardButton.de_json({}, None)
         assert none is None
diff --git a/tests/test_keyboardbuttonpolltype.py b/tests/test_keyboardbuttonpolltype.py
index 41d2f4fbc3b..978670d6264 100644
--- a/tests/test_keyboardbuttonpolltype.py
+++ b/tests/test_keyboardbuttonpolltype.py
@@ -21,14 +21,16 @@
 from telegram import KeyboardButtonPollType, Poll
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def keyboard_button_poll_type():
-    return KeyboardButtonPollType(TestKeyboardButtonPollType.type)
+    return KeyboardButtonPollType(Space.type)
 
 
-class TestKeyboardButtonPollType:
+class Space:
     type = Poll.QUIZ
 
+
+class TestKeyboardButtonPollTypeNoReq:
     def test_slot_behaviour(self, keyboard_button_poll_type, mro_slots):
         inst = keyboard_button_poll_type
         for attr in inst.__slots__:
@@ -38,7 +40,7 @@ def test_slot_behaviour(self, keyboard_button_poll_type, mro_slots):
     def test_to_dict(self, keyboard_button_poll_type):
         keyboard_button_poll_type_dict = keyboard_button_poll_type.to_dict()
         assert isinstance(keyboard_button_poll_type_dict, dict)
-        assert keyboard_button_poll_type_dict["type"] == self.type
+        assert keyboard_button_poll_type_dict["type"] == Space.type
 
     def test_equality(self):
         a = KeyboardButtonPollType(Poll.QUIZ)
diff --git a/tests/test_labeledprice.py b/tests/test_labeledprice.py
index 0586c3788fb..346d5bb69b8 100644
--- a/tests/test_labeledprice.py
+++ b/tests/test_labeledprice.py
@@ -21,15 +21,17 @@
 from telegram import LabeledPrice, Location
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def labeled_price():
-    return LabeledPrice(TestLabeledPrice.label, TestLabeledPrice.amount)
+    return LabeledPrice(Space.label, Space.amount)
 
 
-class TestLabeledPrice:
+class Space:
     label = "label"
     amount = 100
 
+
+class TestLabeledPriceNoReq:
     def test_slot_behaviour(self, labeled_price, mro_slots):
         inst = labeled_price
         for attr in inst.__slots__:
@@ -37,8 +39,8 @@ def test_slot_behaviour(self, labeled_price, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, labeled_price):
-        assert labeled_price.label == self.label
-        assert labeled_price.amount == self.amount
+        assert labeled_price.label == Space.label
+        assert labeled_price.amount == Space.amount
 
     def test_to_dict(self, labeled_price):
         labeled_price_dict = labeled_price.to_dict()
diff --git a/tests/test_location.py b/tests/test_location.py
index a33eb0fbc7e..157a4d88a94 100644
--- a/tests/test_location.py
+++ b/tests/test_location.py
@@ -16,6 +16,8 @@
 #
 # You should have received a copy of the GNU Lesser Public License
 # along with this program.  If not, see [http://www.gnu.org/licenses/].
+import asyncio
+
 import pytest
 
 from telegram import Location
@@ -23,19 +25,19 @@
 from telegram.request import RequestData
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def location():
     return Location(
-        latitude=TestLocation.latitude,
-        longitude=TestLocation.longitude,
-        horizontal_accuracy=TestLocation.horizontal_accuracy,
-        live_period=TestLocation.live_period,
-        heading=TestLocation.live_period,
-        proximity_alert_radius=TestLocation.proximity_alert_radius,
+        latitude=Space.latitude,
+        longitude=Space.longitude,
+        horizontal_accuracy=Space.horizontal_accuracy,
+        live_period=Space.live_period,
+        heading=Space.live_period,
+        proximity_alert_radius=Space.proximity_alert_radius,
     )
 
 
-class TestLocation:
+class Space:
     latitude = -23.691288
     longitude = -46.788279
     horizontal_accuracy = 999
@@ -43,6 +45,8 @@ class TestLocation:
     heading = 90
     proximity_alert_radius = 50
 
+
+class TestLocationNoReq:
     def test_slot_behaviour(self, location, mro_slots):
         for attr in location.__slots__:
             assert getattr(location, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -50,66 +54,22 @@ def test_slot_behaviour(self, location, mro_slots):
 
     def test_de_json(self, bot):
         json_dict = {
-            "latitude": TestLocation.latitude,
-            "longitude": TestLocation.longitude,
-            "horizontal_accuracy": TestLocation.horizontal_accuracy,
-            "live_period": TestLocation.live_period,
-            "heading": TestLocation.heading,
-            "proximity_alert_radius": TestLocation.proximity_alert_radius,
+            "latitude": Space.latitude,
+            "longitude": Space.longitude,
+            "horizontal_accuracy": Space.horizontal_accuracy,
+            "live_period": Space.live_period,
+            "heading": Space.heading,
+            "proximity_alert_radius": Space.proximity_alert_radius,
         }
         location = Location.de_json(json_dict, bot)
         assert location.api_kwargs == {}
 
-        assert location.latitude == self.latitude
-        assert location.longitude == self.longitude
-        assert location.horizontal_accuracy == self.horizontal_accuracy
-        assert location.live_period == self.live_period
-        assert location.heading == self.heading
-        assert location.proximity_alert_radius == self.proximity_alert_radius
-
-    @pytest.mark.flaky(3, 1)
-    @pytest.mark.xfail
-    async def test_send_live_location(self, bot, chat_id):
-        message = await bot.send_location(
-            chat_id=chat_id,
-            latitude=52.223880,
-            longitude=5.166146,
-            live_period=80,
-            horizontal_accuracy=50,
-            heading=90,
-            proximity_alert_radius=1000,
-            protect_content=True,
-        )
-        assert message.location
-        assert 52.223880 == pytest.approx(message.location.latitude, rel=1e-5)
-        assert 5.166146 == pytest.approx(message.location.longitude, rel=1e-5)
-        assert message.location.live_period == 80
-        assert message.location.horizontal_accuracy == 50
-        assert message.location.heading == 90
-        assert message.location.proximity_alert_radius == 1000
-        assert message.has_protected_content
-
-        message2 = await bot.edit_message_live_location(
-            message.chat_id,
-            message.message_id,
-            latitude=52.223098,
-            longitude=5.164306,
-            horizontal_accuracy=30,
-            heading=10,
-            proximity_alert_radius=500,
-        )
-
-        assert 52.223098 == pytest.approx(message2.location.latitude, rel=1e-5)
-        assert 5.164306 == pytest.approx(message2.location.longitude, rel=1e-5)
-        assert message2.location.horizontal_accuracy == 30
-        assert message2.location.heading == 10
-        assert message2.location.proximity_alert_radius == 500
-
-        await bot.stop_message_live_location(message.chat_id, message.message_id)
-        with pytest.raises(BadRequest, match="Message can't be edited"):
-            await bot.edit_message_live_location(
-                message.chat_id, message.message_id, latitude=52.223880, longitude=5.164306
-            )
+        assert location.latitude == Space.latitude
+        assert location.longitude == Space.longitude
+        assert location.horizontal_accuracy == Space.horizontal_accuracy
+        assert location.live_period == Space.live_period
+        assert location.heading == Space.heading
+        assert location.proximity_alert_radius == Space.proximity_alert_radius
 
     # TODO: Needs improvement with in inline sent live location.
     async def test_edit_live_inline_message(self, monkeypatch, bot, location):
@@ -150,50 +110,6 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs):
         monkeypatch.setattr(bot.request, "post", make_assertion)
         assert await bot.send_location(location=location, chat_id=chat_id)
 
-    @pytest.mark.flaky(3, 1)
-    @pytest.mark.parametrize(
-        "default_bot,custom",
-        [
-            ({"allow_sending_without_reply": True}, None),
-            ({"allow_sending_without_reply": False}, None),
-            ({"allow_sending_without_reply": False}, True),
-        ],
-        indirect=["default_bot"],
-    )
-    async def test_send_location_default_allow_sending_without_reply(
-        self, default_bot, chat_id, location, custom
-    ):
-        reply_to_message = await default_bot.send_message(chat_id, "test")
-        await reply_to_message.delete()
-        if custom is not None:
-            message = await default_bot.send_location(
-                chat_id,
-                location=location,
-                allow_sending_without_reply=custom,
-                reply_to_message_id=reply_to_message.message_id,
-            )
-            assert message.reply_to_message is None
-        elif default_bot.defaults.allow_sending_without_reply:
-            message = await default_bot.send_location(
-                chat_id, location=location, reply_to_message_id=reply_to_message.message_id
-            )
-            assert message.reply_to_message is None
-        else:
-            with pytest.raises(BadRequest, match="message not found"):
-                await default_bot.send_location(
-                    chat_id, location=location, reply_to_message_id=reply_to_message.message_id
-                )
-
-    @pytest.mark.flaky(3, 1)
-    @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
-    async def test_send_location_default_protect_content(self, chat_id, default_bot, location):
-        protected = await default_bot.send_location(chat_id, location=location)
-        assert protected.has_protected_content
-        unprotected = await default_bot.send_location(
-            chat_id, location=location, protect_content=False
-        )
-        assert not unprotected.has_protected_content
-
     async def test_edit_live_location_with_location(self, monkeypatch, bot, location):
         async def make_assertion(url, request_data: RequestData, *args, **kwargs):
             lat = request_data.json_parameters["latitude"] == str(location.latitude)
@@ -232,9 +148,9 @@ def test_to_dict(self, location):
         assert location["proximity_alert_radius"] == location.proximity_alert_radius
 
     def test_equality(self):
-        a = Location(self.longitude, self.latitude)
-        b = Location(self.longitude, self.latitude)
-        d = Location(0, self.latitude)
+        a = Location(Space.longitude, Space.latitude)
+        b = Location(Space.longitude, Space.latitude)
+        d = Location(0, Space.latitude)
 
         assert a == b
         assert hash(a) == hash(b)
@@ -242,3 +158,91 @@ def test_equality(self):
 
         assert a != d
         assert hash(a) != hash(d)
+
+
+class TestLocationReq:
+    @pytest.mark.parametrize(
+        "default_bot,custom",
+        [
+            ({"allow_sending_without_reply": True}, None),
+            ({"allow_sending_without_reply": False}, None),
+            ({"allow_sending_without_reply": False}, True),
+        ],
+        indirect=["default_bot"],
+    )
+    async def test_send_location_default_allow_sending_without_reply(
+        self, default_bot, chat_id, location, custom
+    ):
+        reply_to_message = await default_bot.send_message(chat_id, "test")
+        await reply_to_message.delete()
+        if custom is not None:
+            message = await default_bot.send_location(
+                chat_id,
+                location=location,
+                allow_sending_without_reply=custom,
+                reply_to_message_id=reply_to_message.message_id,
+            )
+            assert message.reply_to_message is None
+        elif default_bot.defaults.allow_sending_without_reply:
+            message = await default_bot.send_location(
+                chat_id, location=location, reply_to_message_id=reply_to_message.message_id
+            )
+            assert message.reply_to_message is None
+        else:
+            with pytest.raises(BadRequest, match="message not found"):
+                await default_bot.send_location(
+                    chat_id, location=location, reply_to_message_id=reply_to_message.message_id
+                )
+
+    @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
+    async def test_send_location_default_protect_content(self, chat_id, default_bot, location):
+        tasks = asyncio.gather(
+            default_bot.send_location(chat_id, location=location),
+            default_bot.send_location(chat_id, location=location, protect_content=False),
+        )
+        protected, unprotected = await tasks
+        assert protected.has_protected_content
+        assert not unprotected.has_protected_content
+
+    @pytest.mark.xfail
+    async def test_send_live_location(self, bot, chat_id):
+        message = await bot.send_location(
+            chat_id=chat_id,
+            latitude=52.223880,
+            longitude=5.166146,
+            live_period=80,
+            horizontal_accuracy=50,
+            heading=90,
+            proximity_alert_radius=1000,
+            protect_content=True,
+        )
+        assert message.location
+        assert 52.223880 == pytest.approx(message.location.latitude, rel=1e-5)
+        assert 5.166146 == pytest.approx(message.location.longitude, rel=1e-5)
+        assert message.location.live_period == 80
+        assert message.location.horizontal_accuracy == 50
+        assert message.location.heading == 90
+        assert message.location.proximity_alert_radius == 1000
+        assert message.has_protected_content
+
+        message2 = await bot.edit_message_live_location(
+            message.chat_id,
+            message.message_id,
+            latitude=52.223098,
+            longitude=5.164306,
+            horizontal_accuracy=30,
+            heading=10,
+            proximity_alert_radius=500,
+        )
+
+        assert 52.223098 == pytest.approx(message2.location.latitude, rel=1e-5)
+        assert 5.164306 == pytest.approx(message2.location.longitude, rel=1e-5)
+        assert message2.location.horizontal_accuracy == 30
+        assert message2.location.heading == 10
+        assert message2.location.proximity_alert_radius == 500
+
+        await bot.stop_message_live_location(message.chat_id, message.message_id)
+        with pytest.raises(BadRequest, match="Message can't be edited"):
+            await bot.edit_message_live_location(
+                message.chat_id, message.message_id, latitude=52.223880, longitude=5.164306
+            )
diff --git a/tests/test_loginurl.py b/tests/test_loginurl.py
index 42550900025..4c796d9f949 100644
--- a/tests/test_loginurl.py
+++ b/tests/test_loginurl.py
@@ -21,22 +21,24 @@
 from telegram import LoginUrl
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def login_url():
     return LoginUrl(
-        url=TestLoginUrl.url,
-        forward_text=TestLoginUrl.forward_text,
-        bot_username=TestLoginUrl.bot_username,
-        request_write_access=TestLoginUrl.request_write_access,
+        url=Space.url,
+        forward_text=Space.forward_text,
+        bot_username=Space.bot_username,
+        request_write_access=Space.request_write_access,
     )
 
 
-class TestLoginUrl:
+class Space:
     url = "http://www.google.com"
     forward_text = "Send me forward!"
     bot_username = "botname"
     request_write_access = True
 
+
+class TestLoginUrlNoReq:
     def test_slot_behaviour(self, login_url, mro_slots):
         for attr in login_url.__slots__:
             assert getattr(login_url, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -46,16 +48,18 @@ def test_to_dict(self, login_url):
         login_url_dict = login_url.to_dict()
 
         assert isinstance(login_url_dict, dict)
-        assert login_url_dict["url"] == self.url
-        assert login_url_dict["forward_text"] == self.forward_text
-        assert login_url_dict["bot_username"] == self.bot_username
-        assert login_url_dict["request_write_access"] == self.request_write_access
+        assert login_url_dict["url"] == Space.url
+        assert login_url_dict["forward_text"] == Space.forward_text
+        assert login_url_dict["bot_username"] == Space.bot_username
+        assert login_url_dict["request_write_access"] == Space.request_write_access
 
     def test_equality(self):
-        a = LoginUrl(self.url, self.forward_text, self.bot_username, self.request_write_access)
-        b = LoginUrl(self.url, self.forward_text, self.bot_username, self.request_write_access)
-        c = LoginUrl(self.url)
-        d = LoginUrl("text.com", self.forward_text, self.bot_username, self.request_write_access)
+        a = LoginUrl(Space.url, Space.forward_text, Space.bot_username, Space.request_write_access)
+        b = LoginUrl(Space.url, Space.forward_text, Space.bot_username, Space.request_write_access)
+        c = LoginUrl(Space.url)
+        d = LoginUrl(
+            "text.com", Space.forward_text, Space.bot_username, Space.request_write_access
+        )
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_menubutton.py b/tests/test_menubutton.py
index ec95ed325b1..8b0fb037aa2 100644
--- a/tests/test_menubutton.py
+++ b/tests/test_menubutton.py
@@ -31,7 +31,7 @@
 
 
 @pytest.fixture(
-    scope="class",
+    scope="module",
     params=[
         MenuButton.DEFAULT,
         MenuButton.WEB_APP,
@@ -43,7 +43,7 @@ def scope_type(request):
 
 
 @pytest.fixture(
-    scope="class",
+    scope="module",
     params=[
         MenuButtonDefault,
         MenuButtonCommands,
@@ -60,7 +60,7 @@ def scope_class(request):
 
 
 @pytest.fixture(
-    scope="class",
+    scope="module",
     params=[
         (MenuButtonDefault, MenuButton.DEFAULT),
         (MenuButtonCommands, MenuButton.COMMANDS),
@@ -76,24 +76,26 @@ def scope_class_and_type(request):
     return request.param
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def menu_button(scope_class_and_type):
     # We use de_json here so that we don't have to worry about which class gets which arguments
     return scope_class_and_type[0].de_json(
         dict(
             type=scope_class_and_type[1],
-            text=TestMenuButton.text,
-            web_app=TestMenuButton.web_app.to_dict(),
+            text=Space.text,
+            web_app=Space.web_app.to_dict(),
         ),
         bot=None,
     )
 
 
-# All the scope types are very similar, so we test everything via parametrization
-class TestMenuButton:
+class Space:
     text = "button_text"
     web_app = WebAppInfo(url="https://python-telegram-bot.org/web_app")
 
+
+# All the scope types are very similar, so we test everything via parametrization
+class TestMenuButtonNoReq:
     def test_slot_behaviour(self, menu_button, mro_slots):
         for attr in menu_button.__slots__:
             assert getattr(menu_button, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -103,7 +105,7 @@ def test_de_json(self, bot, scope_class_and_type):
         cls = scope_class_and_type[0]
         type_ = scope_class_and_type[1]
 
-        json_dict = {"type": type_, "text": self.text, "web_app": self.web_app.to_dict()}
+        json_dict = {"type": type_, "text": Space.text, "web_app": Space.web_app.to_dict()}
         menu_button = MenuButton.de_json(json_dict, bot)
         assert set(menu_button.api_kwargs.keys()) == {"text", "web_app"} - set(cls.__slots__)
 
@@ -111,17 +113,17 @@ def test_de_json(self, bot, scope_class_and_type):
         assert type(menu_button) is cls
         assert menu_button.type == type_
         if "web_app" in cls.__slots__:
-            assert menu_button.web_app == self.web_app
+            assert menu_button.web_app == Space.web_app
         if "text" in cls.__slots__:
-            assert menu_button.text == self.text
+            assert menu_button.text == Space.text
 
         assert cls.de_json(None, bot) is None
         assert MenuButton.de_json({}, bot) is None
 
     def test_de_json_invalid_type(self, bot):
-        json_dict = {"type": "invalid", "text": self.text, "web_app": self.web_app.to_dict()}
+        json_dict = {"type": "invalid", "text": Space.text, "web_app": Space.web_app.to_dict()}
         menu_button = MenuButton.de_json(json_dict, bot)
-        assert menu_button.api_kwargs == {"text": self.text, "web_app": self.web_app.to_dict()}
+        assert menu_button.api_kwargs == {"text": Space.text, "web_app": Space.web_app.to_dict()}
 
         assert type(menu_button) is MenuButton
         assert menu_button.type == "invalid"
@@ -129,7 +131,7 @@ def test_de_json_invalid_type(self, bot):
     def test_de_json_subclass(self, scope_class, bot):
         """This makes sure that e.g. MenuButtonDefault(data) never returns a
         MenuButtonChat instance."""
-        json_dict = {"type": "invalid", "text": self.text, "web_app": self.web_app.to_dict()}
+        json_dict = {"type": "invalid", "text": Space.text, "web_app": Space.web_app.to_dict()}
         assert type(scope_class.de_json(json_dict, bot)) is scope_class
 
     def test_to_dict(self, menu_button):
diff --git a/tests/test_message.py b/tests/test_message.py
index 7891d1e43ea..fd474ea1bde 100644
--- a/tests/test_message.py
+++ b/tests/test_message.py
@@ -64,13 +64,13 @@
 from tests.test_passport import RAW_PASSPORT_DATA
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def message(bot):
     message = Message(
-        message_id=TestMessage.id_,
-        date=TestMessage.date,
-        chat=copy(TestMessage.chat),
-        from_user=copy(TestMessage.from_user),
+        message_id=Space.id_,
+        date=Space.date,
+        chat=copy(Space.chat),
+        from_user=copy(Space.from_user),
     )
     message.set_bot(bot)
     message._unfreeze()
@@ -265,17 +265,17 @@ def message(bot):
 )
 def message_params(bot, request):
     message = Message(
-        message_id=TestMessage.id_,
-        from_user=TestMessage.from_user,
-        date=TestMessage.date,
-        chat=TestMessage.chat,
+        message_id=Space.id_,
+        from_user=Space.from_user,
+        date=Space.date,
+        chat=Space.chat,
         **request.param,
     )
     message.set_bot(bot)
     return message
 
 
-class TestMessage:
+class Space:
     id_ = 1
     from_user = User(2, "testuser", False)
     date = datetime.utcnow()
@@ -341,6 +341,8 @@ class TestMessage:
         caption_entities=[MessageEntity(**e) for e in test_entities_v2],
     )
 
+
+class TestMessageNoReq:
     def test_all_possibilities_de_json_and_to_dict(self, bot, message_params):
         new = Message.de_json(message_params.to_dict(), bot)
         assert new.api_kwargs == {}
@@ -365,16 +367,16 @@ async def test_parse_entity(self):
         entity = MessageEntity(type=MessageEntity.URL, offset=13, length=17)
         message = Message(
             1,
-            from_user=self.from_user,
-            date=self.date,
-            chat=self.chat,
+            from_user=Space.from_user,
+            date=Space.date,
+            chat=Space.chat,
             text=text,
             entities=[entity],
         )
         assert message.parse_entity(entity) == "http://google.com"
 
         with pytest.raises(RuntimeError, match="Message has no"):
-            Message(message_id=1, date=self.date, chat=self.chat).parse_entity(entity)
+            Message(message_id=1, date=Space.date, chat=Space.chat).parse_entity(entity)
 
     async def test_parse_caption_entity(self):
         caption = (
@@ -384,16 +386,16 @@ async def test_parse_caption_entity(self):
         entity = MessageEntity(type=MessageEntity.URL, offset=13, length=17)
         message = Message(
             1,
-            from_user=self.from_user,
-            date=self.date,
-            chat=self.chat,
+            from_user=Space.from_user,
+            date=Space.date,
+            chat=Space.chat,
             caption=caption,
             caption_entities=[entity],
         )
         assert message.parse_caption_entity(entity) == "http://google.com"
 
         with pytest.raises(RuntimeError, match="Message has no"):
-            Message(message_id=1, date=self.date, chat=self.chat).parse_entity(entity)
+            Message(message_id=1, date=Space.date, chat=Space.chat).parse_entity(entity)
 
     async def test_parse_entities(self):
         text = (
@@ -404,9 +406,9 @@ async def test_parse_entities(self):
         entity_2 = MessageEntity(type=MessageEntity.BOLD, offset=13, length=1)
         message = Message(
             1,
-            from_user=self.from_user,
-            date=self.date,
-            chat=self.chat,
+            from_user=Space.from_user,
+            date=Space.date,
+            chat=Space.chat,
             text=text,
             entities=[entity_2, entity],
         )
@@ -422,9 +424,9 @@ async def test_parse_caption_entities(self):
         entity_2 = MessageEntity(type=MessageEntity.BOLD, offset=13, length=1)
         message = Message(
             1,
-            from_user=self.from_user,
-            date=self.date,
-            chat=self.chat,
+            from_user=Space.from_user,
+            date=Space.date,
+            chat=Space.chat,
             caption=text,
             caption_entities=[entity_2, entity],
         )
@@ -445,7 +447,7 @@ def test_text_html_simple(self):
             '<pre><code class="python">Python pre</code></pre>. '
             '<span class="tg-spoiler">Spoiled</span>.'
         )
-        text_html = self.test_message_v2.text_html
+        text_html = Space.test_message_v2.text_html
         assert text_html == test_html_string
 
     def test_text_html_empty(self, message):
@@ -464,7 +466,7 @@ def test_text_html_urled(self):
             '<pre><code class="python">Python pre</code></pre>. '
             '<span class="tg-spoiler">Spoiled</span>.'
         )
-        text_html = self.test_message_v2.text_html_urled
+        text_html = Space.test_message_v2.text_html_urled
         assert text_html == test_html_string
 
     def test_text_markdown_simple(self):
@@ -474,7 +476,7 @@ def test_text_markdown_simple(self):
             "[text-mention](tg://user?id=123456789) and ```python\npre```. "
             r"http://google.com/ab\_"
         )
-        text_markdown = self.test_message.text_markdown
+        text_markdown = Space.test_message.text_markdown
         assert text_markdown == test_md_string
 
     def test_text_markdown_v2_simple(self):
@@ -485,7 +487,7 @@ def test_text_markdown_v2_simple(self):
             r"http://google\.com and _bold *nested in ~strk\>trgh~ nested in* italic_\. "
             "```python\nPython pre```\\. ||Spoiled||\\."
         )
-        text_markdown = self.test_message_v2.text_markdown_v2
+        text_markdown = Space.test_message_v2.text_markdown_v2
         assert text_markdown == test_md_string
 
     def test_text_markdown_new_in_v2(self, message):
@@ -524,7 +526,7 @@ def test_text_markdown_urled(self):
             "[text-mention](tg://user?id=123456789) and ```python\npre```. "
             "[http://google.com/ab_](http://google.com/ab_)"
         )
-        text_markdown = self.test_message.text_markdown_urled
+        text_markdown = Space.test_message.text_markdown_urled
         assert text_markdown == test_md_string
 
     def test_text_markdown_v2_urled(self):
@@ -535,7 +537,7 @@ def test_text_markdown_v2_urled(self):
             r"[http://google\.com](http://google.com) and _bold *nested in ~strk\>trgh~ "
             "nested in* italic_\\. ```python\nPython pre```\\. ||Spoiled||\\."
         )
-        text_markdown = self.test_message_v2.text_markdown_v2_urled
+        text_markdown = Space.test_message_v2.text_markdown_v2_urled
         assert text_markdown == test_md_string
 
     def test_text_html_emoji(self):
@@ -544,9 +546,9 @@ def test_text_html_emoji(self):
         bold_entity = MessageEntity(type=MessageEntity.BOLD, offset=7, length=3)
         message = Message(
             1,
-            from_user=self.from_user,
-            date=self.date,
-            chat=self.chat,
+            from_user=Space.from_user,
+            date=Space.date,
+            chat=Space.chat,
             text=text,
             entities=[bold_entity],
         )
@@ -557,7 +559,7 @@ def test_text_markdown_emoji(self):
         expected = b"\\U0001f469\\u200d\\U0001f469\\u200d *ABC*".decode("unicode-escape")
         bold_entity = MessageEntity(type=MessageEntity.BOLD, offset=7, length=3)
         message = Message(
-            1, self.from_user, self.date, self.chat, text=text, entities=[bold_entity]
+            1, Space.from_user, Space.date, Space.chat, text=text, entities=[bold_entity]
         )
         assert expected == message.text_markdown
 
@@ -583,9 +585,9 @@ def test_text_custom_emoji(self, type_):
         )
         message = Message(
             1,
-            from_user=self.from_user,
-            date=self.date,
-            chat=self.chat,
+            from_user=Space.from_user,
+            date=Space.date,
+            chat=Space.chat,
             text=text,
             entities=[emoji_entity],
         )
@@ -602,7 +604,7 @@ def test_caption_html_simple(self):
             '<pre><code class="python">Python pre</code></pre>. '
             '<span class="tg-spoiler">Spoiled</span>.'
         )
-        caption_html = self.test_message_v2.caption_html
+        caption_html = Space.test_message_v2.caption_html
         assert caption_html == test_html_string
 
     def test_caption_html_empty(self, message):
@@ -621,7 +623,7 @@ def test_caption_html_urled(self):
             '<pre><code class="python">Python pre</code></pre>. '
             '<span class="tg-spoiler">Spoiled</span>.'
         )
-        caption_html = self.test_message_v2.caption_html_urled
+        caption_html = Space.test_message_v2.caption_html_urled
         assert caption_html == test_html_string
 
     def test_caption_markdown_simple(self):
@@ -631,7 +633,7 @@ def test_caption_markdown_simple(self):
             "[text-mention](tg://user?id=123456789) and ```python\npre```. "
             r"http://google.com/ab\_"
         )
-        caption_markdown = self.test_message.caption_markdown
+        caption_markdown = Space.test_message.caption_markdown
         assert caption_markdown == test_md_string
 
     def test_caption_markdown_v2_simple(self):
@@ -642,7 +644,7 @@ def test_caption_markdown_v2_simple(self):
             r"http://google\.com and _bold *nested in ~strk\>trgh~ nested in* italic_\. "
             "```python\nPython pre```\\. ||Spoiled||\\."
         )
-        caption_markdown = self.test_message_v2.caption_markdown_v2
+        caption_markdown = Space.test_message_v2.caption_markdown_v2
         assert caption_markdown == test_md_string
 
     def test_caption_markdown_empty(self, message):
@@ -658,7 +660,7 @@ def test_caption_markdown_urled(self):
             "[text-mention](tg://user?id=123456789) and ```python\npre```. "
             "[http://google.com/ab_](http://google.com/ab_)"
         )
-        caption_markdown = self.test_message.caption_markdown_urled
+        caption_markdown = Space.test_message.caption_markdown_urled
         assert caption_markdown == test_md_string
 
     def test_caption_markdown_v2_urled(self):
@@ -669,7 +671,7 @@ def test_caption_markdown_v2_urled(self):
             r"[http://google\.com](http://google.com) and _bold *nested in ~strk\>trgh~ "
             "nested in* italic_\\. ```python\nPython pre```\\. ||Spoiled||\\."
         )
-        caption_markdown = self.test_message_v2.caption_markdown_v2_urled
+        caption_markdown = Space.test_message_v2.caption_markdown_v2_urled
         assert caption_markdown == test_md_string
 
     def test_caption_html_emoji(self):
@@ -678,9 +680,9 @@ def test_caption_html_emoji(self):
         bold_entity = MessageEntity(type=MessageEntity.BOLD, offset=7, length=3)
         message = Message(
             1,
-            from_user=self.from_user,
-            date=self.date,
-            chat=self.chat,
+            from_user=Space.from_user,
+            date=Space.date,
+            chat=Space.chat,
             caption=caption,
             caption_entities=[bold_entity],
         )
@@ -692,9 +694,9 @@ def test_caption_markdown_emoji(self):
         bold_entity = MessageEntity(type=MessageEntity.BOLD, offset=7, length=3)
         message = Message(
             1,
-            from_user=self.from_user,
-            date=self.date,
-            chat=self.chat,
+            from_user=Space.from_user,
+            date=Space.date,
+            chat=Space.chat,
             caption=caption,
             caption_entities=[bold_entity],
         )
@@ -722,9 +724,9 @@ def test_caption_custom_emoji(self, type_):
         )
         message = Message(
             1,
-            from_user=self.from_user,
-            date=self.date,
-            chat=self.chat,
+            from_user=Space.from_user,
+            date=Space.date,
+            chat=Space.chat,
             caption=caption,
             caption_entities=[emoji_entity],
         )
@@ -735,7 +737,7 @@ async def test_parse_entities_url_emoji(self):
         text = "some url"
         link_entity = MessageEntity(type=MessageEntity.URL, offset=0, length=8, url=url)
         message = Message(
-            1, self.from_user, self.date, self.chat, text=text, entities=[link_entity]
+            1, Space.from_user, Space.date, Space.chat, text=text, entities=[link_entity]
         )
         assert message.parse_entities() == {link_entity: text}
         assert next(iter(message.parse_entities())).url == url
@@ -855,14 +857,14 @@ async def make_assertion(*_, **kwargs):
         assert await check_shortcut_call(message.reply_text, message.get_bot(), "send_message")
         assert await check_defaults_handling(message.reply_text, message.get_bot())
 
-        text_markdown = self.test_message.text_markdown
+        text_markdown = Space.test_message.text_markdown
         assert text_markdown == test_md_string
 
         monkeypatch.setattr(message.get_bot(), "send_message", make_assertion)
-        assert await message.reply_markdown(self.test_message.text_markdown)
-        assert await message.reply_markdown(self.test_message.text_markdown, quote=True)
+        assert await message.reply_markdown(Space.test_message.text_markdown)
+        assert await message.reply_markdown(Space.test_message.text_markdown, quote=True)
         assert await message.reply_markdown(
-            self.test_message.text_markdown, reply_to_message_id=message.message_id, quote=True
+            Space.test_message.text_markdown, reply_to_message_id=message.message_id, quote=True
         )
 
     async def test_reply_markdown_v2(self, monkeypatch, message):
@@ -890,14 +892,14 @@ async def make_assertion(*_, **kwargs):
         assert await check_shortcut_call(message.reply_text, message.get_bot(), "send_message")
         assert await check_defaults_handling(message.reply_text, message.get_bot())
 
-        text_markdown = self.test_message_v2.text_markdown_v2
+        text_markdown = Space.test_message_v2.text_markdown_v2
         assert text_markdown == test_md_string
 
         monkeypatch.setattr(message.get_bot(), "send_message", make_assertion)
-        assert await message.reply_markdown_v2(self.test_message_v2.text_markdown_v2)
-        assert await message.reply_markdown_v2(self.test_message_v2.text_markdown_v2, quote=True)
+        assert await message.reply_markdown_v2(Space.test_message_v2.text_markdown_v2)
+        assert await message.reply_markdown_v2(Space.test_message_v2.text_markdown_v2, quote=True)
         assert await message.reply_markdown_v2(
-            self.test_message_v2.text_markdown_v2,
+            Space.test_message_v2.text_markdown_v2,
             reply_to_message_id=message.message_id,
             quote=True,
         )
@@ -930,14 +932,14 @@ async def make_assertion(*_, **kwargs):
         assert await check_shortcut_call(message.reply_text, message.get_bot(), "send_message")
         assert await check_defaults_handling(message.reply_text, message.get_bot())
 
-        text_html = self.test_message_v2.text_html
+        text_html = Space.test_message_v2.text_html
         assert text_html == test_html_string
 
         monkeypatch.setattr(message.get_bot(), "send_message", make_assertion)
-        assert await message.reply_html(self.test_message_v2.text_html)
-        assert await message.reply_html(self.test_message_v2.text_html, quote=True)
+        assert await message.reply_html(Space.test_message_v2.text_html)
+        assert await message.reply_html(Space.test_message_v2.text_html, quote=True)
         assert await message.reply_html(
-            self.test_message_v2.text_html, reply_to_message_id=message.message_id, quote=True
+            Space.test_message_v2.text_html, reply_to_message_id=message.message_id, quote=True
         )
 
     async def test_reply_media_group(self, monkeypatch, message):
@@ -1825,18 +1827,18 @@ def test_equality(self):
         id_ = 1
         a = Message(
             id_,
-            self.date,
-            self.chat,
-            from_user=self.from_user,
+            Space.date,
+            Space.chat,
+            from_user=Space.from_user,
         )
         b = Message(
             id_,
-            self.date,
-            self.chat,
-            from_user=self.from_user,
+            Space.date,
+            Space.chat,
+            from_user=Space.from_user,
         )
-        c = Message(id_, self.date, Chat(123, Chat.GROUP), from_user=User(0, "", False))
-        d = Message(0, self.date, self.chat, from_user=self.from_user)
+        c = Message(id_, Space.date, Chat(123, Chat.GROUP), from_user=User(0, "", False))
+        d = Message(0, Space.date, Space.chat, from_user=Space.from_user)
         e = Update(id_)
 
         assert a == b
diff --git a/tests/test_messageautodeletetimerchanged.py b/tests/test_messageautodeletetimerchanged.py
index ee8e6c4c06b..5d2eaa05190 100644
--- a/tests/test_messageautodeletetimerchanged.py
+++ b/tests/test_messageautodeletetimerchanged.py
@@ -19,7 +19,7 @@
 from telegram import MessageAutoDeleteTimerChanged, VideoChatEnded
 
 
-class TestMessageAutoDeleteTimerChanged:
+class TestMessageAutoDeleteTimerChangedNoReq:
     message_auto_delete_time = 100
 
     def test_slot_behaviour(self, mro_slots):
diff --git a/tests/test_messageentity.py b/tests/test_messageentity.py
index 116d5263788..ce178c59463 100644
--- a/tests/test_messageentity.py
+++ b/tests/test_messageentity.py
@@ -22,7 +22,7 @@
 from telegram.constants import MessageEntityType
 
 
-@pytest.fixture(scope="class", params=MessageEntity.ALL_TYPES)
+@pytest.fixture(scope="module", params=MessageEntity.ALL_TYPES)
 def message_entity(request):
     type_ = request.param
     url = None
@@ -37,12 +37,14 @@ def message_entity(request):
     return MessageEntity(type_, 1, 3, url=url, user=user, language=language)
 
 
-class TestMessageEntity:
+class Space:
     type_ = "url"
     offset = 1
     length = 2
     url = "url"
 
+
+class TestMessageEntityNoReq:
     def test_slot_behaviour(self, message_entity, mro_slots):
         inst = message_entity
         for attr in inst.__slots__:
@@ -50,13 +52,13 @@ def test_slot_behaviour(self, message_entity, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_de_json(self, bot):
-        json_dict = {"type": self.type_, "offset": self.offset, "length": self.length}
+        json_dict = {"type": Space.type_, "offset": Space.offset, "length": Space.length}
         entity = MessageEntity.de_json(json_dict, bot)
         assert entity.api_kwargs == {}
 
-        assert entity.type == self.type_
-        assert entity.offset == self.offset
-        assert entity.length == self.length
+        assert entity.type == Space.type_
+        assert entity.offset == Space.offset
+        assert entity.length == Space.length
 
     def test_to_dict(self, message_entity):
         entity_dict = message_entity.to_dict()
diff --git a/tests/test_messageid.py b/tests/test_messageid.py
index 3ae10efe9eb..90c3a8e782f 100644
--- a/tests/test_messageid.py
+++ b/tests/test_messageid.py
@@ -20,12 +20,12 @@
 from telegram import MessageId, User
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def message_id():
-    return MessageId(message_id=TestMessageId.m_id)
+    return MessageId(message_id=TestMessageIdNoReq.m_id)
 
 
-class TestMessageId:
+class TestMessageIdNoReq:
     m_id = 1234
 
     def test_slot_behaviour(self, message_id, mro_slots):
diff --git a/tests/test_no_passport.py b/tests/test_no_passport.py
index 071e29c5306..ee4999988aa 100644
--- a/tests/test_no_passport.py
+++ b/tests/test_no_passport.py
@@ -26,21 +26,17 @@
 
 with the TEST_WITH_OPT_DEPS environment variable set to False in addition to the regular test suite
 """
-import os
-
 import pytest
 
 from telegram import _bot as bot
 from telegram._passport import credentials as credentials
-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))
+from tests.conftest import TEST_WITH_OPT_DEPS
 
 
 @pytest.mark.skipif(
     TEST_WITH_OPT_DEPS, reason="Only relevant if the optional dependency is not installed"
 )
-class TestNoPassport:
+class TestNoPassportNoReq:
     def test_bot_init(self, bot_info, monkeypatch):
         with pytest.raises(RuntimeError, match="passport"):
             bot.Bot(bot_info["token"], private_key=1, private_key_password=2)
diff --git a/tests/test_orderinfo.py b/tests/test_orderinfo.py
index ab402d468e5..a569b4e1884 100644
--- a/tests/test_orderinfo.py
+++ b/tests/test_orderinfo.py
@@ -21,22 +21,24 @@
 from telegram import OrderInfo, ShippingAddress
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def order_info():
     return OrderInfo(
-        TestOrderInfo.name,
-        TestOrderInfo.phone_number,
-        TestOrderInfo.email,
-        TestOrderInfo.shipping_address,
+        Space.name,
+        Space.phone_number,
+        Space.email,
+        Space.shipping_address,
     )
 
 
-class TestOrderInfo:
+class Space:
     name = "name"
     phone_number = "phone_number"
     email = "email"
     shipping_address = ShippingAddress("GB", "", "London", "12 Grimmauld Place", "", "WC1")
 
+
+class TestOrderInfoNoReq:
     def test_slot_behaviour(self, order_info, mro_slots):
         for attr in order_info.__slots__:
             assert getattr(order_info, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -44,18 +46,18 @@ def test_slot_behaviour(self, order_info, mro_slots):
 
     def test_de_json(self, bot):
         json_dict = {
-            "name": TestOrderInfo.name,
-            "phone_number": TestOrderInfo.phone_number,
-            "email": TestOrderInfo.email,
-            "shipping_address": TestOrderInfo.shipping_address.to_dict(),
+            "name": Space.name,
+            "phone_number": Space.phone_number,
+            "email": Space.email,
+            "shipping_address": Space.shipping_address.to_dict(),
         }
         order_info = OrderInfo.de_json(json_dict, bot)
         assert order_info.api_kwargs == {}
 
-        assert order_info.name == self.name
-        assert order_info.phone_number == self.phone_number
-        assert order_info.email == self.email
-        assert order_info.shipping_address == self.shipping_address
+        assert order_info.name == Space.name
+        assert order_info.phone_number == Space.phone_number
+        assert order_info.email == Space.email
+        assert order_info.shipping_address == Space.shipping_address
 
     def test_to_dict(self, order_info):
         order_info_dict = order_info.to_dict()
diff --git a/tests/test_passport.py b/tests/test_passport.py
index 77f9a0c91ea..0d229e3aaba 100644
--- a/tests/test_passport.py
+++ b/tests/test_passport.py
@@ -128,7 +128,7 @@
 }
 
 
-@pytest.fixture(scope="function")
+@pytest.fixture(scope="module")
 def all_passport_data():
     return [
         {
@@ -214,12 +214,12 @@ def all_passport_data():
     ]
 
 
-@pytest.fixture(scope="function")
+@pytest.fixture(scope="module")
 def passport_data(bot):
     return PassportData.de_json(RAW_PASSPORT_DATA, bot=bot)
 
 
-class TestPassport:
+class Space:
     driver_license_selfie_file_id = "DgADBAADEQQAAkopgFNr6oi-wISRtAI"
     driver_license_selfie_file_unique_id = "d4e390cca57b4da5a65322b304762a12"
     driver_license_front_side_file_id = "DgADBAADxwMAApnQgVPK2-ckL2eXVAI"
@@ -241,6 +241,8 @@ class TestPassport:
     driver_license_selfie_credentials_file_hash = "Cila/qLXSBH7DpZFbb5bRZIRxeFW2uv/ulL0u0JNsYI="
     driver_license_selfie_credentials_secret = "tivdId6RNYNsvXYPppdzrbxOBuBOr9wXRPDcCvnXU7E="
 
+
+class TestPassportNoReq:
     def test_slot_behaviour(self, passport_data, mro_slots):
         inst = passport_data
         for attr in inst.__slots__:
@@ -259,58 +261,58 @@ def test_expected_encrypted_values(self, passport_data):
         assert driver_license.type == "driver_license"
         assert driver_license.data == RAW_PASSPORT_DATA["data"][1]["data"]
         assert isinstance(driver_license.selfie, PassportFile)
-        assert driver_license.selfie.file_id == self.driver_license_selfie_file_id
-        assert driver_license.selfie.file_unique_id == self.driver_license_selfie_file_unique_id
+        assert driver_license.selfie.file_id == Space.driver_license_selfie_file_id
+        assert driver_license.selfie.file_unique_id == Space.driver_license_selfie_file_unique_id
 
         assert isinstance(driver_license.front_side, PassportFile)
-        assert driver_license.front_side.file_id == self.driver_license_front_side_file_id
+        assert driver_license.front_side.file_id == Space.driver_license_front_side_file_id
         assert (
             driver_license.front_side.file_unique_id
-            == self.driver_license_front_side_file_unique_id
+            == Space.driver_license_front_side_file_unique_id
         )
 
         assert isinstance(driver_license.reverse_side, PassportFile)
-        assert driver_license.reverse_side.file_id == self.driver_license_reverse_side_file_id
+        assert driver_license.reverse_side.file_id == Space.driver_license_reverse_side_file_id
         assert (
             driver_license.reverse_side.file_unique_id
-            == self.driver_license_reverse_side_file_unique_id
+            == Space.driver_license_reverse_side_file_unique_id
         )
 
         assert isinstance(driver_license.translation[0], PassportFile)
-        assert driver_license.translation[0].file_id == self.driver_license_translation_1_file_id
+        assert driver_license.translation[0].file_id == Space.driver_license_translation_1_file_id
         assert (
             driver_license.translation[0].file_unique_id
-            == self.driver_license_translation_1_file_unique_id
+            == Space.driver_license_translation_1_file_unique_id
         )
 
         assert isinstance(driver_license.translation[1], PassportFile)
-        assert driver_license.translation[1].file_id == self.driver_license_translation_2_file_id
+        assert driver_license.translation[1].file_id == Space.driver_license_translation_2_file_id
         assert (
             driver_license.translation[1].file_unique_id
-            == self.driver_license_translation_2_file_unique_id
+            == Space.driver_license_translation_2_file_unique_id
         )
 
         assert utility_bill.type == "utility_bill"
         assert isinstance(utility_bill.files[0], PassportFile)
-        assert utility_bill.files[0].file_id == self.utility_bill_1_file_id
-        assert utility_bill.files[0].file_unique_id == self.utility_bill_1_file_unique_id
+        assert utility_bill.files[0].file_id == Space.utility_bill_1_file_id
+        assert utility_bill.files[0].file_unique_id == Space.utility_bill_1_file_unique_id
 
         assert isinstance(utility_bill.files[1], PassportFile)
-        assert utility_bill.files[1].file_id == self.utility_bill_2_file_id
-        assert utility_bill.files[1].file_unique_id == self.utility_bill_2_file_unique_id
+        assert utility_bill.files[1].file_id == Space.utility_bill_2_file_id
+        assert utility_bill.files[1].file_unique_id == Space.utility_bill_2_file_unique_id
 
         assert isinstance(utility_bill.translation[0], PassportFile)
-        assert utility_bill.translation[0].file_id == self.utility_bill_translation_1_file_id
+        assert utility_bill.translation[0].file_id == Space.utility_bill_translation_1_file_id
         assert (
             utility_bill.translation[0].file_unique_id
-            == self.utility_bill_translation_1_file_unique_id
+            == Space.utility_bill_translation_1_file_unique_id
         )
 
         assert isinstance(utility_bill.translation[1], PassportFile)
-        assert utility_bill.translation[1].file_id == self.utility_bill_translation_2_file_id
+        assert utility_bill.translation[1].file_id == Space.utility_bill_translation_2_file_id
         assert (
             utility_bill.translation[1].file_unique_id
-            == self.utility_bill_translation_2_file_unique_id
+            == Space.utility_bill_translation_2_file_unique_id
         )
 
         assert address.type == "address"
@@ -348,21 +350,21 @@ def test_expected_decrypted_values(self, passport_data):
             "document_no": "DOCUMENT_NO",
         }
         assert isinstance(driver_license.selfie, PassportFile)
-        assert driver_license.selfie.file_id == self.driver_license_selfie_file_id
-        assert driver_license.selfie.file_unique_id == self.driver_license_selfie_file_unique_id
+        assert driver_license.selfie.file_id == Space.driver_license_selfie_file_id
+        assert driver_license.selfie.file_unique_id == Space.driver_license_selfie_file_unique_id
 
         assert isinstance(driver_license.front_side, PassportFile)
-        assert driver_license.front_side.file_id == self.driver_license_front_side_file_id
+        assert driver_license.front_side.file_id == Space.driver_license_front_side_file_id
         assert (
             driver_license.front_side.file_unique_id
-            == self.driver_license_front_side_file_unique_id
+            == Space.driver_license_front_side_file_unique_id
         )
 
         assert isinstance(driver_license.reverse_side, PassportFile)
-        assert driver_license.reverse_side.file_id == self.driver_license_reverse_side_file_id
+        assert driver_license.reverse_side.file_id == Space.driver_license_reverse_side_file_id
         assert (
             driver_license.reverse_side.file_unique_id
-            == self.driver_license_reverse_side_file_unique_id
+            == Space.driver_license_reverse_side_file_unique_id
         )
 
         assert address.type == "address"
@@ -377,12 +379,12 @@ def test_expected_decrypted_values(self, passport_data):
 
         assert utility_bill.type == "utility_bill"
         assert isinstance(utility_bill.files[0], PassportFile)
-        assert utility_bill.files[0].file_id == self.utility_bill_1_file_id
-        assert utility_bill.files[0].file_unique_id == self.utility_bill_1_file_unique_id
+        assert utility_bill.files[0].file_id == Space.utility_bill_1_file_id
+        assert utility_bill.files[0].file_unique_id == Space.utility_bill_1_file_unique_id
 
         assert isinstance(utility_bill.files[1], PassportFile)
-        assert utility_bill.files[1].file_id == self.utility_bill_2_file_id
-        assert utility_bill.files[1].file_unique_id == self.utility_bill_2_file_unique_id
+        assert utility_bill.files[1].file_id == Space.utility_bill_2_file_id
+        assert utility_bill.files[1].file_unique_id == Space.utility_bill_2_file_unique_id
 
         assert email.type == "email"
         assert email.email == "fb3e3i47zt@dispostable.com"
@@ -468,8 +470,8 @@ async def get_file(*_, **kwargs):
         file = await selfie.get_file()
         assert file.file_id == selfie.file_id
         assert file.file_unique_id == selfie.file_unique_id
-        assert file._credentials.file_hash == self.driver_license_selfie_credentials_file_hash
-        assert file._credentials.secret == self.driver_license_selfie_credentials_secret
+        assert file._credentials.file_hash == Space.driver_license_selfie_credentials_file_hash
+        assert file._credentials.secret == Space.driver_license_selfie_credentials_secret
 
     async def test_mocked_set_passport_data_errors(self, monkeypatch, bot, chat_id, passport_data):
         async def make_assertion(url, request_data: RequestData, *args, **kwargs):
diff --git a/tests/test_passportelementerrordatafield.py b/tests/test_passportelementerrordatafield.py
index ca2d3b2186e..d76dd5ef134 100644
--- a/tests/test_passportelementerrordatafield.py
+++ b/tests/test_passportelementerrordatafield.py
@@ -21,23 +21,25 @@
 from telegram import PassportElementErrorDataField, PassportElementErrorSelfie
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def passport_element_error_data_field():
     return PassportElementErrorDataField(
-        TestPassportElementErrorDataField.type_,
-        TestPassportElementErrorDataField.field_name,
-        TestPassportElementErrorDataField.data_hash,
-        TestPassportElementErrorDataField.message,
+        Space.type_,
+        Space.field_name,
+        Space.data_hash,
+        Space.message,
     )
 
 
-class TestPassportElementErrorDataField:
+class Space:
     source = "data"
     type_ = "test_type"
     field_name = "test_field"
     data_hash = "data_hash"
     message = "Error message"
 
+
+class TestPassportElementErrorDataFieldNoReq:
     def test_slot_behaviour(self, passport_element_error_data_field, mro_slots):
         inst = passport_element_error_data_field
         for attr in inst.__slots__:
@@ -45,11 +47,11 @@ def test_slot_behaviour(self, passport_element_error_data_field, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, passport_element_error_data_field):
-        assert passport_element_error_data_field.source == self.source
-        assert passport_element_error_data_field.type == self.type_
-        assert passport_element_error_data_field.field_name == self.field_name
-        assert passport_element_error_data_field.data_hash == self.data_hash
-        assert passport_element_error_data_field.message == self.message
+        assert passport_element_error_data_field.source == Space.source
+        assert passport_element_error_data_field.type == Space.type_
+        assert passport_element_error_data_field.field_name == Space.field_name
+        assert passport_element_error_data_field.data_hash == Space.data_hash
+        assert passport_element_error_data_field.message == Space.message
 
     def test_to_dict(self, passport_element_error_data_field):
         passport_element_error_data_field_dict = passport_element_error_data_field.to_dict()
@@ -78,16 +80,16 @@ def test_to_dict(self, passport_element_error_data_field):
 
     def test_equality(self):
         a = PassportElementErrorDataField(
-            self.type_, self.field_name, self.data_hash, self.message
+            Space.type_, Space.field_name, Space.data_hash, Space.message
         )
         b = PassportElementErrorDataField(
-            self.type_, self.field_name, self.data_hash, self.message
+            Space.type_, Space.field_name, Space.data_hash, Space.message
         )
-        c = PassportElementErrorDataField(self.type_, "", "", "")
-        d = PassportElementErrorDataField("", self.field_name, "", "")
-        e = PassportElementErrorDataField("", "", self.data_hash, "")
-        f = PassportElementErrorDataField("", "", "", self.message)
-        g = PassportElementErrorSelfie(self.type_, "", self.message)
+        c = PassportElementErrorDataField(Space.type_, "", "", "")
+        d = PassportElementErrorDataField("", Space.field_name, "", "")
+        e = PassportElementErrorDataField("", "", Space.data_hash, "")
+        f = PassportElementErrorDataField("", "", "", Space.message)
+        g = PassportElementErrorSelfie(Space.type_, "", Space.message)
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_passportelementerrorfile.py b/tests/test_passportelementerrorfile.py
index c7fc752e979..7d6d887e277 100644
--- a/tests/test_passportelementerrorfile.py
+++ b/tests/test_passportelementerrorfile.py
@@ -21,21 +21,19 @@
 from telegram import PassportElementErrorFile, PassportElementErrorSelfie
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def passport_element_error_file():
-    return PassportElementErrorFile(
-        TestPassportElementErrorFile.type_,
-        TestPassportElementErrorFile.file_hash,
-        TestPassportElementErrorFile.message,
-    )
+    return PassportElementErrorFile(Space.type_, Space.file_hash, Space.message)
 
 
-class TestPassportElementErrorFile:
+class Space:
     source = "file"
     type_ = "test_type"
     file_hash = "file_hash"
     message = "Error message"
 
+
+class TestPassportElementErrorFileNoReq:
     def test_slot_behaviour(self, passport_element_error_file, mro_slots):
         inst = passport_element_error_file
         for attr in inst.__slots__:
@@ -43,10 +41,10 @@ def test_slot_behaviour(self, passport_element_error_file, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, passport_element_error_file):
-        assert passport_element_error_file.source == self.source
-        assert passport_element_error_file.type == self.type_
-        assert passport_element_error_file.file_hash == self.file_hash
-        assert passport_element_error_file.message == self.message
+        assert passport_element_error_file.source == Space.source
+        assert passport_element_error_file.type == Space.type_
+        assert passport_element_error_file.file_hash == Space.file_hash
+        assert passport_element_error_file.message == Space.message
 
     def test_to_dict(self, passport_element_error_file):
         passport_element_error_file_dict = passport_element_error_file.to_dict()
@@ -60,12 +58,12 @@ def test_to_dict(self, passport_element_error_file):
         assert passport_element_error_file_dict["message"] == passport_element_error_file.message
 
     def test_equality(self):
-        a = PassportElementErrorFile(self.type_, self.file_hash, self.message)
-        b = PassportElementErrorFile(self.type_, self.file_hash, self.message)
-        c = PassportElementErrorFile(self.type_, "", "")
-        d = PassportElementErrorFile("", self.file_hash, "")
-        e = PassportElementErrorFile("", "", self.message)
-        f = PassportElementErrorSelfie(self.type_, self.file_hash, self.message)
+        a = PassportElementErrorFile(Space.type_, Space.file_hash, Space.message)
+        b = PassportElementErrorFile(Space.type_, Space.file_hash, Space.message)
+        c = PassportElementErrorFile(Space.type_, "", "")
+        d = PassportElementErrorFile("", Space.file_hash, "")
+        e = PassportElementErrorFile("", "", Space.message)
+        f = PassportElementErrorSelfie(Space.type_, Space.file_hash, Space.message)
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_passportelementerrorfiles.py b/tests/test_passportelementerrorfiles.py
index ea7c6a9086f..74a9160c639 100644
--- a/tests/test_passportelementerrorfiles.py
+++ b/tests/test_passportelementerrorfiles.py
@@ -21,21 +21,19 @@
 from telegram import PassportElementErrorFiles, PassportElementErrorSelfie
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def passport_element_error_files():
-    return PassportElementErrorFiles(
-        TestPassportElementErrorFiles.type_,
-        TestPassportElementErrorFiles.file_hashes,
-        TestPassportElementErrorFiles.message,
-    )
+    return PassportElementErrorFiles(Space.type_, Space.file_hashes, Space.message)
 
 
-class TestPassportElementErrorFiles:
+class Space:
     source = "files"
     type_ = "test_type"
     file_hashes = ["hash1", "hash2"]
     message = "Error message"
 
+
+class TestPassportElementErrorFilesNoReq:
     def test_slot_behaviour(self, passport_element_error_files, mro_slots):
         inst = passport_element_error_files
         for attr in inst.__slots__:
@@ -43,11 +41,11 @@ def test_slot_behaviour(self, passport_element_error_files, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, passport_element_error_files):
-        assert passport_element_error_files.source == self.source
-        assert passport_element_error_files.type == self.type_
+        assert passport_element_error_files.source == Space.source
+        assert passport_element_error_files.type == Space.type_
         assert isinstance(passport_element_error_files.file_hashes, list)
-        assert passport_element_error_files.file_hashes == self.file_hashes
-        assert passport_element_error_files.message == self.message
+        assert passport_element_error_files.file_hashes == Space.file_hashes
+        assert passport_element_error_files.message == Space.message
 
     def test_to_dict(self, passport_element_error_files):
         passport_element_error_files_dict = passport_element_error_files.to_dict()
@@ -62,12 +60,12 @@ def test_to_dict(self, passport_element_error_files):
         assert passport_element_error_files_dict["message"] == passport_element_error_files.message
 
     def test_equality(self):
-        a = PassportElementErrorFiles(self.type_, self.file_hashes, self.message)
-        b = PassportElementErrorFiles(self.type_, self.file_hashes, self.message)
-        c = PassportElementErrorFiles(self.type_, "", "")
-        d = PassportElementErrorFiles("", self.file_hashes, "")
-        e = PassportElementErrorFiles("", "", self.message)
-        f = PassportElementErrorSelfie(self.type_, "", self.message)
+        a = PassportElementErrorFiles(Space.type_, Space.file_hashes, Space.message)
+        b = PassportElementErrorFiles(Space.type_, Space.file_hashes, Space.message)
+        c = PassportElementErrorFiles(Space.type_, "", "")
+        d = PassportElementErrorFiles("", Space.file_hashes, "")
+        e = PassportElementErrorFiles("", "", Space.message)
+        f = PassportElementErrorSelfie(Space.type_, "", Space.message)
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_passportelementerrorfrontside.py b/tests/test_passportelementerrorfrontside.py
index b8389eac246..728ec8d5d7b 100644
--- a/tests/test_passportelementerrorfrontside.py
+++ b/tests/test_passportelementerrorfrontside.py
@@ -21,21 +21,19 @@
 from telegram import PassportElementErrorFrontSide, PassportElementErrorSelfie
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def passport_element_error_front_side():
-    return PassportElementErrorFrontSide(
-        TestPassportElementErrorFrontSide.type_,
-        TestPassportElementErrorFrontSide.file_hash,
-        TestPassportElementErrorFrontSide.message,
-    )
+    return PassportElementErrorFrontSide(Space.type_, Space.file_hash, Space.message)
 
 
-class TestPassportElementErrorFrontSide:
+class Space:
     source = "front_side"
     type_ = "test_type"
     file_hash = "file_hash"
     message = "Error message"
 
+
+class TestPassportElementErrorFrontSideNoReq:
     def test_slot_behaviour(self, passport_element_error_front_side, mro_slots):
         inst = passport_element_error_front_side
         for attr in inst.__slots__:
@@ -43,10 +41,10 @@ def test_slot_behaviour(self, passport_element_error_front_side, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, passport_element_error_front_side):
-        assert passport_element_error_front_side.source == self.source
-        assert passport_element_error_front_side.type == self.type_
-        assert passport_element_error_front_side.file_hash == self.file_hash
-        assert passport_element_error_front_side.message == self.message
+        assert passport_element_error_front_side.source == Space.source
+        assert passport_element_error_front_side.type == Space.type_
+        assert passport_element_error_front_side.file_hash == Space.file_hash
+        assert passport_element_error_front_side.message == Space.message
 
     def test_to_dict(self, passport_element_error_front_side):
         passport_element_error_front_side_dict = passport_element_error_front_side.to_dict()
@@ -70,12 +68,12 @@ def test_to_dict(self, passport_element_error_front_side):
         )
 
     def test_equality(self):
-        a = PassportElementErrorFrontSide(self.type_, self.file_hash, self.message)
-        b = PassportElementErrorFrontSide(self.type_, self.file_hash, self.message)
-        c = PassportElementErrorFrontSide(self.type_, "", "")
-        d = PassportElementErrorFrontSide("", self.file_hash, "")
-        e = PassportElementErrorFrontSide("", "", self.message)
-        f = PassportElementErrorSelfie(self.type_, self.file_hash, self.message)
+        a = PassportElementErrorFrontSide(Space.type_, Space.file_hash, Space.message)
+        b = PassportElementErrorFrontSide(Space.type_, Space.file_hash, Space.message)
+        c = PassportElementErrorFrontSide(Space.type_, "", "")
+        d = PassportElementErrorFrontSide("", Space.file_hash, "")
+        e = PassportElementErrorFrontSide("", "", Space.message)
+        f = PassportElementErrorSelfie(Space.type_, Space.file_hash, Space.message)
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_passportelementerrorreverseside.py b/tests/test_passportelementerrorreverseside.py
index 80cb3acab90..32cd0e01585 100644
--- a/tests/test_passportelementerrorreverseside.py
+++ b/tests/test_passportelementerrorreverseside.py
@@ -21,21 +21,19 @@
 from telegram import PassportElementErrorReverseSide, PassportElementErrorSelfie
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def passport_element_error_reverse_side():
-    return PassportElementErrorReverseSide(
-        TestPassportElementErrorReverseSide.type_,
-        TestPassportElementErrorReverseSide.file_hash,
-        TestPassportElementErrorReverseSide.message,
-    )
+    return PassportElementErrorReverseSide(Space.type_, Space.file_hash, Space.message)
 
 
-class TestPassportElementErrorReverseSide:
+class Space:
     source = "reverse_side"
     type_ = "test_type"
     file_hash = "file_hash"
     message = "Error message"
 
+
+class TestPassportElementErrorReverseSideNoReq:
     def test_slot_behaviour(self, passport_element_error_reverse_side, mro_slots):
         inst = passport_element_error_reverse_side
         for attr in inst.__slots__:
@@ -43,10 +41,10 @@ def test_slot_behaviour(self, passport_element_error_reverse_side, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, passport_element_error_reverse_side):
-        assert passport_element_error_reverse_side.source == self.source
-        assert passport_element_error_reverse_side.type == self.type_
-        assert passport_element_error_reverse_side.file_hash == self.file_hash
-        assert passport_element_error_reverse_side.message == self.message
+        assert passport_element_error_reverse_side.source == Space.source
+        assert passport_element_error_reverse_side.type == Space.type_
+        assert passport_element_error_reverse_side.file_hash == Space.file_hash
+        assert passport_element_error_reverse_side.message == Space.message
 
     def test_to_dict(self, passport_element_error_reverse_side):
         passport_element_error_reverse_side_dict = passport_element_error_reverse_side.to_dict()
@@ -70,12 +68,12 @@ def test_to_dict(self, passport_element_error_reverse_side):
         )
 
     def test_equality(self):
-        a = PassportElementErrorReverseSide(self.type_, self.file_hash, self.message)
-        b = PassportElementErrorReverseSide(self.type_, self.file_hash, self.message)
-        c = PassportElementErrorReverseSide(self.type_, "", "")
-        d = PassportElementErrorReverseSide("", self.file_hash, "")
-        e = PassportElementErrorReverseSide("", "", self.message)
-        f = PassportElementErrorSelfie(self.type_, self.file_hash, self.message)
+        a = PassportElementErrorReverseSide(Space.type_, Space.file_hash, Space.message)
+        b = PassportElementErrorReverseSide(Space.type_, Space.file_hash, Space.message)
+        c = PassportElementErrorReverseSide(Space.type_, "", "")
+        d = PassportElementErrorReverseSide("", Space.file_hash, "")
+        e = PassportElementErrorReverseSide("", "", Space.message)
+        f = PassportElementErrorSelfie(Space.type_, Space.file_hash, Space.message)
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_passportelementerrorselfie.py b/tests/test_passportelementerrorselfie.py
index 993dc34f178..d15d92c120d 100644
--- a/tests/test_passportelementerrorselfie.py
+++ b/tests/test_passportelementerrorselfie.py
@@ -21,21 +21,19 @@
 from telegram import PassportElementErrorDataField, PassportElementErrorSelfie
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def passport_element_error_selfie():
-    return PassportElementErrorSelfie(
-        TestPassportElementErrorSelfie.type_,
-        TestPassportElementErrorSelfie.file_hash,
-        TestPassportElementErrorSelfie.message,
-    )
+    return PassportElementErrorSelfie(Space.type_, Space.file_hash, Space.message)
 
 
-class TestPassportElementErrorSelfie:
+class Space:
     source = "selfie"
     type_ = "test_type"
     file_hash = "file_hash"
     message = "Error message"
 
+
+class TestPassportElementErrorSelfieNoReq:
     def test_slot_behaviour(self, passport_element_error_selfie, mro_slots):
         inst = passport_element_error_selfie
         for attr in inst.__slots__:
@@ -43,10 +41,10 @@ def test_slot_behaviour(self, passport_element_error_selfie, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, passport_element_error_selfie):
-        assert passport_element_error_selfie.source == self.source
-        assert passport_element_error_selfie.type == self.type_
-        assert passport_element_error_selfie.file_hash == self.file_hash
-        assert passport_element_error_selfie.message == self.message
+        assert passport_element_error_selfie.source == Space.source
+        assert passport_element_error_selfie.type == Space.type_
+        assert passport_element_error_selfie.file_hash == Space.file_hash
+        assert passport_element_error_selfie.message == Space.message
 
     def test_to_dict(self, passport_element_error_selfie):
         passport_element_error_selfie_dict = passport_element_error_selfie.to_dict()
@@ -63,12 +61,12 @@ def test_to_dict(self, passport_element_error_selfie):
         )
 
     def test_equality(self):
-        a = PassportElementErrorSelfie(self.type_, self.file_hash, self.message)
-        b = PassportElementErrorSelfie(self.type_, self.file_hash, self.message)
-        c = PassportElementErrorSelfie(self.type_, "", "")
-        d = PassportElementErrorSelfie("", self.file_hash, "")
-        e = PassportElementErrorSelfie("", "", self.message)
-        f = PassportElementErrorDataField(self.type_, "", "", self.message)
+        a = PassportElementErrorSelfie(Space.type_, Space.file_hash, Space.message)
+        b = PassportElementErrorSelfie(Space.type_, Space.file_hash, Space.message)
+        c = PassportElementErrorSelfie(Space.type_, "", "")
+        d = PassportElementErrorSelfie("", Space.file_hash, "")
+        e = PassportElementErrorSelfie("", "", Space.message)
+        f = PassportElementErrorDataField(Space.type_, "", "", Space.message)
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_passportelementerrortranslationfile.py b/tests/test_passportelementerrortranslationfile.py
index 79e886e080b..c93855343ba 100644
--- a/tests/test_passportelementerrortranslationfile.py
+++ b/tests/test_passportelementerrortranslationfile.py
@@ -21,21 +21,19 @@
 from telegram import PassportElementErrorDataField, PassportElementErrorTranslationFile
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def passport_element_error_translation_file():
-    return PassportElementErrorTranslationFile(
-        TestPassportElementErrorTranslationFile.type_,
-        TestPassportElementErrorTranslationFile.file_hash,
-        TestPassportElementErrorTranslationFile.message,
-    )
+    return PassportElementErrorTranslationFile(Space.type_, Space.file_hash, Space.message)
 
 
-class TestPassportElementErrorTranslationFile:
+class Space:
     source = "translation_file"
     type_ = "test_type"
     file_hash = "file_hash"
     message = "Error message"
 
+
+class TestPassportElementErrorTranslationFileNoReq:
     def test_slot_behaviour(self, passport_element_error_translation_file, mro_slots):
         inst = passport_element_error_translation_file
         for attr in inst.__slots__:
@@ -43,10 +41,10 @@ def test_slot_behaviour(self, passport_element_error_translation_file, mro_slots
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, passport_element_error_translation_file):
-        assert passport_element_error_translation_file.source == self.source
-        assert passport_element_error_translation_file.type == self.type_
-        assert passport_element_error_translation_file.file_hash == self.file_hash
-        assert passport_element_error_translation_file.message == self.message
+        assert passport_element_error_translation_file.source == Space.source
+        assert passport_element_error_translation_file.type == Space.type_
+        assert passport_element_error_translation_file.file_hash == Space.file_hash
+        assert passport_element_error_translation_file.message == Space.message
 
     def test_to_dict(self, passport_element_error_translation_file):
         passport_element_error_translation_file_dict = (
@@ -72,12 +70,12 @@ def test_to_dict(self, passport_element_error_translation_file):
         )
 
     def test_equality(self):
-        a = PassportElementErrorTranslationFile(self.type_, self.file_hash, self.message)
-        b = PassportElementErrorTranslationFile(self.type_, self.file_hash, self.message)
-        c = PassportElementErrorTranslationFile(self.type_, "", "")
-        d = PassportElementErrorTranslationFile("", self.file_hash, "")
-        e = PassportElementErrorTranslationFile("", "", self.message)
-        f = PassportElementErrorDataField(self.type_, "", "", self.message)
+        a = PassportElementErrorTranslationFile(Space.type_, Space.file_hash, Space.message)
+        b = PassportElementErrorTranslationFile(Space.type_, Space.file_hash, Space.message)
+        c = PassportElementErrorTranslationFile(Space.type_, "", "")
+        d = PassportElementErrorTranslationFile("", Space.file_hash, "")
+        e = PassportElementErrorTranslationFile("", "", Space.message)
+        f = PassportElementErrorDataField(Space.type_, "", "", Space.message)
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_passportelementerrortranslationfiles.py b/tests/test_passportelementerrortranslationfiles.py
index 69be1a927b2..a301857d303 100644
--- a/tests/test_passportelementerrortranslationfiles.py
+++ b/tests/test_passportelementerrortranslationfiles.py
@@ -21,21 +21,19 @@
 from telegram import PassportElementErrorSelfie, PassportElementErrorTranslationFiles
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def passport_element_error_translation_files():
-    return PassportElementErrorTranslationFiles(
-        TestPassportElementErrorTranslationFiles.type_,
-        TestPassportElementErrorTranslationFiles.file_hashes,
-        TestPassportElementErrorTranslationFiles.message,
-    )
+    return PassportElementErrorTranslationFiles(Space.type_, Space.file_hashes, Space.message)
 
 
-class TestPassportElementErrorTranslationFiles:
+class Space:
     source = "translation_files"
     type_ = "test_type"
     file_hashes = ["hash1", "hash2"]
     message = "Error message"
 
+
+class TestPassportElementErrorTranslationFilesNoReq:
     def test_slot_behaviour(self, passport_element_error_translation_files, mro_slots):
         inst = passport_element_error_translation_files
         for attr in inst.__slots__:
@@ -43,11 +41,11 @@ def test_slot_behaviour(self, passport_element_error_translation_files, mro_slot
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, passport_element_error_translation_files):
-        assert passport_element_error_translation_files.source == self.source
-        assert passport_element_error_translation_files.type == self.type_
+        assert passport_element_error_translation_files.source == Space.source
+        assert passport_element_error_translation_files.type == Space.type_
         assert isinstance(passport_element_error_translation_files.file_hashes, list)
-        assert passport_element_error_translation_files.file_hashes == self.file_hashes
-        assert passport_element_error_translation_files.message == self.message
+        assert passport_element_error_translation_files.file_hashes == Space.file_hashes
+        assert passport_element_error_translation_files.message == Space.message
 
     def test_to_dict(self, passport_element_error_translation_files):
         passport_element_error_translation_files_dict = (
@@ -73,12 +71,12 @@ def test_to_dict(self, passport_element_error_translation_files):
         )
 
     def test_equality(self):
-        a = PassportElementErrorTranslationFiles(self.type_, self.file_hashes, self.message)
-        b = PassportElementErrorTranslationFiles(self.type_, self.file_hashes, self.message)
-        c = PassportElementErrorTranslationFiles(self.type_, "", "")
-        d = PassportElementErrorTranslationFiles("", self.file_hashes, "")
-        e = PassportElementErrorTranslationFiles("", "", self.message)
-        f = PassportElementErrorSelfie(self.type_, "", self.message)
+        a = PassportElementErrorTranslationFiles(Space.type_, Space.file_hashes, Space.message)
+        b = PassportElementErrorTranslationFiles(Space.type_, Space.file_hashes, Space.message)
+        c = PassportElementErrorTranslationFiles(Space.type_, "", "")
+        d = PassportElementErrorTranslationFiles("", Space.file_hashes, "")
+        e = PassportElementErrorTranslationFiles("", "", Space.message)
+        f = PassportElementErrorSelfie(Space.type_, "", Space.message)
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_passportelementerrorunspecified.py b/tests/test_passportelementerrorunspecified.py
index 5640bb3bd1c..53f27460dab 100644
--- a/tests/test_passportelementerrorunspecified.py
+++ b/tests/test_passportelementerrorunspecified.py
@@ -21,21 +21,19 @@
 from telegram import PassportElementErrorDataField, PassportElementErrorUnspecified
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def passport_element_error_unspecified():
-    return PassportElementErrorUnspecified(
-        TestPassportElementErrorUnspecified.type_,
-        TestPassportElementErrorUnspecified.element_hash,
-        TestPassportElementErrorUnspecified.message,
-    )
+    return PassportElementErrorUnspecified(Space.type_, Space.element_hash, Space.message)
 
 
-class TestPassportElementErrorUnspecified:
+class Space:
     source = "unspecified"
     type_ = "test_type"
     element_hash = "element_hash"
     message = "Error message"
 
+
+class TestPassportElementErrorUnspecifiedNoReq:
     def test_slot_behaviour(self, passport_element_error_unspecified, mro_slots):
         inst = passport_element_error_unspecified
         for attr in inst.__slots__:
@@ -43,10 +41,10 @@ def test_slot_behaviour(self, passport_element_error_unspecified, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, passport_element_error_unspecified):
-        assert passport_element_error_unspecified.source == self.source
-        assert passport_element_error_unspecified.type == self.type_
-        assert passport_element_error_unspecified.element_hash == self.element_hash
-        assert passport_element_error_unspecified.message == self.message
+        assert passport_element_error_unspecified.source == Space.source
+        assert passport_element_error_unspecified.type == Space.type_
+        assert passport_element_error_unspecified.element_hash == Space.element_hash
+        assert passport_element_error_unspecified.message == Space.message
 
     def test_to_dict(self, passport_element_error_unspecified):
         passport_element_error_unspecified_dict = passport_element_error_unspecified.to_dict()
@@ -70,12 +68,12 @@ def test_to_dict(self, passport_element_error_unspecified):
         )
 
     def test_equality(self):
-        a = PassportElementErrorUnspecified(self.type_, self.element_hash, self.message)
-        b = PassportElementErrorUnspecified(self.type_, self.element_hash, self.message)
-        c = PassportElementErrorUnspecified(self.type_, "", "")
-        d = PassportElementErrorUnspecified("", self.element_hash, "")
-        e = PassportElementErrorUnspecified("", "", self.message)
-        f = PassportElementErrorDataField(self.type_, "", "", self.message)
+        a = PassportElementErrorUnspecified(Space.type_, Space.element_hash, Space.message)
+        b = PassportElementErrorUnspecified(Space.type_, Space.element_hash, Space.message)
+        c = PassportElementErrorUnspecified(Space.type_, "", "")
+        d = PassportElementErrorUnspecified("", Space.element_hash, "")
+        e = PassportElementErrorUnspecified("", "", Space.message)
+        f = PassportElementErrorDataField(Space.type_, "", "", Space.message)
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_passportfile.py b/tests/test_passportfile.py
index 4ec365a2266..c39a2ba7aa5 100644
--- a/tests/test_passportfile.py
+++ b/tests/test_passportfile.py
@@ -29,21 +29,23 @@
 @pytest.fixture(scope="class")
 def passport_file(bot):
     pf = PassportFile(
-        file_id=TestPassportFile.file_id,
-        file_unique_id=TestPassportFile.file_unique_id,
-        file_size=TestPassportFile.file_size,
-        file_date=TestPassportFile.file_date,
+        file_id=Space.file_id,
+        file_unique_id=Space.file_unique_id,
+        file_size=Space.file_size,
+        file_date=Space.file_date,
     )
     pf.set_bot(bot)
     return pf
 
 
-class TestPassportFile:
+class Space:
     file_id = "data"
     file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
     file_size = 50
     file_date = 1532879128
 
+
+class TestPassportFileNoReq:
     def test_slot_behaviour(self, passport_file, mro_slots):
         inst = passport_file
         for attr in inst.__slots__:
@@ -51,10 +53,10 @@ def test_slot_behaviour(self, passport_file, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, passport_file):
-        assert passport_file.file_id == self.file_id
-        assert passport_file.file_unique_id == self.file_unique_id
-        assert passport_file.file_size == self.file_size
-        assert passport_file.file_date == self.file_date
+        assert passport_file.file_id == Space.file_id
+        assert passport_file.file_unique_id == Space.file_unique_id
+        assert passport_file.file_size == Space.file_size
+        assert passport_file.file_date == Space.file_date
 
     def test_to_dict(self, passport_file):
         passport_file_dict = passport_file.to_dict()
@@ -81,10 +83,10 @@ async def make_assertion(*_, **kwargs):
         assert (await passport_file.get_file()).file_id == "True"
 
     def test_equality(self):
-        a = PassportFile(self.file_id, self.file_unique_id, self.file_size, self.file_date)
-        b = PassportFile("", self.file_unique_id, self.file_size, self.file_date)
-        c = PassportFile(self.file_id, self.file_unique_id, "", "")
-        d = PassportFile("", "", self.file_size, self.file_date)
+        a = PassportFile(Space.file_id, Space.file_unique_id, Space.file_size, Space.file_date)
+        b = PassportFile("", Space.file_unique_id, Space.file_size, Space.file_date)
+        c = PassportFile(Space.file_id, Space.file_unique_id, "", "")
+        d = PassportFile("", "", Space.file_size, Space.file_date)
         e = PassportElementError("source", "type", "message")
 
         assert a == b
diff --git a/tests/test_photo.py b/tests/test_photo.py
index 4d7baeeec48..cbbfe44a392 100644
--- a/tests/test_photo.py
+++ b/tests/test_photo.py
@@ -15,6 +15,7 @@
 #
 # You should have received a copy of the GNU Lesser Public License
 # along with this program.  If not, see [http://www.gnu.org/licenses/].
+import asyncio
 import os
 from io import BytesIO
 from pathlib import Path
@@ -35,34 +36,32 @@
 
 @pytest.fixture(scope="function")
 def photo_file():
-    f = data_file("telegram.jpg").open("rb")
-    yield f
-    f.close()
+    with data_file("telegram.jpg").open("rb") as f:
+        yield f
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 async def _photo(bot, chat_id):
     async def func():
         with data_file("telegram.jpg").open("rb") as f:
-            photo = (await bot.send_photo(chat_id, photo=f, read_timeout=50)).photo
-            return photo
+            return (await bot.send_photo(chat_id, photo=f, read_timeout=50)).photo
 
     return await expect_bad_request(
         func, "Type of file mismatch", "Telegram did not accept the file."
     )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def thumb(_photo):
     return _photo[0]
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def photo(_photo):
     return _photo[-1]
 
 
-class TestPhoto:
+class Space:
     width = 800
     height = 800
     caption = "<b>PhotoTest</b> - *Caption*"
@@ -71,6 +70,8 @@ class TestPhoto:
     # so we accept three different sizes here. Shouldn't be too much
     file_size = [29176, 27662]
 
+
+class TestPhotoNoReq:
     def test_slot_behaviour(self, photo, mro_slots):
         for attr in photo.__slots__:
             assert getattr(photo, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -91,19 +92,128 @@ def test_creation(self, thumb, photo):
         assert thumb.file_unique_id != ""
 
     def test_expected_values(self, photo, thumb):
-        assert photo.width == self.width
-        assert photo.height == self.height
-        assert photo.file_size in self.file_size
+        assert photo.width == Space.width
+        assert photo.height == Space.height
+        assert photo.file_size in Space.file_size
         assert thumb.width == 90
         assert thumb.height == 90
         assert thumb.file_size == 1477
 
-    @pytest.mark.flaky(3, 1)
+    async def test_send_photo_custom_filename(self, bot, chat_id, photo_file, monkeypatch):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            return list(request_data.multipart_data.values())[0][0] == "custom_filename"
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+
+        assert await bot.send_photo(chat_id, photo_file, filename="custom_filename")
+
+    @pytest.mark.parametrize("local_mode", [True, False])
+    async def test_send_photo_local_files(self, monkeypatch, bot, chat_id, local_mode):
+        try:
+            bot._local_mode = local_mode
+            # For just test that the correct paths are passed as we have no local bot API set up
+            test_flag = False
+            file = data_file("telegram.jpg")
+            expected = file.as_uri()
+
+            async def make_assertion(_, data, *args, **kwargs):
+                nonlocal test_flag
+                if local_mode:
+                    test_flag = data.get("photo") == expected
+                else:
+                    test_flag = isinstance(data.get("photo"), InputFile)
+
+            monkeypatch.setattr(bot, "_post", make_assertion)
+            await bot.send_photo(chat_id, file)
+            assert test_flag
+        finally:
+            bot._local_mode = False
+
+    async def test_send_with_photosize(self, monkeypatch, bot, chat_id, photo):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            return request_data.json_parameters["photo"] == photo.file_id
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+        message = await bot.send_photo(photo=photo, chat_id=chat_id)
+        assert message
+
+    def test_de_json(self, bot, photo):
+        json_dict = {
+            "file_id": photo.file_id,
+            "file_unique_id": photo.file_unique_id,
+            "width": Space.width,
+            "height": Space.height,
+            "file_size": Space.file_size,
+        }
+        json_photo = PhotoSize.de_json(json_dict, bot)
+        assert json_photo.api_kwargs == {}
+
+        assert json_photo.file_id == photo.file_id
+        assert json_photo.file_unique_id == photo.file_unique_id
+        assert json_photo.width == Space.width
+        assert json_photo.height == Space.height
+        assert json_photo.file_size == Space.file_size
+
+    def test_to_dict(self, photo):
+        photo_dict = photo.to_dict()
+
+        assert isinstance(photo_dict, dict)
+        assert photo_dict["file_id"] == photo.file_id
+        assert photo_dict["file_unique_id"] == photo.file_unique_id
+        assert photo_dict["width"] == photo.width
+        assert photo_dict["height"] == photo.height
+        assert photo_dict["file_size"] == photo.file_size
+
+    async def test_error_without_required_args(self, bot, chat_id):
+        with pytest.raises(TypeError):
+            await bot.send_photo(chat_id=chat_id)
+
+    async def test_get_file_instance_method(self, monkeypatch, photo):
+        async def make_assertion(*_, **kwargs):
+            return kwargs["file_id"] == photo.file_id
+
+        assert check_shortcut_signature(PhotoSize.get_file, Bot.get_file, ["file_id"], [])
+        assert await check_shortcut_call(photo.get_file, photo.get_bot(), "get_file")
+        assert await check_defaults_handling(photo.get_file, photo.get_bot())
+
+        monkeypatch.setattr(photo.get_bot(), "get_file", make_assertion)
+        assert await photo.get_file()
+
+    def test_equality(self, photo):
+        a = PhotoSize(photo.file_id, photo.file_unique_id, Space.width, Space.height)
+        b = PhotoSize("", photo.file_unique_id, Space.width, Space.height)
+        c = PhotoSize(photo.file_id, photo.file_unique_id, 0, 0)
+        d = PhotoSize("", "", Space.width, Space.height)
+        e = Sticker(
+            photo.file_id,
+            photo.file_unique_id,
+            Space.width,
+            Space.height,
+            False,
+            False,
+            Sticker.REGULAR,
+        )
+
+        assert a == b
+        assert hash(a) == hash(b)
+        assert a is not b
+
+        assert a == c
+        assert hash(a) == hash(c)
+
+        assert a != d
+        assert hash(a) != hash(d)
+
+        assert a != e
+        assert hash(a) != hash(e)
+
+
+class TestPhotoReq:
     async def test_send_photo_all_args(self, bot, chat_id, photo_file, thumb, photo):
         message = await bot.send_photo(
             chat_id,
             photo_file,
-            caption=self.caption,
+            caption=Space.caption,
             disable_notification=False,
             protect_content=True,
             parse_mode="Markdown",
@@ -121,22 +231,12 @@ async def test_send_photo_all_args(self, bot, chat_id, photo_file, thumb, photo)
         assert message.photo[-1].file_id != ""
         assert message.photo[-1].file_unique_id != ""
 
-        assert message.caption == TestPhoto.caption.replace("*", "")
+        assert message.caption == Space.caption.replace("*", "")
         assert message.has_protected_content
 
-    @pytest.mark.flaky(3, 1)
-    async def test_send_photo_custom_filename(self, bot, chat_id, photo_file, monkeypatch):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            return list(request_data.multipart_data.values())[0][0] == "custom_filename"
-
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-
-        assert await bot.send_photo(chat_id, photo_file, filename="custom_filename")
-
-    @pytest.mark.flaky(3, 1)
     async def test_send_photo_parse_mode_markdown(self, bot, chat_id, photo_file, thumb, photo):
         message = await bot.send_photo(
-            chat_id, photo_file, caption=self.caption, parse_mode="Markdown"
+            chat_id, photo_file, caption=Space.caption, parse_mode="Markdown"
         )
         assert isinstance(message.photo[-2], PhotoSize)
         assert isinstance(message.photo[-2].file_id, str)
@@ -150,13 +250,12 @@ async def test_send_photo_parse_mode_markdown(self, bot, chat_id, photo_file, th
         assert message.photo[-1].file_id != ""
         assert message.photo[-1].file_unique_id != ""
 
-        assert message.caption == TestPhoto.caption.replace("*", "")
+        assert message.caption == Space.caption.replace("*", "")
         assert len(message.caption_entities) == 1
 
-    @pytest.mark.flaky(3, 1)
     async def test_send_photo_parse_mode_html(self, bot, chat_id, photo_file, thumb, photo):
         message = await bot.send_photo(
-            chat_id, photo_file, caption=self.caption, parse_mode="HTML"
+            chat_id, photo_file, caption=Space.caption, parse_mode="HTML"
         )
         assert isinstance(message.photo[-2], PhotoSize)
         assert isinstance(message.photo[-2].file_id, str)
@@ -170,10 +269,9 @@ async def test_send_photo_parse_mode_html(self, bot, chat_id, photo_file, thumb,
         assert message.photo[-1].file_id != ""
         assert message.photo[-1].file_unique_id != ""
 
-        assert message.caption == TestPhoto.caption.replace("<b>", "").replace("</b>", "")
+        assert message.caption == Space.caption.replace("<b>", "").replace("</b>", "")
         assert len(message.caption_entities) == 1
 
-    @pytest.mark.flaky(3, 1)
     async def test_send_photo_caption_entities(self, bot, chat_id, photo_file, thumb, photo):
         test_string = "Italic Bold Code"
         entities = [
@@ -188,7 +286,6 @@ async def test_send_photo_caption_entities(self, bot, chat_id, photo_file, thumb
         assert message.caption == test_string
         assert message.caption_entities == tuple(entities)
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_send_photo_default_parse_mode_1(
         self, default_bot, chat_id, photo_file, thumb, photo
@@ -200,7 +297,6 @@ async def test_send_photo_default_parse_mode_1(
         assert message.caption_markdown == test_markdown_string
         assert message.caption == test_string
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_send_photo_default_parse_mode_2(
         self, default_bot, chat_id, photo_file, thumb, photo
@@ -213,7 +309,6 @@ async def test_send_photo_default_parse_mode_2(
         assert message.caption == test_markdown_string
         assert message.caption_markdown == escape_markdown(test_markdown_string)
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_send_photo_default_parse_mode_3(
         self, default_bot, chat_id, photo_file, thumb, photo
@@ -226,37 +321,16 @@ async def test_send_photo_default_parse_mode_3(
         assert message.caption == test_markdown_string
         assert message.caption_markdown == escape_markdown(test_markdown_string)
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
     async def test_send_photo_default_protect_content(self, chat_id, default_bot, photo):
-        protected = await default_bot.send_photo(chat_id, photo)
+        tasks = asyncio.gather(
+            default_bot.send_photo(chat_id, photo),
+            default_bot.send_photo(chat_id, photo, protect_content=False),
+        )
+        protected, unprotected = await tasks
         assert protected.has_protected_content
-        unprotected = await default_bot.send_photo(chat_id, photo, protect_content=False)
         assert not unprotected.has_protected_content
 
-    @pytest.mark.parametrize("local_mode", [True, False])
-    async def test_send_photo_local_files(self, monkeypatch, bot, chat_id, local_mode):
-        try:
-            bot._local_mode = local_mode
-            # For just test that the correct paths are passed as we have no local bot API set up
-            test_flag = False
-            file = data_file("telegram.jpg")
-            expected = file.as_uri()
-
-            async def make_assertion(_, data, *args, **kwargs):
-                nonlocal test_flag
-                if local_mode:
-                    test_flag = data.get("photo") == expected
-                else:
-                    test_flag = isinstance(data.get("photo"), InputFile)
-
-            monkeypatch.setattr(bot, "_post", make_assertion)
-            await bot.send_photo(chat_id, file)
-            assert test_flag
-        finally:
-            bot._local_mode = False
-
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize(
         "default_bot,custom",
         [
@@ -290,7 +364,6 @@ async def test_send_photo_default_allow_sending_without_reply(
                     chat_id, photo_file, reply_to_message_id=reply_to_message.message_id
                 )
 
-    @pytest.mark.flaky(3, 1)
     async def test_get_and_download(self, bot, photo):
         path = Path("telegram.jpg")
         if path.is_file():
@@ -306,9 +379,8 @@ async def test_get_and_download(self, bot, photo):
 
         assert path.is_file()
 
-    @pytest.mark.flaky(3, 1)
     async def test_send_url_jpg_file(self, bot, chat_id, thumb, photo):
-        message = await bot.send_photo(chat_id, photo=self.photo_file_url)
+        message = await bot.send_photo(chat_id, photo=Space.photo_file_url)
 
         assert isinstance(message.photo[-2], PhotoSize)
         assert isinstance(message.photo[-2].file_id, str)
@@ -322,7 +394,6 @@ async def test_send_url_jpg_file(self, bot, chat_id, thumb, photo):
         assert message.photo[-1].file_id != ""
         assert message.photo[-1].file_unique_id != ""
 
-    @pytest.mark.flaky(3, 1)
     async def test_send_url_png_file(self, bot, chat_id):
         message = await bot.send_photo(
             photo="http://dummyimage.com/600x400/000/fff.png&text=telegram", chat_id=chat_id
@@ -336,7 +407,6 @@ async def test_send_url_png_file(self, bot, chat_id):
         assert photo.file_id != ""
         assert photo.file_unique_id != ""
 
-    @pytest.mark.flaky(3, 1)
     async def test_send_url_gif_file(self, bot, chat_id):
         message = await bot.send_photo(
             photo="http://dummyimage.com/600x400/000/fff.png&text=telegram", chat_id=chat_id
@@ -350,7 +420,6 @@ async def test_send_url_gif_file(self, bot, chat_id):
         assert photo.file_id != ""
         assert photo.file_unique_id != ""
 
-    @pytest.mark.flaky(3, 1)
     async def test_send_file_unicode_filename(self, bot, chat_id):
         """
         Regression test for https://github.com/python-telegram-bot/python-telegram-bot/issues/1202
@@ -366,7 +435,6 @@ async def test_send_file_unicode_filename(self, bot, chat_id):
         assert photo.file_id != ""
         assert photo.file_unique_id != ""
 
-    @pytest.mark.flaky(3, 1)
     async def test_send_bytesio_jpg_file(self, bot, chat_id):
         filepath = data_file("telegram_no_standard_header.jpg")
 
@@ -394,15 +462,6 @@ async def test_send_bytesio_jpg_file(self, bot, chat_id):
         assert photo.height == 720
         assert photo.file_size == 33372
 
-    async def test_send_with_photosize(self, monkeypatch, bot, chat_id, photo):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            return request_data.json_parameters["photo"] == photo.file_id
-
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-        message = await bot.send_photo(photo=photo, chat_id=chat_id)
-        assert message
-
-    @pytest.mark.flaky(3, 1)
     async def test_resend(self, bot, chat_id, photo, thumb):
         message = await bot.send_photo(chat_id=chat_id, photo=photo.file_id)
 
@@ -418,82 +477,10 @@ async def test_resend(self, bot, chat_id, photo, thumb):
         assert message.photo[-1].file_id != ""
         assert message.photo[-1].file_unique_id != ""
 
-    def test_de_json(self, bot, photo):
-        json_dict = {
-            "file_id": photo.file_id,
-            "file_unique_id": photo.file_unique_id,
-            "width": self.width,
-            "height": self.height,
-            "file_size": self.file_size,
-        }
-        json_photo = PhotoSize.de_json(json_dict, bot)
-        assert json_photo.api_kwargs == {}
-
-        assert json_photo.file_id == photo.file_id
-        assert json_photo.file_unique_id == photo.file_unique_id
-        assert json_photo.width == self.width
-        assert json_photo.height == self.height
-        assert json_photo.file_size == self.file_size
-
-    def test_to_dict(self, photo):
-        photo_dict = photo.to_dict()
-
-        assert isinstance(photo_dict, dict)
-        assert photo_dict["file_id"] == photo.file_id
-        assert photo_dict["file_unique_id"] == photo.file_unique_id
-        assert photo_dict["width"] == photo.width
-        assert photo_dict["height"] == photo.height
-        assert photo_dict["file_size"] == photo.file_size
-
-    @pytest.mark.flaky(3, 1)
     async def test_error_send_empty_file(self, bot, chat_id):
         with pytest.raises(TelegramError):
             await bot.send_photo(chat_id=chat_id, photo=open(os.devnull, "rb"))
 
-    @pytest.mark.flaky(3, 1)
     async def test_error_send_empty_file_id(self, bot, chat_id):
         with pytest.raises(TelegramError):
             await bot.send_photo(chat_id=chat_id, photo="")
-
-    async def test_error_without_required_args(self, bot, chat_id):
-        with pytest.raises(TypeError):
-            await bot.send_photo(chat_id=chat_id)
-
-    async def test_get_file_instance_method(self, monkeypatch, photo):
-        async def make_assertion(*_, **kwargs):
-            return kwargs["file_id"] == photo.file_id
-
-        assert check_shortcut_signature(PhotoSize.get_file, Bot.get_file, ["file_id"], [])
-        assert await check_shortcut_call(photo.get_file, photo.get_bot(), "get_file")
-        assert await check_defaults_handling(photo.get_file, photo.get_bot())
-
-        monkeypatch.setattr(photo.get_bot(), "get_file", make_assertion)
-        assert await photo.get_file()
-
-    def test_equality(self, photo):
-        a = PhotoSize(photo.file_id, photo.file_unique_id, self.width, self.height)
-        b = PhotoSize("", photo.file_unique_id, self.width, self.height)
-        c = PhotoSize(photo.file_id, photo.file_unique_id, 0, 0)
-        d = PhotoSize("", "", self.width, self.height)
-        e = Sticker(
-            photo.file_id,
-            photo.file_unique_id,
-            self.width,
-            self.height,
-            False,
-            False,
-            Sticker.REGULAR,
-        )
-
-        assert a == b
-        assert hash(a) == hash(b)
-        assert a is not b
-
-        assert a == c
-        assert hash(a) == hash(c)
-
-        assert a != d
-        assert hash(a) != hash(d)
-
-        assert a != e
-        assert hash(a) != hash(e)
diff --git a/tests/test_poll.py b/tests/test_poll.py
index 425c4eadf1a..b27ab4327b6 100644
--- a/tests/test_poll.py
+++ b/tests/test_poll.py
@@ -24,29 +24,31 @@
 from telegram.constants import PollType
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def poll_option():
-    out = PollOption(text=TestPollOption.text, voter_count=TestPollOption.voter_count)
+    out = PollOption(text=PollOptionSpace.text, voter_count=PollOptionSpace.voter_count)
     out._unfreeze()
     return out
 
 
-class TestPollOption:
+class PollOptionSpace:
     text = "test option"
     voter_count = 3
 
+
+class TestPollOptionNoReq:
     def test_slot_behaviour(self, poll_option, mro_slots):
         for attr in poll_option.__slots__:
             assert getattr(poll_option, attr, "err") != "err", f"got extra slot '{attr}'"
         assert len(mro_slots(poll_option)) == len(set(mro_slots(poll_option))), "duplicate slot"
 
     def test_de_json(self):
-        json_dict = {"text": self.text, "voter_count": self.voter_count}
+        json_dict = {"text": PollOptionSpace.text, "voter_count": PollOptionSpace.voter_count}
         poll_option = PollOption.de_json(json_dict, None)
         assert poll_option.api_kwargs == {}
 
-        assert poll_option.text == self.text
-        assert poll_option.voter_count == self.voter_count
+        assert poll_option.text == PollOptionSpace.text
+        assert poll_option.voter_count == PollOptionSpace.voter_count
 
     def test_to_dict(self, poll_option):
         poll_option_dict = poll_option.to_dict()
@@ -75,30 +77,30 @@ def test_equality(self):
         assert hash(a) != hash(e)
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def poll_answer():
-    return PollAnswer(
-        poll_id=TestPollAnswer.poll_id, user=TestPollAnswer.user, option_ids=TestPollAnswer.poll_id
-    )
+    return PollAnswer(PollAnswerSpace.poll_id, PollAnswerSpace.user, PollAnswerSpace.poll_id)
 
 
-class TestPollAnswer:
+class PollAnswerSpace:
     poll_id = "id"
     user = User(1, "", False)
     option_ids = [2]
 
+
+class TestPollAnswerNoReq:
     def test_de_json(self):
         json_dict = {
-            "poll_id": self.poll_id,
-            "user": self.user.to_dict(),
-            "option_ids": self.option_ids,
+            "poll_id": PollAnswerSpace.poll_id,
+            "user": PollAnswerSpace.user.to_dict(),
+            "option_ids": PollAnswerSpace.option_ids,
         }
         poll_answer = PollAnswer.de_json(json_dict, None)
         assert poll_answer.api_kwargs == {}
 
-        assert poll_answer.poll_id == self.poll_id
-        assert poll_answer.user == self.user
-        assert poll_answer.option_ids == tuple(self.option_ids)
+        assert poll_answer.poll_id == PollAnswerSpace.poll_id
+        assert poll_answer.user == PollAnswerSpace.user
+        assert poll_answer.option_ids == tuple(PollAnswerSpace.option_ids)
 
     def test_to_dict(self, poll_answer):
         poll_answer_dict = poll_answer.to_dict()
@@ -109,10 +111,10 @@ def test_to_dict(self, poll_answer):
         assert poll_answer_dict["option_ids"] == list(poll_answer.option_ids)
 
     def test_equality(self):
-        a = PollAnswer(123, self.user, [2])
+        a = PollAnswer(123, PollAnswerSpace.user, [2])
         b = PollAnswer(123, User(1, "first", False), [2])
-        c = PollAnswer(123, self.user, [1, 2])
-        d = PollAnswer(456, self.user, [2])
+        c = PollAnswer(123, PollAnswerSpace.user, [1, 2])
+        d = PollAnswer(456, PollAnswerSpace.user, [2])
         e = PollOption("Text", 1)
 
         assert a == b
@@ -128,27 +130,27 @@ def test_equality(self):
         assert hash(a) != hash(e)
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def poll():
     poll = Poll(
-        TestPoll.id_,
-        TestPoll.question,
-        TestPoll.options,
-        TestPoll.total_voter_count,
-        TestPoll.is_closed,
-        TestPoll.is_anonymous,
-        TestPoll.type,
-        TestPoll.allows_multiple_answers,
-        explanation=TestPoll.explanation,
-        explanation_entities=TestPoll.explanation_entities,
-        open_period=TestPoll.open_period,
-        close_date=TestPoll.close_date,
+        PollSpace.id_,
+        PollSpace.question,
+        PollSpace.options,
+        PollSpace.total_voter_count,
+        PollSpace.is_closed,
+        PollSpace.is_anonymous,
+        PollSpace.type,
+        PollSpace.allows_multiple_answers,
+        explanation=PollSpace.explanation,
+        explanation_entities=PollSpace.explanation_entities,
+        open_period=PollSpace.open_period,
+        close_date=PollSpace.close_date,
     )
     poll._unfreeze()
     return poll
 
 
-class TestPoll:
+class PollSpace:
     id_ = "id"
     question = "Test?"
     options = [PollOption("test", 10), PollOption("test2", 11)]
@@ -165,41 +167,43 @@ class TestPoll:
     open_period = 42
     close_date = datetime.now(timezone.utc)
 
+
+class TestPollNoReq:
     def test_de_json(self, bot):
         json_dict = {
-            "id": self.id_,
-            "question": self.question,
-            "options": [o.to_dict() for o in self.options],
-            "total_voter_count": self.total_voter_count,
-            "is_closed": self.is_closed,
-            "is_anonymous": self.is_anonymous,
-            "type": self.type,
-            "allows_multiple_answers": self.allows_multiple_answers,
-            "explanation": self.explanation,
-            "explanation_entities": [self.explanation_entities[0].to_dict()],
-            "open_period": self.open_period,
-            "close_date": to_timestamp(self.close_date),
+            "id": PollSpace.id_,
+            "question": PollSpace.question,
+            "options": [o.to_dict() for o in PollSpace.options],
+            "total_voter_count": PollSpace.total_voter_count,
+            "is_closed": PollSpace.is_closed,
+            "is_anonymous": PollSpace.is_anonymous,
+            "type": PollSpace.type,
+            "allows_multiple_answers": PollSpace.allows_multiple_answers,
+            "explanation": PollSpace.explanation,
+            "explanation_entities": [PollSpace.explanation_entities[0].to_dict()],
+            "open_period": PollSpace.open_period,
+            "close_date": to_timestamp(PollSpace.close_date),
         }
         poll = Poll.de_json(json_dict, bot)
         assert poll.api_kwargs == {}
 
-        assert poll.id == self.id_
-        assert poll.question == self.question
-        assert poll.options == tuple(self.options)
-        assert poll.options[0].text == self.options[0].text
-        assert poll.options[0].voter_count == self.options[0].voter_count
-        assert poll.options[1].text == self.options[1].text
-        assert poll.options[1].voter_count == self.options[1].voter_count
-        assert poll.total_voter_count == self.total_voter_count
-        assert poll.is_closed == self.is_closed
-        assert poll.is_anonymous == self.is_anonymous
-        assert poll.type == self.type
-        assert poll.allows_multiple_answers == self.allows_multiple_answers
-        assert poll.explanation == self.explanation
-        assert poll.explanation_entities == tuple(self.explanation_entities)
-        assert poll.open_period == self.open_period
-        assert abs(poll.close_date - self.close_date) < timedelta(seconds=1)
-        assert to_timestamp(poll.close_date) == to_timestamp(self.close_date)
+        assert poll.id == PollSpace.id_
+        assert poll.question == PollSpace.question
+        assert poll.options == tuple(PollSpace.options)
+        assert poll.options[0].text == PollSpace.options[0].text
+        assert poll.options[0].voter_count == PollSpace.options[0].voter_count
+        assert poll.options[1].text == PollSpace.options[1].text
+        assert poll.options[1].voter_count == PollSpace.options[1].voter_count
+        assert poll.total_voter_count == PollSpace.total_voter_count
+        assert poll.is_closed == PollSpace.is_closed
+        assert poll.is_anonymous == PollSpace.is_anonymous
+        assert poll.type == PollSpace.type
+        assert poll.allows_multiple_answers == PollSpace.allows_multiple_answers
+        assert poll.explanation == PollSpace.explanation
+        assert poll.explanation_entities == tuple(PollSpace.explanation_entities)
+        assert poll.open_period == PollSpace.open_period
+        assert abs(poll.close_date - PollSpace.close_date) < timedelta(seconds=1)
+        assert to_timestamp(poll.close_date) == to_timestamp(PollSpace.close_date)
 
     def test_to_dict(self, poll):
         poll_dict = poll.to_dict()
diff --git a/tests/test_precheckoutquery.py b/tests/test_precheckoutquery.py
index 00d4250ef1f..e583b53b84d 100644
--- a/tests/test_precheckoutquery.py
+++ b/tests/test_precheckoutquery.py
@@ -27,22 +27,22 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def pre_checkout_query(bot):
     pcq = PreCheckoutQuery(
-        TestPreCheckoutQuery.id_,
-        TestPreCheckoutQuery.from_user,
-        TestPreCheckoutQuery.currency,
-        TestPreCheckoutQuery.total_amount,
-        TestPreCheckoutQuery.invoice_payload,
-        shipping_option_id=TestPreCheckoutQuery.shipping_option_id,
-        order_info=TestPreCheckoutQuery.order_info,
+        Space.id_,
+        Space.from_user,
+        Space.currency,
+        Space.total_amount,
+        Space.invoice_payload,
+        shipping_option_id=Space.shipping_option_id,
+        order_info=Space.order_info,
     )
     pcq.set_bot(bot)
     return pcq
 
 
-class TestPreCheckoutQuery:
+class Space:
     id_ = 5
     invoice_payload = "invoice_payload"
     shipping_option_id = "shipping_option_id"
@@ -51,6 +51,8 @@ class TestPreCheckoutQuery:
     from_user = User(0, "", False)
     order_info = OrderInfo()
 
+
+class TestPreCheckoutQueryNoReq:
     def test_slot_behaviour(self, pre_checkout_query, mro_slots):
         inst = pre_checkout_query
         for attr in inst.__slots__:
@@ -59,24 +61,24 @@ def test_slot_behaviour(self, pre_checkout_query, mro_slots):
 
     def test_de_json(self, bot):
         json_dict = {
-            "id": self.id_,
-            "invoice_payload": self.invoice_payload,
-            "shipping_option_id": self.shipping_option_id,
-            "currency": self.currency,
-            "total_amount": self.total_amount,
-            "from": self.from_user.to_dict(),
-            "order_info": self.order_info.to_dict(),
+            "id": Space.id_,
+            "invoice_payload": Space.invoice_payload,
+            "shipping_option_id": Space.shipping_option_id,
+            "currency": Space.currency,
+            "total_amount": Space.total_amount,
+            "from": Space.from_user.to_dict(),
+            "order_info": Space.order_info.to_dict(),
         }
         pre_checkout_query = PreCheckoutQuery.de_json(json_dict, bot)
         assert pre_checkout_query.api_kwargs == {}
 
         assert pre_checkout_query.get_bot() is bot
-        assert pre_checkout_query.id == self.id_
-        assert pre_checkout_query.invoice_payload == self.invoice_payload
-        assert pre_checkout_query.shipping_option_id == self.shipping_option_id
-        assert pre_checkout_query.currency == self.currency
-        assert pre_checkout_query.from_user == self.from_user
-        assert pre_checkout_query.order_info == self.order_info
+        assert pre_checkout_query.id == Space.id_
+        assert pre_checkout_query.invoice_payload == Space.invoice_payload
+        assert pre_checkout_query.shipping_option_id == Space.shipping_option_id
+        assert pre_checkout_query.currency == Space.currency
+        assert pre_checkout_query.from_user == Space.from_user
+        assert pre_checkout_query.order_info == Space.order_info
 
     def test_to_dict(self, pre_checkout_query):
         pre_checkout_query_dict = pre_checkout_query.to_dict()
@@ -114,16 +116,16 @@ async def make_assertion(*_, **kwargs):
 
     def test_equality(self):
         a = PreCheckoutQuery(
-            self.id_, self.from_user, self.currency, self.total_amount, self.invoice_payload
+            Space.id_, Space.from_user, Space.currency, Space.total_amount, Space.invoice_payload
         )
         b = PreCheckoutQuery(
-            self.id_, self.from_user, self.currency, self.total_amount, self.invoice_payload
+            Space.id_, Space.from_user, Space.currency, Space.total_amount, Space.invoice_payload
         )
-        c = PreCheckoutQuery(self.id_, None, "", 0, "")
+        c = PreCheckoutQuery(Space.id_, None, "", 0, "")
         d = PreCheckoutQuery(
-            0, self.from_user, self.currency, self.total_amount, self.invoice_payload
+            0, Space.from_user, Space.currency, Space.total_amount, Space.invoice_payload
         )
-        e = Update(self.id_)
+        e = Update(Space.id_)
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_proximityalerttriggered.py b/tests/test_proximityalerttriggered.py
index 0d1fd0ff777..6285d2de55f 100644
--- a/tests/test_proximityalerttriggered.py
+++ b/tests/test_proximityalerttriggered.py
@@ -21,20 +21,22 @@
 from telegram import BotCommand, ProximityAlertTriggered, User
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def proximity_alert_triggered():
     return ProximityAlertTriggered(
-        traveler=TestProximityAlertTriggered.traveler,
-        watcher=TestProximityAlertTriggered.watcher,
-        distance=TestProximityAlertTriggered.distance,
+        Space.traveler,
+        Space.watcher,
+        Space.distance,
     )
 
 
-class TestProximityAlertTriggered:
+class Space:
     traveler = User(1, "foo", False)
     watcher = User(2, "bar", False)
     distance = 42
 
+
+class TestProximityAlertTriggeredNoReq:
     def test_slot_behaviour(self, proximity_alert_triggered, mro_slots):
         inst = proximity_alert_triggered
         for attr in inst.__slots__:
@@ -43,18 +45,18 @@ def test_slot_behaviour(self, proximity_alert_triggered, mro_slots):
 
     def test_de_json(self, bot):
         json_dict = {
-            "traveler": self.traveler.to_dict(),
-            "watcher": self.watcher.to_dict(),
-            "distance": self.distance,
+            "traveler": Space.traveler.to_dict(),
+            "watcher": Space.watcher.to_dict(),
+            "distance": Space.distance,
         }
         proximity_alert_triggered = ProximityAlertTriggered.de_json(json_dict, bot)
         assert proximity_alert_triggered.api_kwargs == {}
 
-        assert proximity_alert_triggered.traveler == self.traveler
-        assert proximity_alert_triggered.traveler.first_name == self.traveler.first_name
-        assert proximity_alert_triggered.watcher == self.watcher
-        assert proximity_alert_triggered.watcher.first_name == self.watcher.first_name
-        assert proximity_alert_triggered.distance == self.distance
+        assert proximity_alert_triggered.traveler == Space.traveler
+        assert proximity_alert_triggered.traveler.first_name == Space.traveler.first_name
+        assert proximity_alert_triggered.watcher == Space.watcher
+        assert proximity_alert_triggered.watcher.first_name == Space.watcher.first_name
+        assert proximity_alert_triggered.distance == Space.distance
 
     def test_to_dict(self, proximity_alert_triggered):
         proximity_alert_triggered_dict = proximity_alert_triggered.to_dict()
diff --git a/tests/test_ratelimiter.py b/tests/test_ratelimiter.py
index 39c4c731fc9..9c95855e6d7 100644
--- a/tests/test_ratelimiter.py
+++ b/tests/test_ratelimiter.py
@@ -36,9 +36,7 @@
 from telegram.error import RetryAfter
 from telegram.ext import AIORateLimiter, BaseRateLimiter, Defaults, ExtBot
 from telegram.request import BaseRequest, RequestData
-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))
+from tests.conftest import TEST_WITH_OPT_DEPS
 
 
 @pytest.mark.skipif(
diff --git a/tests/test_replykeyboardmarkup.py b/tests/test_replykeyboardmarkup.py
index 56b1366e016..004272c12fa 100644
--- a/tests/test_replykeyboardmarkup.py
+++ b/tests/test_replykeyboardmarkup.py
@@ -22,44 +22,30 @@
 from telegram import InlineKeyboardMarkup, KeyboardButton, ReplyKeyboardMarkup
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def reply_keyboard_markup():
     return ReplyKeyboardMarkup(
-        TestReplyKeyboardMarkup.keyboard,
-        resize_keyboard=TestReplyKeyboardMarkup.resize_keyboard,
-        one_time_keyboard=TestReplyKeyboardMarkup.one_time_keyboard,
-        selective=TestReplyKeyboardMarkup.selective,
+        Space.keyboard,
+        resize_keyboard=Space.resize_keyboard,
+        one_time_keyboard=Space.one_time_keyboard,
+        selective=Space.selective,
     )
 
 
-class TestReplyKeyboardMarkup:
+class Space:
     keyboard = [[KeyboardButton("button1"), KeyboardButton("button2")]]
     resize_keyboard = True
     one_time_keyboard = True
     selective = True
 
+
+class TestReplyKeyboardMarkupNoReq:
     def test_slot_behaviour(self, reply_keyboard_markup, mro_slots):
         inst = reply_keyboard_markup
         for attr in inst.__slots__:
             assert getattr(inst, attr, "err") != "err", f"got extra slot '{attr}'"
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
-    @pytest.mark.flaky(3, 1)
-    async def test_send_message_with_reply_keyboard_markup(
-        self, bot, chat_id, reply_keyboard_markup
-    ):
-        message = await bot.send_message(chat_id, "Text", reply_markup=reply_keyboard_markup)
-
-        assert message.text == "Text"
-
-    @pytest.mark.flaky(3, 1)
-    async def test_send_message_with_data_markup(self, bot, chat_id):
-        message = await bot.send_message(
-            chat_id, "text 2", reply_markup={"keyboard": [["1", "2"]]}
-        )
-
-        assert message.text == "text 2"
-
     def test_from_button(self):
         reply_keyboard_markup = ReplyKeyboardMarkup.from_button(
             KeyboardButton(text="button1")
@@ -100,9 +86,9 @@ def test_expected_values(self, reply_keyboard_markup):
         assert all(isinstance(row, tuple) for row in reply_keyboard_markup.keyboard)
         assert isinstance(reply_keyboard_markup.keyboard[0][0], KeyboardButton)
         assert isinstance(reply_keyboard_markup.keyboard[0][1], KeyboardButton)
-        assert reply_keyboard_markup.resize_keyboard == self.resize_keyboard
-        assert reply_keyboard_markup.one_time_keyboard == self.one_time_keyboard
-        assert reply_keyboard_markup.selective == self.selective
+        assert reply_keyboard_markup.resize_keyboard == Space.resize_keyboard
+        assert reply_keyboard_markup.one_time_keyboard == Space.one_time_keyboard
+        assert reply_keyboard_markup.selective == Space.selective
 
     def test_wrong_keyboard_inputs(self):
         with pytest.raises(ValueError):
@@ -159,3 +145,19 @@ def test_equality(self):
 
         assert a != f
         assert hash(a) != hash(f)
+
+
+class TestReplyKeyboardMarkupReq:
+    async def test_send_message_with_reply_keyboard_markup(
+        self, bot, chat_id, reply_keyboard_markup
+    ):
+        message = await bot.send_message(chat_id, "Text", reply_markup=reply_keyboard_markup)
+
+        assert message.text == "Text"
+
+    async def test_send_message_with_data_markup(self, bot, chat_id):
+        message = await bot.send_message(
+            chat_id, "text 2", reply_markup={"keyboard": [["1", "2"]]}
+        )
+
+        assert message.text == "text 2"
diff --git a/tests/test_replykeyboardremove.py b/tests/test_replykeyboardremove.py
index 91937d05e33..08244b9ce42 100644
--- a/tests/test_replykeyboardremove.py
+++ b/tests/test_replykeyboardremove.py
@@ -21,32 +21,26 @@
 from telegram import ReplyKeyboardRemove
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def reply_keyboard_remove():
-    return ReplyKeyboardRemove(selective=TestReplyKeyboardRemove.selective)
+    return ReplyKeyboardRemove(selective=Space.selective)
 
 
-class TestReplyKeyboardRemove:
+class Space:
     remove_keyboard = True
     selective = True
 
+
+class TestReplyKeyboardRemoveNoReq:
     def test_slot_behaviour(self, reply_keyboard_remove, mro_slots):
         inst = reply_keyboard_remove
         for attr in inst.__slots__:
             assert getattr(inst, attr, "err") != "err", f"got extra slot '{attr}'"
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
-    @pytest.mark.flaky(3, 1)
-    async def test_send_message_with_reply_keyboard_remove(
-        self, bot, chat_id, reply_keyboard_remove
-    ):
-        message = await bot.send_message(chat_id, "Text", reply_markup=reply_keyboard_remove)
-
-        assert message.text == "Text"
-
     def test_expected_values(self, reply_keyboard_remove):
-        assert reply_keyboard_remove.remove_keyboard == self.remove_keyboard
-        assert reply_keyboard_remove.selective == self.selective
+        assert reply_keyboard_remove.remove_keyboard == Space.remove_keyboard
+        assert reply_keyboard_remove.selective == Space.selective
 
     def test_to_dict(self, reply_keyboard_remove):
         reply_keyboard_remove_dict = reply_keyboard_remove.to_dict()
@@ -55,3 +49,11 @@ def test_to_dict(self, reply_keyboard_remove):
             reply_keyboard_remove_dict["remove_keyboard"] == reply_keyboard_remove.remove_keyboard
         )
         assert reply_keyboard_remove_dict["selective"] == reply_keyboard_remove.selective
+
+
+class TestReplyKeyboardRemoveReq:
+    async def test_send_message_with_reply_keyboard_remove(
+        self, bot, chat_id, reply_keyboard_remove
+    ):
+        message = await bot.send_message(chat_id, "Text", reply_markup=reply_keyboard_remove)
+        assert message.text == "Text"
diff --git a/tests/test_request.py b/tests/test_request.py
index 7ab655586cc..22d0e01bbe3 100644
--- a/tests/test_request.py
+++ b/tests/test_request.py
@@ -20,7 +20,6 @@
 implementations for BaseRequest and we want to test HTTPXRequest anyway."""
 import asyncio
 import json
-import os
 from collections import defaultdict
 from dataclasses import dataclass
 from http import HTTPStatus
@@ -43,7 +42,7 @@
 )
 from telegram.request._httpxrequest import HTTPXRequest
 
-from .auxil.object_conversions import env_var_2_bool
+from .conftest import TEST_WITH_OPT_DEPS
 
 # We only need the first fixture, but it uses the others, so pytest needs us to import them as well
 from .test_requestdata import (  # noqa: F401
@@ -72,9 +71,6 @@ async def httpx_request():
         yield rq
 
 
-TEST_WITH_OPT_DEPS = env_var_2_bool(os.getenv("TEST_WITH_OPT_DEPS", True))
-
-
 @pytest.mark.skipif(
     TEST_WITH_OPT_DEPS, reason="Only relevant if the optional dependency is not installed"
 )
@@ -84,7 +80,7 @@ async def test_init(self, bot):
             HTTPXRequest(proxy_url="socks5://foo")
 
 
-class TestRequest:
+class TestRequestNoReq:
     test_flag = None
 
     @pytest.fixture(autouse=True)
@@ -325,7 +321,7 @@ async def make_assertion(*args, **kwargs):
         assert self.test_flag == (1, 2, 3, 4)
 
 
-class TestHTTPXRequest:
+class TestHTTPXRequestNoReq:
     test_flag = None
 
     @pytest.fixture(autouse=True)
@@ -567,7 +563,8 @@ async def request(_, **kwargs):
                     httpx_request.do_request(method="GET", url="URL"),
                 )
 
-    @pytest.mark.flaky(3, 1)
+
+class TestHTTPXRequestReq:
     async def test_do_request_wait_for_pool(self, monkeypatch, httpx_request):
         """The pool logic is buried rather deeply in httpxcore, so we make actual requests here
         instead of mocking"""
diff --git a/tests/test_requestdata.py b/tests/test_requestdata.py
index a814d3ed5a4..908cda5db7b 100644
--- a/tests/test_requestdata.py
+++ b/tests/test_requestdata.py
@@ -108,28 +108,28 @@ def file_rqs(file_params) -> RequestData:
     )
 
 
-@pytest.fixture()
+@pytest.fixture(scope="module")
 def mixed_params(file_params, simple_params) -> Dict[str, Any]:
     both = file_params.copy()
     both.update(simple_params)
     return both
 
 
-@pytest.fixture()
+@pytest.fixture(scope="module")
 def mixed_jsons(file_jsons, simple_jsons) -> Dict[str, Any]:
     both = file_jsons.copy()
     both.update(simple_jsons)
     return both
 
 
-@pytest.fixture()
+@pytest.fixture(scope="module")
 def mixed_rqs(mixed_params) -> RequestData:
     return RequestData(
         [RequestParameter.from_input(key, value) for key, value in mixed_params.items()]
     )
 
 
-class TestRequestData:
+class TestRequestDataNoReq:
     def test_slot_behaviour(self, simple_rqs, mro_slots):
         for attr in simple_rqs.__slots__:
             assert getattr(simple_rqs, attr, "err") != "err", f"got extra slot '{attr}'"
diff --git a/tests/test_requestparameter.py b/tests/test_requestparameter.py
index f5add3dbfba..49f333a0261 100644
--- a/tests/test_requestparameter.py
+++ b/tests/test_requestparameter.py
@@ -26,7 +26,7 @@
 from tests.conftest import data_file
 
 
-class TestRequestParameter:
+class TestRequestParameterNoReq:
     def test_init(self):
         request_parameter = RequestParameter("name", "value", [1, 2])
         assert request_parameter.name == "name"
diff --git a/tests/test_sentwebappmessage.py b/tests/test_sentwebappmessage.py
index 2d3d93da6f7..d513e90e9d8 100644
--- a/tests/test_sentwebappmessage.py
+++ b/tests/test_sentwebappmessage.py
@@ -22,16 +22,16 @@
 from telegram import SentWebAppMessage
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def sent_web_app_message():
-    return SentWebAppMessage(
-        inline_message_id=TestSentWebAppMessage.inline_message_id,
-    )
+    return SentWebAppMessage(inline_message_id=Space.inline_message_id)
 
 
-class TestSentWebAppMessage:
+class Space:
     inline_message_id = "123"
 
+
+class TestSentWebAppMessageNoReq:
     def test_slot_behaviour(self, sent_web_app_message, mro_slots):
         inst = sent_web_app_message
         for attr in inst.__slots__:
@@ -42,17 +42,17 @@ def test_to_dict(self, sent_web_app_message):
         sent_web_app_message_dict = sent_web_app_message.to_dict()
 
         assert isinstance(sent_web_app_message_dict, dict)
-        assert sent_web_app_message_dict["inline_message_id"] == self.inline_message_id
+        assert sent_web_app_message_dict["inline_message_id"] == Space.inline_message_id
 
     def test_de_json(self, bot):
-        data = {"inline_message_id": self.inline_message_id}
+        data = {"inline_message_id": Space.inline_message_id}
         m = SentWebAppMessage.de_json(data, None)
         assert m.api_kwargs == {}
-        assert m.inline_message_id == self.inline_message_id
+        assert m.inline_message_id == Space.inline_message_id
 
     def test_equality(self):
-        a = SentWebAppMessage(self.inline_message_id)
-        b = SentWebAppMessage(self.inline_message_id)
+        a = SentWebAppMessage(Space.inline_message_id)
+        b = SentWebAppMessage(Space.inline_message_id)
         c = SentWebAppMessage("")
         d = SentWebAppMessage("not_inline_message_id")
 
diff --git a/tests/test_shippingaddress.py b/tests/test_shippingaddress.py
index 1552ebc88dd..5c1db72228b 100644
--- a/tests/test_shippingaddress.py
+++ b/tests/test_shippingaddress.py
@@ -21,19 +21,19 @@
 from telegram import ShippingAddress
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def shipping_address():
     return ShippingAddress(
-        TestShippingAddress.country_code,
-        TestShippingAddress.state,
-        TestShippingAddress.city,
-        TestShippingAddress.street_line1,
-        TestShippingAddress.street_line2,
-        TestShippingAddress.post_code,
+        Space.country_code,
+        Space.state,
+        Space.city,
+        Space.street_line1,
+        Space.street_line2,
+        Space.post_code,
     )
 
 
-class TestShippingAddress:
+class Space:
     country_code = "GB"
     state = "state"
     city = "London"
@@ -41,6 +41,8 @@ class TestShippingAddress:
     street_line2 = "street_line2"
     post_code = "WC1"
 
+
+class TestShippingAddressNoReq:
     def test_slot_behaviour(self, shipping_address, mro_slots):
         inst = shipping_address
         for attr in inst.__slots__:
@@ -49,22 +51,22 @@ def test_slot_behaviour(self, shipping_address, mro_slots):
 
     def test_de_json(self, bot):
         json_dict = {
-            "country_code": self.country_code,
-            "state": self.state,
-            "city": self.city,
-            "street_line1": self.street_line1,
-            "street_line2": self.street_line2,
-            "post_code": self.post_code,
+            "country_code": Space.country_code,
+            "state": Space.state,
+            "city": Space.city,
+            "street_line1": Space.street_line1,
+            "street_line2": Space.street_line2,
+            "post_code": Space.post_code,
         }
         shipping_address = ShippingAddress.de_json(json_dict, bot)
         assert shipping_address.api_kwargs == {}
 
-        assert shipping_address.country_code == self.country_code
-        assert shipping_address.state == self.state
-        assert shipping_address.city == self.city
-        assert shipping_address.street_line1 == self.street_line1
-        assert shipping_address.street_line2 == self.street_line2
-        assert shipping_address.post_code == self.post_code
+        assert shipping_address.country_code == Space.country_code
+        assert shipping_address.state == Space.state
+        assert shipping_address.city == Space.city
+        assert shipping_address.street_line1 == Space.street_line1
+        assert shipping_address.street_line2 == Space.street_line2
+        assert shipping_address.post_code == Space.post_code
 
     def test_to_dict(self, shipping_address):
         shipping_address_dict = shipping_address.to_dict()
@@ -79,38 +81,48 @@ def test_to_dict(self, shipping_address):
 
     def test_equality(self):
         a = ShippingAddress(
-            self.country_code,
-            self.state,
-            self.city,
-            self.street_line1,
-            self.street_line2,
-            self.post_code,
+            Space.country_code,
+            Space.state,
+            Space.city,
+            Space.street_line1,
+            Space.street_line2,
+            Space.post_code,
         )
         b = ShippingAddress(
-            self.country_code,
-            self.state,
-            self.city,
-            self.street_line1,
-            self.street_line2,
-            self.post_code,
+            Space.country_code,
+            Space.state,
+            Space.city,
+            Space.street_line1,
+            Space.street_line2,
+            Space.post_code,
         )
         d = ShippingAddress(
-            "", self.state, self.city, self.street_line1, self.street_line2, self.post_code
+            "", Space.state, Space.city, Space.street_line1, Space.street_line2, Space.post_code
         )
         d2 = ShippingAddress(
-            self.country_code, "", self.city, self.street_line1, self.street_line2, self.post_code
+            Space.country_code,
+            "",
+            Space.city,
+            Space.street_line1,
+            Space.street_line2,
+            Space.post_code,
         )
         d3 = ShippingAddress(
-            self.country_code, self.state, "", self.street_line1, self.street_line2, self.post_code
+            Space.country_code,
+            Space.state,
+            "",
+            Space.street_line1,
+            Space.street_line2,
+            Space.post_code,
         )
         d4 = ShippingAddress(
-            self.country_code, self.state, self.city, "", self.street_line2, self.post_code
+            Space.country_code, Space.state, Space.city, "", Space.street_line2, Space.post_code
         )
         d5 = ShippingAddress(
-            self.country_code, self.state, self.city, self.street_line1, "", self.post_code
+            Space.country_code, Space.state, Space.city, Space.street_line1, "", Space.post_code
         )
         d6 = ShippingAddress(
-            self.country_code, self.state, self.city, self.street_line1, self.street_line2, ""
+            Space.country_code, Space.state, Space.city, Space.street_line1, Space.street_line2, ""
         )
 
         assert a == b
diff --git a/tests/test_shippingoption.py b/tests/test_shippingoption.py
index 663a5ad2712..913228dc551 100644
--- a/tests/test_shippingoption.py
+++ b/tests/test_shippingoption.py
@@ -21,18 +21,18 @@
 from telegram import LabeledPrice, ShippingOption, Voice
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def shipping_option():
-    return ShippingOption(
-        TestShippingOption.id_, TestShippingOption.title, TestShippingOption.prices
-    )
+    return ShippingOption(Space.id_, Space.title, Space.prices)
 
 
-class TestShippingOption:
+class Space:
     id_ = "id"
     title = "title"
     prices = [LabeledPrice("Fish Container", 100), LabeledPrice("Premium Fish Container", 1000)]
 
+
+class TestShippingOptionNoReq:
     def test_slot_behaviour(self, shipping_option, mro_slots):
         inst = shipping_option
         for attr in inst.__slots__:
@@ -40,9 +40,9 @@ def test_slot_behaviour(self, shipping_option, mro_slots):
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_expected_values(self, shipping_option):
-        assert shipping_option.id == self.id_
-        assert shipping_option.title == self.title
-        assert shipping_option.prices == tuple(self.prices)
+        assert shipping_option.id == Space.id_
+        assert shipping_option.title == Space.title
+        assert shipping_option.prices == tuple(Space.prices)
 
     def test_to_dict(self, shipping_option):
         shipping_option_dict = shipping_option.to_dict()
@@ -54,11 +54,11 @@ def test_to_dict(self, shipping_option):
         assert shipping_option_dict["prices"][1] == shipping_option.prices[1].to_dict()
 
     def test_equality(self):
-        a = ShippingOption(self.id_, self.title, self.prices)
-        b = ShippingOption(self.id_, self.title, self.prices)
-        c = ShippingOption(self.id_, "", [])
-        d = ShippingOption(0, self.title, self.prices)
-        e = Voice(self.id_, "someid", 0)
+        a = ShippingOption(Space.id_, Space.title, Space.prices)
+        b = ShippingOption(Space.id_, Space.title, Space.prices)
+        c = ShippingOption(Space.id_, "", [])
+        d = ShippingOption(0, Space.title, Space.prices)
+        e = Voice(Space.id_, "someid", 0)
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_shippingquery.py b/tests/test_shippingquery.py
index e6c857083aa..8f988351af4 100644
--- a/tests/test_shippingquery.py
+++ b/tests/test_shippingquery.py
@@ -27,24 +27,21 @@
 )
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def shipping_query(bot):
-    sq = ShippingQuery(
-        TestShippingQuery.id_,
-        TestShippingQuery.from_user,
-        TestShippingQuery.invoice_payload,
-        TestShippingQuery.shipping_address,
-    )
+    sq = ShippingQuery(Space.id_, Space.from_user, Space.invoice_payload, Space.shipping_address)
     sq.set_bot(bot)
     return sq
 
 
-class TestShippingQuery:
+class Space:
     id_ = "5"
     invoice_payload = "invoice_payload"
     from_user = User(0, "", False)
     shipping_address = ShippingAddress("GB", "", "London", "12 Grimmauld Place", "", "WC1")
 
+
+class TestShippingQueryNoReq:
     def test_slot_behaviour(self, shipping_query, mro_slots):
         inst = shipping_query
         for attr in inst.__slots__:
@@ -53,18 +50,18 @@ def test_slot_behaviour(self, shipping_query, mro_slots):
 
     def test_de_json(self, bot):
         json_dict = {
-            "id": TestShippingQuery.id_,
-            "invoice_payload": TestShippingQuery.invoice_payload,
-            "from": TestShippingQuery.from_user.to_dict(),
-            "shipping_address": TestShippingQuery.shipping_address.to_dict(),
+            "id": Space.id_,
+            "invoice_payload": Space.invoice_payload,
+            "from": Space.from_user.to_dict(),
+            "shipping_address": Space.shipping_address.to_dict(),
         }
         shipping_query = ShippingQuery.de_json(json_dict, bot)
         assert shipping_query.api_kwargs == {}
 
-        assert shipping_query.id == self.id_
-        assert shipping_query.invoice_payload == self.invoice_payload
-        assert shipping_query.from_user == self.from_user
-        assert shipping_query.shipping_address == self.shipping_address
+        assert shipping_query.id == Space.id_
+        assert shipping_query.invoice_payload == Space.invoice_payload
+        assert shipping_query.from_user == Space.from_user
+        assert shipping_query.shipping_address == Space.shipping_address
         assert shipping_query.get_bot() is bot
 
     def test_to_dict(self, shipping_query):
@@ -92,11 +89,15 @@ async def make_assertion(*_, **kwargs):
         assert await shipping_query.answer(ok=True)
 
     def test_equality(self):
-        a = ShippingQuery(self.id_, self.from_user, self.invoice_payload, self.shipping_address)
-        b = ShippingQuery(self.id_, self.from_user, self.invoice_payload, self.shipping_address)
-        c = ShippingQuery(self.id_, None, "", None)
-        d = ShippingQuery(0, self.from_user, self.invoice_payload, self.shipping_address)
-        e = Update(self.id_)
+        a = ShippingQuery(
+            Space.id_, Space.from_user, Space.invoice_payload, Space.shipping_address
+        )
+        b = ShippingQuery(
+            Space.id_, Space.from_user, Space.invoice_payload, Space.shipping_address
+        )
+        c = ShippingQuery(Space.id_, None, "", None)
+        d = ShippingQuery(0, Space.from_user, Space.invoice_payload, Space.shipping_address)
+        e = Update(Space.id_)
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_sticker.py b/tests/test_sticker.py
index fe96bd6ac55..78882c3f28b 100644
--- a/tests/test_sticker.py
+++ b/tests/test_sticker.py
@@ -39,7 +39,7 @@ def sticker_file():
         yield file
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 async def sticker(bot, chat_id):
     with data_file("telegram.webp").open("rb") as f:
         return (await bot.send_sticker(chat_id, sticker=f, read_timeout=50)).sticker
@@ -51,7 +51,7 @@ def animated_sticker_file():
         yield f
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 async def animated_sticker(bot, chat_id):
     with data_file("telegram_animated_sticker.tgs").open("rb") as f:
         return (await bot.send_sticker(chat_id, sticker=f, read_timeout=50)).sticker
@@ -63,13 +63,13 @@ def video_sticker_file():
         yield f
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def video_sticker(bot, chat_id):
     with data_file("telegram_video_sticker.webm").open("rb") as f:
         return bot.send_sticker(chat_id, sticker=f, timeout=50).sticker
 
 
-class TestSticker:
+class StickerSpace:
     # sticker_file_url = 'https://python-telegram-bot.org/static/testfiles/telegram.webp'
     # Serving sticker from gh since our server sends wrong content_type
     sticker_file_url = (
@@ -94,6 +94,8 @@ class TestSticker:
 
     premium_animation = File("this_is_an_id", "this_is_an_unique_id")
 
+
+class TestStickerNoReq:
     def test_slot_behaviour(self, sticker, mro_slots, recwarn):
         for attr in sticker.__slots__:
             assert getattr(sticker, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -113,19 +115,158 @@ def test_creation(self, sticker):
         assert sticker.thumb.file_unique_id != ""
 
     def test_expected_values(self, sticker):
-        assert sticker.width == self.width
-        assert sticker.height == self.height
-        assert sticker.is_animated == self.is_animated
-        assert sticker.is_video == self.is_video
-        assert sticker.file_size == self.file_size
-        assert sticker.thumb.width == self.thumb_width
-        assert sticker.thumb.height == self.thumb_height
-        assert sticker.thumb.file_size == self.thumb_file_size
-        assert sticker.type == self.type
+        assert sticker.width == StickerSpace.width
+        assert sticker.height == StickerSpace.height
+        assert sticker.is_animated == StickerSpace.is_animated
+        assert sticker.is_video == StickerSpace.is_video
+        assert sticker.file_size == StickerSpace.file_size
+        assert sticker.thumb.width == StickerSpace.thumb_width
+        assert sticker.thumb.height == StickerSpace.thumb_height
+        assert sticker.thumb.file_size == StickerSpace.thumb_file_size
+        assert sticker.type == StickerSpace.type
         # we need to be a premium TG user to send a premium sticker, so the below is not tested
-        # assert sticker.premium_animation == self.premium_animation
+        # assert sticker.premium_animation == StickerSpace.premium_animation
+
+    def test_de_json(self, bot, sticker):
+        json_dict = {
+            "file_id": StickerSpace.sticker_file_id,
+            "file_unique_id": StickerSpace.sticker_file_unique_id,
+            "width": StickerSpace.width,
+            "height": StickerSpace.height,
+            "is_animated": StickerSpace.is_animated,
+            "is_video": StickerSpace.is_video,
+            "thumb": sticker.thumb.to_dict(),
+            "emoji": StickerSpace.emoji,
+            "file_size": StickerSpace.file_size,
+            "premium_animation": StickerSpace.premium_animation.to_dict(),
+            "type": StickerSpace.type,
+            "custom_emoji_id": StickerSpace.custom_emoji_id,
+        }
+        json_sticker = Sticker.de_json(json_dict, bot)
+        assert json_sticker.api_kwargs == {}
+
+        assert json_sticker.file_id == StickerSpace.sticker_file_id
+        assert json_sticker.file_unique_id == StickerSpace.sticker_file_unique_id
+        assert json_sticker.width == StickerSpace.width
+        assert json_sticker.height == StickerSpace.height
+        assert json_sticker.is_animated == StickerSpace.is_animated
+        assert json_sticker.is_video == StickerSpace.is_video
+        assert json_sticker.emoji == StickerSpace.emoji
+        assert json_sticker.file_size == StickerSpace.file_size
+        assert json_sticker.thumb == sticker.thumb
+        assert json_sticker.premium_animation == StickerSpace.premium_animation
+        assert json_sticker.type == StickerSpace.type
+        assert json_sticker.custom_emoji_id == StickerSpace.custom_emoji_id
+
+    async def test_send_with_sticker(self, monkeypatch, bot, chat_id, sticker):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            return request_data.json_parameters["sticker"] == sticker.file_id
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+        message = await bot.send_sticker(sticker=sticker, chat_id=chat_id)
+        assert message
+
+    @pytest.mark.parametrize("local_mode", [True, False])
+    async def test_send_sticker_local_files(self, monkeypatch, bot, chat_id, local_mode):
+        try:
+            bot._local_mode = local_mode
+            # For just test that the correct paths are passed as we have no local bot API set up
+            test_flag = False
+            file = data_file("telegram.jpg")
+            expected = file.as_uri()
+
+            async def make_assertion(_, data, *args, **kwargs):
+                nonlocal test_flag
+                if local_mode:
+                    test_flag = data.get("sticker") == expected
+                else:
+                    test_flag = isinstance(data.get("sticker"), InputFile)
+
+            monkeypatch.setattr(bot, "_post", make_assertion)
+            await bot.send_sticker(chat_id, file)
+            assert test_flag
+            monkeypatch.delattr(bot, "_post")
+        finally:
+            bot._local_mode = False
+
+    def test_to_dict(self, sticker):
+        sticker_dict = sticker.to_dict()
+
+        assert isinstance(sticker_dict, dict)
+        assert sticker_dict["file_id"] == sticker.file_id
+        assert sticker_dict["file_unique_id"] == sticker.file_unique_id
+        assert sticker_dict["width"] == sticker.width
+        assert sticker_dict["height"] == sticker.height
+        assert sticker_dict["is_animated"] == sticker.is_animated
+        assert sticker_dict["is_video"] == sticker.is_video
+        assert sticker_dict["file_size"] == sticker.file_size
+        assert sticker_dict["thumb"] == sticker.thumb.to_dict()
+        assert sticker_dict["type"] == sticker.type
 
-    @pytest.mark.flaky(3, 1)
+    async def test_error_without_required_args(self, bot, chat_id):
+        with pytest.raises(TypeError):
+            await bot.send_sticker(chat_id)
+
+    def test_equality(self, sticker):
+        a = Sticker(
+            sticker.file_id,
+            sticker.file_unique_id,
+            StickerSpace.width,
+            StickerSpace.height,
+            StickerSpace.is_animated,
+            StickerSpace.is_video,
+            StickerSpace.type,
+        )
+        b = Sticker(
+            "",
+            sticker.file_unique_id,
+            StickerSpace.width,
+            StickerSpace.height,
+            StickerSpace.is_animated,
+            StickerSpace.is_video,
+            StickerSpace.type,
+        )
+        c = Sticker(
+            sticker.file_id,
+            sticker.file_unique_id,
+            0,
+            0,
+            False,
+            True,
+            StickerSpace.type,
+        )
+        d = Sticker(
+            "",
+            "",
+            StickerSpace.width,
+            StickerSpace.height,
+            StickerSpace.is_animated,
+            StickerSpace.is_video,
+            StickerSpace.type,
+        )
+        e = PhotoSize(
+            sticker.file_id,
+            sticker.file_unique_id,
+            StickerSpace.width,
+            StickerSpace.height,
+            StickerSpace.is_animated,
+        )
+
+        assert a == b
+        assert hash(a) == hash(b)
+        assert a is not b
+
+        assert a == c
+        assert hash(a) == hash(c)
+
+        assert a != d
+        assert hash(a) != hash(d)
+
+        assert a != e
+        assert hash(a) != hash(e)
+
+
+class TestStickerReq:
     async def test_send_all_args(self, bot, chat_id, sticker_file, sticker):
         message = await bot.send_sticker(
             chat_id, sticker=sticker_file, disable_notification=False, protect_content=True
@@ -155,7 +296,6 @@ async def test_send_all_args(self, bot, chat_id, sticker_file, sticker):
         assert message.sticker.thumb.height == sticker.thumb.height
         assert message.sticker.thumb.file_size == sticker.thumb.file_size
 
-    @pytest.mark.flaky(3, 1)
     async def test_get_and_download(self, bot, sticker):
         path = Path("telegram.webp")
         if path.is_file():
@@ -172,22 +312,19 @@ async def test_get_and_download(self, bot, sticker):
 
         assert path.is_file()
 
-    @pytest.mark.flaky(3, 1)
     async def test_resend(self, bot, chat_id, sticker):
         message = await bot.send_sticker(chat_id=chat_id, sticker=sticker.file_id)
 
         assert message.sticker == sticker
 
-    @pytest.mark.flaky(3, 1)
     async def test_send_on_server_emoji(self, bot, chat_id):
         server_file_id = "CAADAQADHAADyIsGAAFZfq1bphjqlgI"
         message = await bot.send_sticker(chat_id=chat_id, sticker=server_file_id)
         sticker = message.sticker
-        assert sticker.emoji == self.emoji
+        assert sticker.emoji == StickerSpace.emoji
 
-    @pytest.mark.flaky(3, 1)
     async def test_send_from_url(self, bot, chat_id):
-        message = await bot.send_sticker(chat_id=chat_id, sticker=self.sticker_file_url)
+        message = await bot.send_sticker(chat_id=chat_id, sticker=StickerSpace.sticker_file_url)
         sticker = message.sticker
 
         assert isinstance(message.sticker, Sticker)
@@ -211,69 +348,6 @@ async def test_send_from_url(self, bot, chat_id):
         assert message.sticker.thumb.height == sticker.thumb.height
         assert message.sticker.thumb.file_size == sticker.thumb.file_size
 
-    def test_de_json(self, bot, sticker):
-        json_dict = {
-            "file_id": self.sticker_file_id,
-            "file_unique_id": self.sticker_file_unique_id,
-            "width": self.width,
-            "height": self.height,
-            "is_animated": self.is_animated,
-            "is_video": self.is_video,
-            "thumb": sticker.thumb.to_dict(),
-            "emoji": self.emoji,
-            "file_size": self.file_size,
-            "premium_animation": self.premium_animation.to_dict(),
-            "type": self.type,
-            "custom_emoji_id": self.custom_emoji_id,
-        }
-        json_sticker = Sticker.de_json(json_dict, bot)
-        assert json_sticker.api_kwargs == {}
-
-        assert json_sticker.file_id == self.sticker_file_id
-        assert json_sticker.file_unique_id == self.sticker_file_unique_id
-        assert json_sticker.width == self.width
-        assert json_sticker.height == self.height
-        assert json_sticker.is_animated == self.is_animated
-        assert json_sticker.is_video == self.is_video
-        assert json_sticker.emoji == self.emoji
-        assert json_sticker.file_size == self.file_size
-        assert json_sticker.thumb == sticker.thumb
-        assert json_sticker.premium_animation == self.premium_animation
-        assert json_sticker.type == self.type
-        assert json_sticker.custom_emoji_id == self.custom_emoji_id
-
-    async def test_send_with_sticker(self, monkeypatch, bot, chat_id, sticker):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            return request_data.json_parameters["sticker"] == sticker.file_id
-
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-        message = await bot.send_sticker(sticker=sticker, chat_id=chat_id)
-        assert message
-
-    @pytest.mark.parametrize("local_mode", [True, False])
-    async def test_send_sticker_local_files(self, monkeypatch, bot, chat_id, local_mode):
-        try:
-            bot._local_mode = local_mode
-            # For just test that the correct paths are passed as we have no local bot API set up
-            test_flag = False
-            file = data_file("telegram.jpg")
-            expected = file.as_uri()
-
-            async def make_assertion(_, data, *args, **kwargs):
-                nonlocal test_flag
-                if local_mode:
-                    test_flag = data.get("sticker") == expected
-                else:
-                    test_flag = isinstance(data.get("sticker"), InputFile)
-
-            monkeypatch.setattr(bot, "_post", make_assertion)
-            await bot.send_sticker(chat_id, file)
-            assert test_flag
-            monkeypatch.delattr(bot, "_post")
-        finally:
-            bot._local_mode = False
-
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize(
         "default_bot,custom",
         [
@@ -307,43 +381,16 @@ async def test_send_sticker_default_allow_sending_without_reply(
                     chat_id, sticker, reply_to_message_id=reply_to_message.message_id
                 )
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
     async def test_send_sticker_default_protect_content(self, chat_id, sticker, default_bot):
-        protected = await default_bot.send_sticker(chat_id, sticker)
+        tasks = asyncio.gather(
+            default_bot.send_sticker(chat_id, sticker),
+            default_bot.send_sticker(chat_id, sticker, protect_content=False),
+        )
+        protected, unprotected = await tasks
         assert protected.has_protected_content
-        unprotected = await default_bot.send_sticker(chat_id, sticker, protect_content=False)
         assert not unprotected.has_protected_content
 
-    def test_to_dict(self, sticker):
-        sticker_dict = sticker.to_dict()
-
-        assert isinstance(sticker_dict, dict)
-        assert sticker_dict["file_id"] == sticker.file_id
-        assert sticker_dict["file_unique_id"] == sticker.file_unique_id
-        assert sticker_dict["width"] == sticker.width
-        assert sticker_dict["height"] == sticker.height
-        assert sticker_dict["is_animated"] == sticker.is_animated
-        assert sticker_dict["is_video"] == sticker.is_video
-        assert sticker_dict["file_size"] == sticker.file_size
-        assert sticker_dict["thumb"] == sticker.thumb.to_dict()
-        assert sticker_dict["type"] == sticker.type
-
-    @pytest.mark.flaky(3, 1)
-    async def test_error_send_empty_file(self, bot, chat_id):
-        with pytest.raises(TelegramError):
-            await bot.send_sticker(chat_id, open(os.devnull, "rb"))
-
-    @pytest.mark.flaky(3, 1)
-    async def test_error_send_empty_file_id(self, bot, chat_id):
-        with pytest.raises(TelegramError):
-            await bot.send_sticker(chat_id, "")
-
-    async def test_error_without_required_args(self, bot, chat_id):
-        with pytest.raises(TypeError):
-            await bot.send_sticker(chat_id)
-
-    @pytest.mark.flaky(3, 1)
     async def test_premium_animation(self, bot):
         # testing animation sucks a bit since we can't create a premium sticker. What we can do is
         # get a sticker set which includes a premium sticker and check that specific one.
@@ -361,7 +408,6 @@ async def test_premium_animation(self, bot):
         }
         assert premium_sticker.premium_animation.to_dict() == premium_sticker_dict
 
-    @pytest.mark.flaky(3, 1)
     async def test_custom_emoji(self, bot):
         # testing custom emoji stickers is as much of an annoyance as the premium animation, see
         # in test_premium_animation
@@ -371,63 +417,13 @@ async def test_custom_emoji(self, bot):
         custom_emoji_sticker = custom_emoji_set.stickers[0]
         assert custom_emoji_sticker.custom_emoji_id == "6046140249875156202"
 
-    def test_equality(self, sticker):
-        a = Sticker(
-            sticker.file_id,
-            sticker.file_unique_id,
-            self.width,
-            self.height,
-            self.is_animated,
-            self.is_video,
-            self.type,
-        )
-        b = Sticker(
-            "",
-            sticker.file_unique_id,
-            self.width,
-            self.height,
-            self.is_animated,
-            self.is_video,
-            self.type,
-        )
-        c = Sticker(
-            sticker.file_id,
-            sticker.file_unique_id,
-            0,
-            0,
-            False,
-            True,
-            self.type,
-        )
-        d = Sticker(
-            "",
-            "",
-            self.width,
-            self.height,
-            self.is_animated,
-            self.is_video,
-            self.type,
-        )
-        e = PhotoSize(
-            sticker.file_id,
-            sticker.file_unique_id,
-            self.width,
-            self.height,
-            self.is_animated,
-        )
-
-        assert a == b
-        assert hash(a) == hash(b)
-        assert a is not b
-
-        assert a == c
-        assert hash(a) == hash(c)
-
-        assert a != d
-        assert hash(a) != hash(d)
+    async def test_error_send_empty_file(self, bot, chat_id):
+        with pytest.raises(TelegramError):
+            await bot.send_sticker(chat_id, open(os.devnull, "rb"))
 
-        assert a != e
-        assert hash(a) != hash(e)
+    async def test_error_send_empty_file_id(self, bot, chat_id):
+        with pytest.raises(TelegramError):
+            await bot.send_sticker(chat_id, "")
 
 
 @pytest.fixture(scope="function")
@@ -478,7 +474,7 @@ def sticker_set_thumb_file():
         yield file
 
 
-class TestStickerSet:
+class SetSpace:
     title = "Test stickers"
     is_animated = True
     is_video = True
@@ -487,104 +483,30 @@ class TestStickerSet:
     sticker_type = Sticker.REGULAR
     contains_masks = True
 
+
+class TestStickerSetNoReq:
     def test_de_json(self, bot, sticker):
         name = f"test_by_{bot.username}"
         json_dict = {
             "name": name,
-            "title": self.title,
-            "is_animated": self.is_animated,
-            "is_video": self.is_video,
-            "stickers": [x.to_dict() for x in self.stickers],
+            "title": SetSpace.title,
+            "is_animated": SetSpace.is_animated,
+            "is_video": SetSpace.is_video,
+            "stickers": [x.to_dict() for x in SetSpace.stickers],
             "thumb": sticker.thumb.to_dict(),
-            "sticker_type": self.sticker_type,
-            "contains_masks": self.contains_masks,
+            "sticker_type": SetSpace.sticker_type,
+            "contains_masks": SetSpace.contains_masks,
         }
         sticker_set = StickerSet.de_json(json_dict, bot)
 
         assert sticker_set.name == name
-        assert sticker_set.title == self.title
-        assert sticker_set.is_animated == self.is_animated
-        assert sticker_set.is_video == self.is_video
-        assert sticker_set.stickers == tuple(self.stickers)
+        assert sticker_set.title == SetSpace.title
+        assert sticker_set.is_animated == SetSpace.is_animated
+        assert sticker_set.is_video == SetSpace.is_video
+        assert sticker_set.stickers == tuple(SetSpace.stickers)
         assert sticker_set.thumb == sticker.thumb
-        assert sticker_set.sticker_type == self.sticker_type
-        assert sticker_set.api_kwargs == {"contains_masks": self.contains_masks}
-
-    async def test_create_sticker_set(
-        self, bot, chat_id, sticker_file, animated_sticker_file, video_sticker_file
-    ):
-        """Creates the sticker set (if needed) which is required for tests. Make sure that this
-        test comes before the tests that actually use the sticker sets!
-        """
-        test_by = f"test_by_{bot.username}"
-        for sticker_set in [test_by, f"animated_{test_by}", f"video_{test_by}"]:
-            try:
-                await bot.get_sticker_set(sticker_set)
-            except BadRequest as e:
-                if not e.message == "Stickerset_invalid":
-                    raise e
-
-                if sticker_set.startswith(test_by):
-                    s = await bot.create_new_sticker_set(
-                        chat_id,
-                        name=sticker_set,
-                        title="Sticker Test",
-                        png_sticker=sticker_file,
-                        emojis="😄",
-                    )
-                    assert s
-                elif sticker_set.startswith("animated"):
-                    a = await bot.create_new_sticker_set(
-                        chat_id,
-                        name=sticker_set,
-                        title="Animated Test",
-                        tgs_sticker=animated_sticker_file,
-                        emojis="😄",
-                    )
-                    assert a
-                elif sticker_set.startswith("video"):
-                    v = await bot.create_new_sticker_set(
-                        chat_id,
-                        name=sticker_set,
-                        title="Video Test",
-                        webm_sticker=video_sticker_file,
-                        emojis="🤔",
-                    )
-                    assert v
-
-    @pytest.mark.flaky(3, 1)
-    async def test_bot_methods_1_png(self, bot, chat_id, sticker_file):
-        with data_file("telegram_sticker.png").open("rb") as f:
-            # chat_id was hardcoded as 95205500 but it stopped working for some reason
-            file = await bot.upload_sticker_file(chat_id, f)
-        assert file
-        assert await bot.add_sticker_to_set(
-            chat_id, f"test_by_{bot.username}", png_sticker=file.file_id, emojis="😄"
-        )
-        # Also test with file input and mask
-        assert await bot.add_sticker_to_set(
-            chat_id,
-            f"test_by_{bot.username}",
-            png_sticker=sticker_file,
-            emojis="😄",
-            mask_position=MaskPosition(MaskPosition.EYES, -1, 1, 2),
-        )
-
-    @pytest.mark.flaky(3, 1)
-    async def test_bot_methods_1_tgs(self, bot, chat_id):
-        assert await bot.add_sticker_to_set(
-            chat_id,
-            f"animated_test_by_{bot.username}",
-            tgs_sticker=data_file("telegram_animated_sticker.tgs").open("rb"),
-            emojis="😄",
-        )
-
-    @pytest.mark.flaky(3, 1)
-    async def test_bot_methods_1_webm(self, bot, chat_id):
-        with data_file("telegram_video_sticker.webm").open("rb") as f:
-            assert await bot.add_sticker_to_set(
-                chat_id, f"video_test_by_{bot.username}", webm_sticker=f, emojis="🤔"
-            )
+        assert sticker_set.sticker_type == SetSpace.sticker_type
+        assert sticker_set.api_kwargs == {"contains_masks": SetSpace.contains_masks}
 
     def test_sticker_set_to_dict(self, sticker_set):
         sticker_set_dict = sticker_set.to_dict()
@@ -598,64 +520,6 @@ def test_sticker_set_to_dict(self, sticker_set):
         assert sticker_set_dict["thumb"] == sticker_set.thumb.to_dict()
         assert sticker_set_dict["sticker_type"] == sticker_set.sticker_type
 
-    @pytest.mark.flaky(3, 1)
-    async def test_bot_methods_2_png(self, bot, sticker_set):
-        file_id = sticker_set.stickers[0].file_id
-        assert await bot.set_sticker_position_in_set(file_id, 1)
-
-    @pytest.mark.flaky(3, 1)
-    async def test_bot_methods_2_tgs(self, bot, animated_sticker_set):
-        file_id = animated_sticker_set.stickers[0].file_id
-        assert await bot.set_sticker_position_in_set(file_id, 1)
-
-    @pytest.mark.flaky(3, 1)
-    async def test_bot_methods_2_webm(self, bot, video_sticker_set):
-        file_id = video_sticker_set.stickers[0].file_id
-        assert await bot.set_sticker_position_in_set(file_id, 1)
-
-    @pytest.mark.flaky(3, 1)
-    async def test_bot_methods_3_png(self, bot, chat_id, sticker_set_thumb_file):
-        assert await bot.set_sticker_set_thumb(
-            f"test_by_{bot.username}", chat_id, sticker_set_thumb_file
-        )
-
-    @pytest.mark.flaky(10, 1)
-    async def test_bot_methods_3_tgs(
-        self, bot, chat_id, animated_sticker_file, animated_sticker_set
-    ):
-        await asyncio.sleep(1)
-        animated_test = f"animated_test_by_{bot.username}"
-        assert await bot.set_sticker_set_thumb(animated_test, chat_id, animated_sticker_file)
-        file_id = animated_sticker_set.stickers[-1].file_id
-        # also test with file input and mask
-        assert await bot.set_sticker_set_thumb(animated_test, chat_id, file_id)
-
-    # TODO: Try the below by creating a custom .webm and not by downloading another pack's thumb
-    @pytest.mark.skip(
-        "Skipped for now since Telegram throws a 'File is too big' error "
-        "regardless of the .webm file size."
-    )
-    def test_bot_methods_3_webm(self, bot, chat_id, video_sticker_file, video_sticker_set):
-        pass
-
-    @pytest.mark.flaky(10, 1)
-    async def test_bot_methods_4_png(self, bot, sticker_set):
-        await asyncio.sleep(1)
-        file_id = sticker_set.stickers[-1].file_id
-        assert await bot.delete_sticker_from_set(file_id)
-
-    @pytest.mark.flaky(10, 1)
-    async def test_bot_methods_4_tgs(self, bot, animated_sticker_set):
-        await asyncio.sleep(1)
-        file_id = animated_sticker_set.stickers[-1].file_id
-        assert await bot.delete_sticker_from_set(file_id)
-
-    @pytest.mark.flaky(10, 1)
-    async def test_bot_methods_4_webm(self, bot, video_sticker_set):
-        await asyncio.sleep(1)
-        file_id = video_sticker_set.stickers[-1].file_id
-        assert await bot.delete_sticker_from_set(file_id)
-
     @pytest.mark.parametrize("local_mode", [True, False])
     async def test_upload_sticker_file_local_files(self, monkeypatch, bot, chat_id, local_mode):
         try:
@@ -809,31 +673,31 @@ async def make_assertion(*_, **kwargs):
 
     def test_equality(self):
         a = StickerSet(
-            self.name,
-            self.title,
-            self.is_animated,
-            self.stickers,
-            self.is_video,
-            self.sticker_type,
+            SetSpace.name,
+            SetSpace.title,
+            SetSpace.is_animated,
+            SetSpace.stickers,
+            SetSpace.is_video,
+            SetSpace.sticker_type,
         )
         b = StickerSet(
-            self.name,
-            self.title,
-            self.is_animated,
-            self.stickers,
-            self.is_video,
-            self.sticker_type,
+            SetSpace.name,
+            SetSpace.title,
+            SetSpace.is_animated,
+            SetSpace.stickers,
+            SetSpace.is_video,
+            SetSpace.sticker_type,
         )
-        c = StickerSet(self.name, "title", False, [], True, Sticker.CUSTOM_EMOJI)
+        c = StickerSet(SetSpace.name, "title", False, [], True, Sticker.CUSTOM_EMOJI)
         d = StickerSet(
             "blah",
-            self.title,
-            self.is_animated,
-            self.stickers,
-            self.is_video,
-            self.sticker_type,
+            SetSpace.title,
+            SetSpace.is_animated,
+            SetSpace.stickers,
+            SetSpace.is_video,
+            SetSpace.sticker_type,
         )
-        e = Audio(self.name, "", 0, None, None)
+        e = Audio(SetSpace.name, "", 0, None, None)
 
         assert a == b
         assert hash(a) == hash(b)
@@ -849,36 +713,159 @@ def test_equality(self):
         assert hash(a) != hash(e)
 
 
-@pytest.fixture(scope="class")
-def mask_position():
-    return MaskPosition(
-        TestMaskPosition.point,
-        TestMaskPosition.x_shift,
-        TestMaskPosition.y_shift,
-        TestMaskPosition.scale,
+class TestStickerSetReq:
+    async def test_create_sticker_set(
+        self, bot, chat_id, sticker_file, animated_sticker_file, video_sticker_file
+    ):
+        """Creates the sticker set (if needed) which is required for tests. Make sure that this
+        test comes before the tests that actually use the sticker sets!
+        """
+        test_by = f"test_by_{bot.username}"
+        for sticker_set in [test_by, f"animated_{test_by}", f"video_{test_by}"]:
+            try:
+                await bot.get_sticker_set(sticker_set)
+            except BadRequest as e:
+                if not e.message == "Stickerset_invalid":
+                    raise e
+
+                if sticker_set.startswith(test_by):
+                    s = await bot.create_new_sticker_set(
+                        chat_id,
+                        name=sticker_set,
+                        title="Sticker Test",
+                        png_sticker=sticker_file,
+                        emojis="😄",
+                    )
+                    assert s
+                elif sticker_set.startswith("animated"):
+                    a = await bot.create_new_sticker_set(
+                        chat_id,
+                        name=sticker_set,
+                        title="Animated Test",
+                        tgs_sticker=animated_sticker_file,
+                        emojis="😄",
+                    )
+                    assert a
+                elif sticker_set.startswith("video"):
+                    v = await bot.create_new_sticker_set(
+                        chat_id,
+                        name=sticker_set,
+                        title="Video Test",
+                        webm_sticker=video_sticker_file,
+                        emojis="🤔",
+                    )
+                    assert v
+
+    async def test_bot_methods_1_png(self, bot, chat_id, sticker_file):
+        with data_file("telegram_sticker.png").open("rb") as f:
+            # chat_id was hardcoded as 95205500 but it stopped working for some reason
+            file = await bot.upload_sticker_file(chat_id, f)
+        assert file
+
+        tasks = asyncio.gather(
+            bot.add_sticker_to_set(
+                chat_id, f"test_by_{bot.username}", png_sticker=file.file_id, emojis="😄"
+            ),
+            bot.add_sticker_to_set(  # Also test with file input and mask
+                chat_id,
+                f"test_by_{bot.username}",
+                png_sticker=sticker_file,
+                emojis="😄",
+                mask_position=MaskPosition(MaskPosition.EYES, -1, 1, 2),
+            ),
+        )
+        assert all(await tasks)
+
+    async def test_bot_methods_1_tgs(self, bot, chat_id):
+        assert await bot.add_sticker_to_set(
+            chat_id,
+            f"animated_test_by_{bot.username}",
+            tgs_sticker=data_file("telegram_animated_sticker.tgs").open("rb"),
+            emojis="😄",
+        )
+
+    async def test_bot_methods_1_webm(self, bot, chat_id):
+        with data_file("telegram_video_sticker.webm").open("rb") as f:
+            assert await bot.add_sticker_to_set(
+                chat_id, f"video_test_by_{bot.username}", webm_sticker=f, emojis="🤔"
+            )
+
+    async def test_bot_methods_2_png(self, bot, sticker_set):
+        file_id = sticker_set.stickers[0].file_id
+        assert await bot.set_sticker_position_in_set(file_id, 1)
+
+    async def test_bot_methods_2_tgs(self, bot, animated_sticker_set):
+        file_id = animated_sticker_set.stickers[0].file_id
+        assert await bot.set_sticker_position_in_set(file_id, 1)
+
+    async def test_bot_methods_2_webm(self, bot, video_sticker_set):
+        file_id = video_sticker_set.stickers[0].file_id
+        assert await bot.set_sticker_position_in_set(file_id, 1)
+
+    async def test_bot_methods_3_png(self, bot, chat_id, sticker_set_thumb_file):
+        assert await bot.set_sticker_set_thumb(
+            f"test_by_{bot.username}", chat_id, sticker_set_thumb_file
+        )
+
+    async def test_bot_methods_3_tgs(
+        self, bot, chat_id, animated_sticker_file, animated_sticker_set
+    ):
+        animated_test = f"animated_test_by_{bot.username}"
+        file_id = animated_sticker_set.stickers[-1].file_id
+        tasks = asyncio.gather(
+            bot.set_sticker_set_thumb(animated_test, chat_id, animated_sticker_file),
+            bot.set_sticker_set_thumb(animated_test, chat_id, file_id),
+        )
+        assert all(await tasks)
+
+    # TODO: Try the below by creating a custom .webm and not by downloading another pack's thumb
+    @pytest.mark.skip(
+        "Skipped for now since Telegram throws a 'File is too big' error "
+        "regardless of the .webm file size."
     )
+    def test_bot_methods_3_webm(self, bot, chat_id, video_sticker_file, video_sticker_set):
+        pass
 
+    async def test_bot_methods_4_png(self, bot, sticker_set):
+        file_id = sticker_set.stickers[-1].file_id
+        assert await bot.delete_sticker_from_set(file_id)
 
-class TestMaskPosition:
+    async def test_bot_methods_4_tgs(self, bot, animated_sticker_set):
+        file_id = animated_sticker_set.stickers[-1].file_id
+        assert await bot.delete_sticker_from_set(file_id)
+
+    async def test_bot_methods_4_webm(self, bot, video_sticker_set):
+        file_id = video_sticker_set.stickers[-1].file_id
+        assert await bot.delete_sticker_from_set(file_id)
+
+
+@pytest.fixture(scope="module")
+def mask_position():
+    return MaskPosition(MaskSpace.point, MaskSpace.x_shift, MaskSpace.y_shift, MaskSpace.scale)
+
+
+class MaskSpace:
     point = MaskPosition.EYES
     x_shift = -1
     y_shift = 1
     scale = 2
 
+
+class TestMaskPositionNoReq:
     def test_mask_position_de_json(self, bot):
         json_dict = {
-            "point": self.point,
-            "x_shift": self.x_shift,
-            "y_shift": self.y_shift,
-            "scale": self.scale,
+            "point": MaskSpace.point,
+            "x_shift": MaskSpace.x_shift,
+            "y_shift": MaskSpace.y_shift,
+            "scale": MaskSpace.scale,
         }
         mask_position = MaskPosition.de_json(json_dict, bot)
         assert mask_position.api_kwargs == {}
 
-        assert mask_position.point == self.point
-        assert mask_position.x_shift == self.x_shift
-        assert mask_position.y_shift == self.y_shift
-        assert mask_position.scale == self.scale
+        assert mask_position.point == MaskSpace.point
+        assert mask_position.x_shift == MaskSpace.x_shift
+        assert mask_position.y_shift == MaskSpace.y_shift
+        assert mask_position.scale == MaskSpace.scale
 
     def test_mask_position_to_dict(self, mask_position):
         mask_position_dict = mask_position.to_dict()
@@ -890,10 +877,12 @@ def test_mask_position_to_dict(self, mask_position):
         assert mask_position_dict["scale"] == mask_position.scale
 
     def test_equality(self):
-        a = MaskPosition(self.point, self.x_shift, self.y_shift, self.scale)
-        b = MaskPosition(self.point, self.x_shift, self.y_shift, self.scale)
-        c = MaskPosition(MaskPosition.FOREHEAD, self.x_shift, self.y_shift, self.scale)
-        d = MaskPosition(self.point, 0, 0, self.scale)
+        a = MaskPosition(MaskSpace.point, MaskSpace.x_shift, MaskSpace.y_shift, MaskSpace.scale)
+        b = MaskPosition(MaskSpace.point, MaskSpace.x_shift, MaskSpace.y_shift, MaskSpace.scale)
+        c = MaskPosition(
+            MaskPosition.FOREHEAD, MaskSpace.x_shift, MaskSpace.y_shift, MaskSpace.scale
+        )
+        d = MaskPosition(MaskSpace.point, 0, 0, MaskSpace.scale)
         e = Audio("", "", 0, None, None)
 
         assert a == b
@@ -910,7 +899,7 @@ def test_equality(self):
         assert hash(a) != hash(e)
 
 
-class TestGetCustomEmojiSticker:
+class TestGetCustomEmojiStickerReq:
     async def test_custom_emoji_sticker(self, bot):
         # we use the same ID as in test_custom_emoji
         emoji_sticker_list = await bot.get_custom_emoji_stickers(["6046140249875156202"])
diff --git a/tests/test_successfulpayment.py b/tests/test_successfulpayment.py
index 03cc6e178bc..114253cdca1 100644
--- a/tests/test_successfulpayment.py
+++ b/tests/test_successfulpayment.py
@@ -21,20 +21,20 @@
 from telegram import OrderInfo, SuccessfulPayment
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def successful_payment():
     return SuccessfulPayment(
-        TestSuccessfulPayment.currency,
-        TestSuccessfulPayment.total_amount,
-        TestSuccessfulPayment.invoice_payload,
-        TestSuccessfulPayment.telegram_payment_charge_id,
-        TestSuccessfulPayment.provider_payment_charge_id,
-        shipping_option_id=TestSuccessfulPayment.shipping_option_id,
-        order_info=TestSuccessfulPayment.order_info,
+        Space.currency,
+        Space.total_amount,
+        Space.invoice_payload,
+        Space.telegram_payment_charge_id,
+        Space.provider_payment_charge_id,
+        shipping_option_id=Space.shipping_option_id,
+        order_info=Space.order_info,
     )
 
 
-class TestSuccessfulPayment:
+class Space:
     invoice_payload = "invoice_payload"
     shipping_option_id = "shipping_option_id"
     currency = "EUR"
@@ -43,6 +43,8 @@ class TestSuccessfulPayment:
     telegram_payment_charge_id = "telegram_payment_charge_id"
     provider_payment_charge_id = "provider_payment_charge_id"
 
+
+class TestSuccessfulPaymentNoReq:
     def test_slot_behaviour(self, successful_payment, mro_slots):
         inst = successful_payment
         for attr in inst.__slots__:
@@ -51,23 +53,23 @@ def test_slot_behaviour(self, successful_payment, mro_slots):
 
     def test_de_json(self, bot):
         json_dict = {
-            "invoice_payload": self.invoice_payload,
-            "shipping_option_id": self.shipping_option_id,
-            "currency": self.currency,
-            "total_amount": self.total_amount,
-            "order_info": self.order_info.to_dict(),
-            "telegram_payment_charge_id": self.telegram_payment_charge_id,
-            "provider_payment_charge_id": self.provider_payment_charge_id,
+            "invoice_payload": Space.invoice_payload,
+            "shipping_option_id": Space.shipping_option_id,
+            "currency": Space.currency,
+            "total_amount": Space.total_amount,
+            "order_info": Space.order_info.to_dict(),
+            "telegram_payment_charge_id": Space.telegram_payment_charge_id,
+            "provider_payment_charge_id": Space.provider_payment_charge_id,
         }
         successful_payment = SuccessfulPayment.de_json(json_dict, bot)
         assert successful_payment.api_kwargs == {}
 
-        assert successful_payment.invoice_payload == self.invoice_payload
-        assert successful_payment.shipping_option_id == self.shipping_option_id
-        assert successful_payment.currency == self.currency
-        assert successful_payment.order_info == self.order_info
-        assert successful_payment.telegram_payment_charge_id == self.telegram_payment_charge_id
-        assert successful_payment.provider_payment_charge_id == self.provider_payment_charge_id
+        assert successful_payment.invoice_payload == Space.invoice_payload
+        assert successful_payment.shipping_option_id == Space.shipping_option_id
+        assert successful_payment.currency == Space.currency
+        assert successful_payment.order_info == Space.order_info
+        assert successful_payment.telegram_payment_charge_id == Space.telegram_payment_charge_id
+        assert successful_payment.provider_payment_charge_id == Space.provider_payment_charge_id
 
     def test_to_dict(self, successful_payment):
         successful_payment_dict = successful_payment.to_dict()
@@ -90,27 +92,27 @@ def test_to_dict(self, successful_payment):
 
     def test_equality(self):
         a = SuccessfulPayment(
-            self.currency,
-            self.total_amount,
-            self.invoice_payload,
-            self.telegram_payment_charge_id,
-            self.provider_payment_charge_id,
+            Space.currency,
+            Space.total_amount,
+            Space.invoice_payload,
+            Space.telegram_payment_charge_id,
+            Space.provider_payment_charge_id,
         )
         b = SuccessfulPayment(
-            self.currency,
-            self.total_amount,
-            self.invoice_payload,
-            self.telegram_payment_charge_id,
-            self.provider_payment_charge_id,
+            Space.currency,
+            Space.total_amount,
+            Space.invoice_payload,
+            Space.telegram_payment_charge_id,
+            Space.provider_payment_charge_id,
         )
         c = SuccessfulPayment(
-            "", 0, "", self.telegram_payment_charge_id, self.provider_payment_charge_id
+            "", 0, "", Space.telegram_payment_charge_id, Space.provider_payment_charge_id
         )
         d = SuccessfulPayment(
-            self.currency,
-            self.total_amount,
-            self.invoice_payload,
-            self.telegram_payment_charge_id,
+            Space.currency,
+            Space.total_amount,
+            Space.invoice_payload,
+            Space.telegram_payment_charge_id,
             "",
         )
 
diff --git a/tests/test_update.py b/tests/test_update.py
index 20cce556ed1..cf244ee35de 100644
--- a/tests/test_update.py
+++ b/tests/test_update.py
@@ -96,14 +96,16 @@
 ids = all_types + ("callback_query_without_message",)
 
 
-@pytest.fixture(params=params, ids=ids)
+@pytest.fixture(scope="module", params=params, ids=ids)
 def update(request):
-    return Update(update_id=TestUpdate.update_id, **request.param)
+    return Update(update_id=Space.update_id, **request.param)
 
 
-class TestUpdate:
+class Space:
     update_id = 868573637
 
+
+class TestUpdateNoReq:
     def test_slot_behaviour(self, update, mro_slots):
         for attr in update.__slots__:
             assert getattr(update, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -111,13 +113,13 @@ def test_slot_behaviour(self, update, mro_slots):
 
     @pytest.mark.parametrize("paramdict", argvalues=params, ids=ids)
     def test_de_json(self, bot, paramdict):
-        json_dict = {"update_id": TestUpdate.update_id}
+        json_dict = {"update_id": Space.update_id}
         # Convert the single update 'item' to a dict of that item and apply it to the json_dict
         json_dict.update({k: v.to_dict() for k, v in paramdict.items()})
         update = Update.de_json(json_dict, bot)
         assert update.api_kwargs == {}
 
-        assert update.update_id == self.update_id
+        assert update.update_id == Space.update_id
 
         # Make sure only one thing in the update (other than update_id) is not None
         i = 0
@@ -189,11 +191,11 @@ def test_effective_message(self, update):
             assert eff_message is None
 
     def test_equality(self):
-        a = Update(self.update_id, message=message)
-        b = Update(self.update_id, message=message)
-        c = Update(self.update_id)
+        a = Update(Space.update_id, message=message)
+        b = Update(Space.update_id, message=message)
+        c = Update(Space.update_id)
         d = Update(0, message=message)
-        e = User(self.update_id, "", False)
+        e = User(Space.update_id, "", False)
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_updater.py b/tests/test_updater.py
index 62fb0da5293..bb697e98f2d 100644
--- a/tests/test_updater.py
+++ b/tests/test_updater.py
@@ -18,7 +18,6 @@
 # along with this program.  If not, see [http://www.gnu.org/licenses/].
 import asyncio
 import logging
-import os
 from collections import defaultdict
 from http import HTTPStatus
 from pathlib import Path
@@ -33,6 +32,7 @@
 from telegram.request import HTTPXRequest
 from tests.auxil.object_conversions import env_var_2_bool
 from tests.conftest import (
+    TEST_WITH_OPT_DEPS,
     DictBot,
     data_file,
     make_bot,
@@ -41,8 +41,6 @@
     send_webhook_message,
 )
 
-TEST_WITH_OPT_DEPS = env_var_2_bool(os.getenv("TEST_WITH_OPT_DEPS", True))
-
 if TEST_WITH_OPT_DEPS:
     from telegram.ext._utils.webhookhandler import WebhookServer
 
diff --git a/tests/test_user.py b/tests/test_user.py
index 56c3c6eadf4..6feff8abed0 100644
--- a/tests/test_user.py
+++ b/tests/test_user.py
@@ -30,41 +30,41 @@
 @pytest.fixture(scope="function")
 def json_dict():
     return {
-        "id": TestUser.id_,
-        "is_bot": TestUser.is_bot,
-        "first_name": TestUser.first_name,
-        "last_name": TestUser.last_name,
-        "username": TestUser.username,
-        "language_code": TestUser.language_code,
-        "can_join_groups": TestUser.can_join_groups,
-        "can_read_all_group_messages": TestUser.can_read_all_group_messages,
-        "supports_inline_queries": TestUser.supports_inline_queries,
-        "is_premium": TestUser.is_premium,
-        "added_to_attachment_menu": TestUser.added_to_attachment_menu,
+        "id": Space.id_,
+        "is_bot": Space.is_bot,
+        "first_name": Space.first_name,
+        "last_name": Space.last_name,
+        "username": Space.username,
+        "language_code": Space.language_code,
+        "can_join_groups": Space.can_join_groups,
+        "can_read_all_group_messages": Space.can_read_all_group_messages,
+        "supports_inline_queries": Space.supports_inline_queries,
+        "is_premium": Space.is_premium,
+        "added_to_attachment_menu": Space.added_to_attachment_menu,
     }
 
 
 @pytest.fixture(scope="function")
 def user(bot):
     user = User(
-        id=TestUser.id_,
-        first_name=TestUser.first_name,
-        is_bot=TestUser.is_bot,
-        last_name=TestUser.last_name,
-        username=TestUser.username,
-        language_code=TestUser.language_code,
-        can_join_groups=TestUser.can_join_groups,
-        can_read_all_group_messages=TestUser.can_read_all_group_messages,
-        supports_inline_queries=TestUser.supports_inline_queries,
-        is_premium=TestUser.is_premium,
-        added_to_attachment_menu=TestUser.added_to_attachment_menu,
+        id=Space.id_,
+        first_name=Space.first_name,
+        is_bot=Space.is_bot,
+        last_name=Space.last_name,
+        username=Space.username,
+        language_code=Space.language_code,
+        can_join_groups=Space.can_join_groups,
+        can_read_all_group_messages=Space.can_read_all_group_messages,
+        supports_inline_queries=Space.supports_inline_queries,
+        is_premium=Space.is_premium,
+        added_to_attachment_menu=Space.added_to_attachment_menu,
     )
     user.set_bot(bot)
     user._unfreeze()
     return user
 
 
-class TestUser:
+class Space:
     id_ = 1
     is_bot = True
     first_name = "first\u2022name"
@@ -77,6 +77,8 @@ class TestUser:
     is_premium = True
     added_to_attachment_menu = False
 
+
+class TestUserNoReq:
     def test_slot_behaviour(self, user, mro_slots):
         for attr in user.__slots__:
             assert getattr(user, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -86,17 +88,17 @@ def test_de_json(self, json_dict, bot):
         user = User.de_json(json_dict, bot)
         assert user.api_kwargs == {}
 
-        assert user.id == self.id_
-        assert user.is_bot == self.is_bot
-        assert user.first_name == self.first_name
-        assert user.last_name == self.last_name
-        assert user.username == self.username
-        assert user.language_code == self.language_code
-        assert user.can_join_groups == self.can_join_groups
-        assert user.can_read_all_group_messages == self.can_read_all_group_messages
-        assert user.supports_inline_queries == self.supports_inline_queries
-        assert user.is_premium == self.is_premium
-        assert user.added_to_attachment_menu == self.added_to_attachment_menu
+        assert user.id == Space.id_
+        assert user.is_bot == Space.is_bot
+        assert user.first_name == Space.first_name
+        assert user.last_name == Space.last_name
+        assert user.username == Space.username
+        assert user.language_code == Space.language_code
+        assert user.can_join_groups == Space.can_join_groups
+        assert user.can_read_all_group_messages == Space.can_read_all_group_messages
+        assert user.supports_inline_queries == Space.supports_inline_queries
+        assert user.is_premium == Space.is_premium
+        assert user.added_to_attachment_menu == Space.added_to_attachment_menu
 
     def test_de_json_without_username(self, json_dict, bot):
         del json_dict["username"]
@@ -104,17 +106,17 @@ def test_de_json_without_username(self, json_dict, bot):
         user = User.de_json(json_dict, bot)
         assert user.api_kwargs == {}
 
-        assert user.id == self.id_
-        assert user.is_bot == self.is_bot
-        assert user.first_name == self.first_name
-        assert user.last_name == self.last_name
+        assert user.id == Space.id_
+        assert user.is_bot == Space.is_bot
+        assert user.first_name == Space.first_name
+        assert user.last_name == Space.last_name
         assert user.username is None
-        assert user.language_code == self.language_code
-        assert user.can_join_groups == self.can_join_groups
-        assert user.can_read_all_group_messages == self.can_read_all_group_messages
-        assert user.supports_inline_queries == self.supports_inline_queries
-        assert user.is_premium == self.is_premium
-        assert user.added_to_attachment_menu == self.added_to_attachment_menu
+        assert user.language_code == Space.language_code
+        assert user.can_join_groups == Space.can_join_groups
+        assert user.can_read_all_group_messages == Space.can_read_all_group_messages
+        assert user.supports_inline_queries == Space.supports_inline_queries
+        assert user.is_premium == Space.is_premium
+        assert user.added_to_attachment_menu == Space.added_to_attachment_menu
 
     def test_de_json_without_username_and_last_name(self, json_dict, bot):
         del json_dict["username"]
@@ -123,17 +125,17 @@ def test_de_json_without_username_and_last_name(self, json_dict, bot):
         user = User.de_json(json_dict, bot)
         assert user.api_kwargs == {}
 
-        assert user.id == self.id_
-        assert user.is_bot == self.is_bot
-        assert user.first_name == self.first_name
+        assert user.id == Space.id_
+        assert user.is_bot == Space.is_bot
+        assert user.first_name == Space.first_name
         assert user.last_name is None
         assert user.username is None
-        assert user.language_code == self.language_code
-        assert user.can_join_groups == self.can_join_groups
-        assert user.can_read_all_group_messages == self.can_read_all_group_messages
-        assert user.supports_inline_queries == self.supports_inline_queries
-        assert user.is_premium == self.is_premium
-        assert user.added_to_attachment_menu == self.added_to_attachment_menu
+        assert user.language_code == Space.language_code
+        assert user.can_join_groups == Space.can_join_groups
+        assert user.can_read_all_group_messages == Space.can_read_all_group_messages
+        assert user.supports_inline_queries == Space.supports_inline_queries
+        assert user.is_premium == Space.is_premium
+        assert user.added_to_attachment_menu == Space.added_to_attachment_menu
 
     def test_name(self, user):
         assert user.name == "@username"
@@ -141,7 +143,7 @@ def test_name(self, user):
         assert user.name == "first\u2022name last\u2022name"
         user.last_name = None
         assert user.name == "first\u2022name"
-        user.username = self.username
+        user.username = Space.username
         assert user.name == "@username"
 
     def test_full_name(self, user):
@@ -562,11 +564,11 @@ async def test_mention_markdown_v2(self, user):
         assert user.mention_markdown_v2(user.username) == expected.format(user.username, user.id)
 
     def test_equality(self):
-        a = User(self.id_, self.first_name, self.is_bot, self.last_name)
-        b = User(self.id_, self.first_name, self.is_bot, self.last_name)
-        c = User(self.id_, self.first_name, self.is_bot)
-        d = User(0, self.first_name, self.is_bot, self.last_name)
-        e = Update(self.id_)
+        a = User(Space.id_, Space.first_name, Space.is_bot, Space.last_name)
+        b = User(Space.id_, Space.first_name, Space.is_bot, Space.last_name)
+        c = User(Space.id_, Space.first_name, Space.is_bot)
+        d = User(0, Space.first_name, Space.is_bot, Space.last_name)
+        e = Update(Space.id_)
 
         assert a == b
         assert hash(a) == hash(b)
diff --git a/tests/test_userprofilephotos.py b/tests/test_userprofilephotos.py
index c8edb0daebe..b855e7512dd 100644
--- a/tests/test_userprofilephotos.py
+++ b/tests/test_userprofilephotos.py
@@ -19,7 +19,7 @@
 from telegram import PhotoSize, UserProfilePhotos
 
 
-class TestUserProfilePhotos:
+class Space:
     total_count = 2
     photos = [
         [
@@ -32,21 +32,23 @@ class TestUserProfilePhotos:
         ],
     ]
 
+
+class TestUserProfilePhotosNoReq:
     def test_slot_behaviour(self, mro_slots):
-        inst = UserProfilePhotos(self.total_count, self.photos)
+        inst = UserProfilePhotos(Space.total_count, Space.photos)
         for attr in inst.__slots__:
             assert getattr(inst, attr, "err") != "err", f"got extra slot '{attr}'"
         assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot"
 
     def test_de_json(self, bot):
-        json_dict = {"total_count": 2, "photos": [[y.to_dict() for y in x] for x in self.photos]}
+        json_dict = {"total_count": 2, "photos": [[y.to_dict() for y in x] for x in Space.photos]}
         user_profile_photos = UserProfilePhotos.de_json(json_dict, bot)
         assert user_profile_photos.api_kwargs == {}
-        assert user_profile_photos.total_count == self.total_count
-        assert user_profile_photos.photos == tuple(tuple(p) for p in self.photos)
+        assert user_profile_photos.total_count == Space.total_count
+        assert user_profile_photos.photos == tuple(tuple(p) for p in Space.photos)
 
     def test_to_dict(self):
-        user_profile_photos = UserProfilePhotos(self.total_count, self.photos)
+        user_profile_photos = UserProfilePhotos(Space.total_count, Space.photos)
         user_profile_photos_dict = user_profile_photos.to_dict()
         assert user_profile_photos_dict["total_count"] == user_profile_photos.total_count
         for ix, x in enumerate(user_profile_photos_dict["photos"]):
@@ -54,9 +56,9 @@ def test_to_dict(self):
                 assert y == user_profile_photos.photos[ix][iy].to_dict()
 
     def test_equality(self):
-        a = UserProfilePhotos(2, self.photos)
-        b = UserProfilePhotos(2, self.photos)
-        c = UserProfilePhotos(1, [self.photos[0]])
+        a = UserProfilePhotos(2, Space.photos)
+        b = UserProfilePhotos(2, Space.photos)
+        c = UserProfilePhotos(1, [Space.photos[0]])
         d = PhotoSize("file_id1", "unique_id", 512, 512)
 
         assert a == b
diff --git a/tests/test_venue.py b/tests/test_venue.py
index 53aca6f6121..48706e8f4b7 100644
--- a/tests/test_venue.py
+++ b/tests/test_venue.py
@@ -16,6 +16,8 @@
 #
 # You should have received a copy of the GNU Lesser Public License
 # along with this program.  If not, see [http://www.gnu.org/licenses/].
+import asyncio
+
 import pytest
 
 from telegram import Location, Venue
@@ -23,20 +25,20 @@
 from telegram.request import RequestData
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def venue():
     return Venue(
-        TestVenue.location,
-        TestVenue.title,
-        TestVenue.address,
-        foursquare_id=TestVenue.foursquare_id,
-        foursquare_type=TestVenue.foursquare_type,
-        google_place_id=TestVenue.google_place_id,
-        google_place_type=TestVenue.google_place_type,
+        Space.location,
+        Space.title,
+        Space.address,
+        foursquare_id=Space.foursquare_id,
+        foursquare_type=Space.foursquare_type,
+        google_place_id=Space.google_place_id,
+        google_place_type=Space.google_place_type,
     )
 
 
-class TestVenue:
+class Space:
     location = Location(longitude=-46.788279, latitude=-23.691288)
     title = "title"
     address = "address"
@@ -45,6 +47,8 @@ class TestVenue:
     google_place_id = "google place id"
     google_place_type = "google place type"
 
+
+class TestVenueNoReq:
     def test_slot_behaviour(self, venue, mro_slots):
         for attr in venue.__slots__:
             assert getattr(venue, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -52,85 +56,43 @@ def test_slot_behaviour(self, venue, mro_slots):
 
     def test_de_json(self, bot):
         json_dict = {
-            "location": TestVenue.location.to_dict(),
-            "title": TestVenue.title,
-            "address": TestVenue.address,
-            "foursquare_id": TestVenue.foursquare_id,
-            "foursquare_type": TestVenue.foursquare_type,
-            "google_place_id": TestVenue.google_place_id,
-            "google_place_type": TestVenue.google_place_type,
+            "location": Space.location.to_dict(),
+            "title": Space.title,
+            "address": Space.address,
+            "foursquare_id": Space.foursquare_id,
+            "foursquare_type": Space.foursquare_type,
+            "google_place_id": Space.google_place_id,
+            "google_place_type": Space.google_place_type,
         }
         venue = Venue.de_json(json_dict, bot)
         assert venue.api_kwargs == {}
 
-        assert venue.location == self.location
-        assert venue.title == self.title
-        assert venue.address == self.address
-        assert venue.foursquare_id == self.foursquare_id
-        assert venue.foursquare_type == self.foursquare_type
-        assert venue.google_place_id == self.google_place_id
-        assert venue.google_place_type == self.google_place_type
+        assert venue.location == Space.location
+        assert venue.title == Space.title
+        assert venue.address == Space.address
+        assert venue.foursquare_id == Space.foursquare_id
+        assert venue.foursquare_type == Space.foursquare_type
+        assert venue.google_place_id == Space.google_place_id
+        assert venue.google_place_type == Space.google_place_type
 
     async def test_send_with_venue(self, monkeypatch, bot, chat_id, venue):
         async def make_assertion(url, request_data: RequestData, *args, **kwargs):
             data = request_data.json_parameters
             return (
-                data["longitude"] == str(self.location.longitude)
-                and data["latitude"] == str(self.location.latitude)
-                and data["title"] == self.title
-                and data["address"] == self.address
-                and data["foursquare_id"] == self.foursquare_id
-                and data["foursquare_type"] == self.foursquare_type
-                and data["google_place_id"] == self.google_place_id
-                and data["google_place_type"] == self.google_place_type
+                data["longitude"] == str(Space.location.longitude)
+                and data["latitude"] == str(Space.location.latitude)
+                and data["title"] == Space.title
+                and data["address"] == Space.address
+                and data["foursquare_id"] == Space.foursquare_id
+                and data["foursquare_type"] == Space.foursquare_type
+                and data["google_place_id"] == Space.google_place_id
+                and data["google_place_type"] == Space.google_place_type
             )
 
         monkeypatch.setattr(bot.request, "post", make_assertion)
         message = await bot.send_venue(chat_id, venue=venue)
         assert message
 
-    @pytest.mark.flaky(3, 1)
-    @pytest.mark.parametrize(
-        "default_bot,custom",
-        [
-            ({"allow_sending_without_reply": True}, None),
-            ({"allow_sending_without_reply": False}, None),
-            ({"allow_sending_without_reply": False}, True),
-        ],
-        indirect=["default_bot"],
-    )
-    async def test_send_venue_default_allow_sending_without_reply(
-        self, default_bot, chat_id, venue, custom
-    ):
-        reply_to_message = await default_bot.send_message(chat_id, "test")
-        await reply_to_message.delete()
-        if custom is not None:
-            message = await default_bot.send_venue(
-                chat_id,
-                venue=venue,
-                allow_sending_without_reply=custom,
-                reply_to_message_id=reply_to_message.message_id,
-            )
-            assert message.reply_to_message is None
-        elif default_bot.defaults.allow_sending_without_reply:
-            message = await default_bot.send_venue(
-                chat_id, venue=venue, reply_to_message_id=reply_to_message.message_id
-            )
-            assert message.reply_to_message is None
-        else:
-            with pytest.raises(BadRequest, match="message not found"):
-                await default_bot.send_venue(
-                    chat_id, venue=venue, reply_to_message_id=reply_to_message.message_id
-                )
-
-    @pytest.mark.flaky(3, 1)
-    @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
-    async def test_send_venue_default_protect_content(self, default_bot, chat_id, venue):
-        protected = await default_bot.send_venue(chat_id, venue=venue)
-        assert protected.has_protected_content
-        unprotected = await default_bot.send_venue(chat_id, venue=venue, protect_content=False)
-        assert not unprotected.has_protected_content
-
     async def test_send_venue_without_required(self, bot, chat_id):
         with pytest.raises(ValueError, match="Either venue or latitude, longitude, address and"):
             await bot.send_venue(chat_id=chat_id)
@@ -159,11 +121,11 @@ def test_to_dict(self, venue):
         assert venue_dict["google_place_type"] == venue.google_place_type
 
     def test_equality(self):
-        a = Venue(Location(0, 0), self.title, self.address)
-        b = Venue(Location(0, 0), self.title, self.address)
-        c = Venue(Location(0, 0), self.title, "")
-        d = Venue(Location(0, 1), self.title, self.address)
-        d2 = Venue(Location(0, 0), "", self.address)
+        a = Venue(Location(0, 0), Space.title, Space.address)
+        b = Venue(Location(0, 0), Space.title, Space.address)
+        c = Venue(Location(0, 0), Space.title, "")
+        d = Venue(Location(0, 1), Space.title, Space.address)
+        d2 = Venue(Location(0, 0), "", Space.address)
 
         assert a == b
         assert hash(a) == hash(b)
@@ -177,3 +139,48 @@ def test_equality(self):
 
         assert a != d2
         assert hash(a) != hash(d2)
+
+
+class TestVenueReq:
+    @pytest.mark.parametrize(
+        "default_bot,custom",
+        [
+            ({"allow_sending_without_reply": True}, None),
+            ({"allow_sending_without_reply": False}, None),
+            ({"allow_sending_without_reply": False}, True),
+        ],
+        indirect=["default_bot"],
+    )
+    async def test_send_venue_default_allow_sending_without_reply(
+        self, default_bot, chat_id, venue, custom
+    ):
+        reply_to_message = await default_bot.send_message(chat_id, "test")
+        await reply_to_message.delete()
+        if custom is not None:
+            message = await default_bot.send_venue(
+                chat_id,
+                venue=venue,
+                allow_sending_without_reply=custom,
+                reply_to_message_id=reply_to_message.message_id,
+            )
+            assert message.reply_to_message is None
+        elif default_bot.defaults.allow_sending_without_reply:
+            message = await default_bot.send_venue(
+                chat_id, venue=venue, reply_to_message_id=reply_to_message.message_id
+            )
+            assert message.reply_to_message is None
+        else:
+            with pytest.raises(BadRequest, match="message not found"):
+                await default_bot.send_venue(
+                    chat_id, venue=venue, reply_to_message_id=reply_to_message.message_id
+                )
+
+    @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
+    async def test_send_venue_default_protect_content(self, default_bot, chat_id, venue):
+        tasks = asyncio.gather(
+            default_bot.send_venue(chat_id, venue=venue),
+            default_bot.send_venue(chat_id, venue=venue, protect_content=False),
+        )
+        protected, unprotected = await tasks
+        assert protected.has_protected_content
+        assert not unprotected.has_protected_content
diff --git a/tests/test_video.py b/tests/test_video.py
index 80f68cd57bd..a060a2d40f2 100644
--- a/tests/test_video.py
+++ b/tests/test_video.py
@@ -16,6 +16,7 @@
 #
 # You should have received a copy of the GNU Lesser Public License
 # along with this program.  If not, see [http://www.gnu.org/licenses/].
+import asyncio
 import os
 from pathlib import Path
 
@@ -35,18 +36,17 @@
 
 @pytest.fixture(scope="function")
 def video_file():
-    f = data_file("telegram.mp4").open("rb")
-    yield f
-    f.close()
+    with data_file("telegram.mp4").open("rb") as f:
+        yield f
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 async def video(bot, chat_id):
     with data_file("telegram.mp4").open("rb") as f:
         return (await bot.send_video(chat_id, video=f, read_timeout=50)).video
 
 
-class TestVideo:
+class Space:
     width = 360
     height = 640
     duration = 5
@@ -54,17 +54,16 @@ class TestVideo:
     mime_type = "video/mp4"
     supports_streaming = True
     file_name = "telegram.mp4"
-
     thumb_width = 180
     thumb_height = 320
     thumb_file_size = 1767
-
     caption = "<b>VideoTest</b> - *Caption*"
     video_file_url = "https://python-telegram-bot.org/static/testfiles/telegram.mp4"
-
     video_file_id = "5a3128a4d2a04750b5b58397f3b5e812"
     video_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
 
+
+class TestVideoNoReq:
     def test_slot_behaviour(self, video, mro_slots):
         for attr in video.__slots__:
             assert getattr(video, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -85,20 +84,132 @@ def test_creation(self, video):
         assert video.thumb.file_unique_id != ""
 
     def test_expected_values(self, video):
-        assert video.width == self.width
-        assert video.height == self.height
-        assert video.duration == self.duration
-        assert video.file_size == self.file_size
-        assert video.mime_type == self.mime_type
+        assert video.width == Space.width
+        assert video.height == Space.height
+        assert video.duration == Space.duration
+        assert video.file_size == Space.file_size
+        assert video.mime_type == Space.mime_type
+
+    async def test_send_video_custom_filename(self, bot, chat_id, video_file, monkeypatch):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            return list(request_data.multipart_data.values())[0][0] == "custom_filename"
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+
+        assert await bot.send_video(chat_id, video_file, filename="custom_filename")
+
+    async def test_send_with_video(self, monkeypatch, bot, chat_id, video):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            return request_data.json_parameters["video"] == video.file_id
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+        message = await bot.send_video(chat_id, video=video)
+        assert message
+
+    @pytest.mark.parametrize("local_mode", [True, False])
+    async def test_send_video_local_files(self, monkeypatch, bot, chat_id, local_mode):
+        try:
+            bot._local_mode = local_mode
+            # For just test that the correct paths are passed as we have no local bot API set up
+            test_flag = False
+            file = data_file("telegram.jpg")
+            expected = file.as_uri()
+
+            async def make_assertion(_, data, *args, **kwargs):
+                nonlocal test_flag
+                if local_mode:
+                    test_flag = data.get("video") == expected and data.get("thumb") == expected
+                else:
+                    test_flag = isinstance(data.get("video"), InputFile) and isinstance(
+                        data.get("thumb"), InputFile
+                    )
+
+            monkeypatch.setattr(bot, "_post", make_assertion)
+            await bot.send_video(chat_id, file, thumb=file)
+            assert test_flag
+        finally:
+            bot._local_mode = False
+
+    def test_de_json(self, bot):
+        json_dict = {
+            "file_id": Space.video_file_id,
+            "file_unique_id": Space.video_file_unique_id,
+            "width": Space.width,
+            "height": Space.height,
+            "duration": Space.duration,
+            "mime_type": Space.mime_type,
+            "file_size": Space.file_size,
+            "file_name": Space.file_name,
+        }
+        json_video = Video.de_json(json_dict, bot)
+        assert json_video.api_kwargs == {}
+
+        assert json_video.file_id == Space.video_file_id
+        assert json_video.file_unique_id == Space.video_file_unique_id
+        assert json_video.width == Space.width
+        assert json_video.height == Space.height
+        assert json_video.duration == Space.duration
+        assert json_video.mime_type == Space.mime_type
+        assert json_video.file_size == Space.file_size
+        assert json_video.file_name == Space.file_name
+
+    def test_to_dict(self, video):
+        video_dict = video.to_dict()
+
+        assert isinstance(video_dict, dict)
+        assert video_dict["file_id"] == video.file_id
+        assert video_dict["file_unique_id"] == video.file_unique_id
+        assert video_dict["width"] == video.width
+        assert video_dict["height"] == video.height
+        assert video_dict["duration"] == video.duration
+        assert video_dict["mime_type"] == video.mime_type
+        assert video_dict["file_size"] == video.file_size
+        assert video_dict["file_name"] == video.file_name
+
+    async def test_error_without_required_args(self, bot, chat_id):
+        with pytest.raises(TypeError):
+            await bot.send_video(chat_id=chat_id)
+
+    async def test_get_file_instance_method(self, monkeypatch, video):
+        async def make_assertion(*_, **kwargs):
+            return kwargs["file_id"] == video.file_id
+
+        assert check_shortcut_signature(Video.get_file, Bot.get_file, ["file_id"], [])
+        assert await check_shortcut_call(video.get_file, video.get_bot(), "get_file")
+        assert await check_defaults_handling(video.get_file, video.get_bot())
+
+        monkeypatch.setattr(video.get_bot(), "get_file", make_assertion)
+        assert await video.get_file()
+
+    def test_equality(self, video):
+        a = Video(video.file_id, video.file_unique_id, Space.width, Space.height, Space.duration)
+        b = Video("", video.file_unique_id, Space.width, Space.height, Space.duration)
+        c = Video(video.file_id, video.file_unique_id, 0, 0, 0)
+        d = Video("", "", Space.width, Space.height, Space.duration)
+        e = Voice(video.file_id, video.file_unique_id, Space.duration)
+
+        assert a == b
+        assert hash(a) == hash(b)
+        assert a is not b
+
+        assert a == c
+        assert hash(a) == hash(c)
+
+        assert a != d
+        assert hash(a) != hash(d)
+
+        assert a != e
+        assert hash(a) != hash(e)
+
 
-    @pytest.mark.flaky(3, 1)
+class TestVideoReq:
     async def test_send_all_args(self, bot, chat_id, video_file, video, thumb_file):
         message = await bot.send_video(
             chat_id,
             video_file,
-            duration=self.duration,
-            caption=self.caption,
-            supports_streaming=self.supports_streaming,
+            duration=Space.duration,
+            caption=Space.caption,
+            supports_streaming=Space.supports_streaming,
             disable_notification=False,
             protect_content=True,
             width=video.width,
@@ -117,25 +228,15 @@ async def test_send_all_args(self, bot, chat_id, video_file, video, thumb_file):
         assert message.video.duration == video.duration
         assert message.video.file_size == video.file_size
 
-        assert message.caption == self.caption.replace("*", "")
+        assert message.caption == Space.caption.replace("*", "")
 
-        assert message.video.thumb.file_size == self.thumb_file_size
-        assert message.video.thumb.width == self.thumb_width
-        assert message.video.thumb.height == self.thumb_height
+        assert message.video.thumb.file_size == Space.thumb_file_size
+        assert message.video.thumb.width == Space.thumb_width
+        assert message.video.thumb.height == Space.thumb_height
 
-        assert message.video.file_name == self.file_name
+        assert message.video.file_name == Space.file_name
         assert message.has_protected_content
 
-    @pytest.mark.flaky(3, 1)
-    async def test_send_video_custom_filename(self, bot, chat_id, video_file, monkeypatch):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            return list(request_data.multipart_data.values())[0][0] == "custom_filename"
-
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-
-        assert await bot.send_video(chat_id, video_file, filename="custom_filename")
-
-    @pytest.mark.flaky(3, 1)
     async def test_get_and_download(self, bot, video):
         path = Path("telegram.mp4")
         if path.is_file():
@@ -143,7 +244,7 @@ async def test_get_and_download(self, bot, video):
 
         new_file = await bot.get_file(video.file_id)
 
-        assert new_file.file_size == self.file_size
+        assert new_file.file_size == Space.file_size
         assert new_file.file_id == video.file_id
         assert new_file.file_unique_id == video.file_unique_id
         assert new_file.file_path.startswith("https://")
@@ -152,9 +253,8 @@ async def test_get_and_download(self, bot, video):
 
         assert path.is_file()
 
-    @pytest.mark.flaky(3, 1)
     async def test_send_mp4_file_url(self, bot, chat_id, video):
-        message = await bot.send_video(chat_id, self.video_file_url, caption=self.caption)
+        message = await bot.send_video(chat_id, Space.video_file_url, caption=Space.caption)
 
         assert isinstance(message.video, Video)
         assert isinstance(message.video.file_id, str)
@@ -171,13 +271,12 @@ async def test_send_mp4_file_url(self, bot, chat_id, video):
         assert isinstance(message.video.thumb.file_unique_id, str)
         assert message.video.thumb.file_id != ""
         assert message.video.thumb.file_unique_id != ""
-        assert message.video.thumb.width == 51  # This seems odd that it's not self.thumb_width
+        assert message.video.thumb.width == 51  # This seems odd that it's not Space.thumb_width
         assert message.video.thumb.height == 90  # Ditto
         assert message.video.thumb.file_size == 645  # same
 
-        assert message.caption == self.caption
+        assert message.caption == Space.caption
 
-    @pytest.mark.flaky(3, 1)
     async def test_send_video_caption_entities(self, bot, chat_id, video):
         test_string = "Italic Bold Code"
         entities = [
@@ -192,21 +291,10 @@ async def test_send_video_caption_entities(self, bot, chat_id, video):
         assert message.caption == test_string
         assert message.caption_entities == tuple(entities)
 
-    @pytest.mark.flaky(3, 1)
     async def test_resend(self, bot, chat_id, video):
         message = await bot.send_video(chat_id, video.file_id)
-
         assert message.video == video
 
-    async def test_send_with_video(self, monkeypatch, bot, chat_id, video):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            return request_data.json_parameters["video"] == video.file_id
-
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-        message = await bot.send_video(chat_id, video=video)
-        assert message
-
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_send_video_default_parse_mode_1(self, default_bot, chat_id, video):
         test_string = "Italic Bold Code"
@@ -216,7 +304,6 @@ async def test_send_video_default_parse_mode_1(self, default_bot, chat_id, video
         assert message.caption_markdown == test_markdown_string
         assert message.caption == test_string
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_send_video_default_parse_mode_2(self, default_bot, chat_id, video):
         test_markdown_string = "_Italic_ *Bold* `Code`"
@@ -227,7 +314,6 @@ async def test_send_video_default_parse_mode_2(self, default_bot, chat_id, video
         assert message.caption == test_markdown_string
         assert message.caption_markdown == escape_markdown(test_markdown_string)
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_send_video_default_parse_mode_3(self, default_bot, chat_id, video):
         test_markdown_string = "_Italic_ *Bold* `Code`"
@@ -238,39 +324,16 @@ async def test_send_video_default_parse_mode_3(self, default_bot, chat_id, video
         assert message.caption == test_markdown_string
         assert message.caption_markdown == escape_markdown(test_markdown_string)
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
     async def test_send_video_default_protect_content(self, chat_id, default_bot, video):
-        protected = await default_bot.send_video(chat_id, video)
+        tasks = asyncio.gather(
+            default_bot.send_video(chat_id, video),
+            default_bot.send_video(chat_id, video, protect_content=False),
+        )
+        protected, unprotected = await tasks
         assert protected.has_protected_content
-        unprotected = await default_bot.send_video(chat_id, video, protect_content=False)
         assert not unprotected.has_protected_content
 
-    @pytest.mark.parametrize("local_mode", [True, False])
-    async def test_send_video_local_files(self, monkeypatch, bot, chat_id, local_mode):
-        try:
-            bot._local_mode = local_mode
-            # For just test that the correct paths are passed as we have no local bot API set up
-            test_flag = False
-            file = data_file("telegram.jpg")
-            expected = file.as_uri()
-
-            async def make_assertion(_, data, *args, **kwargs):
-                nonlocal test_flag
-                if local_mode:
-                    test_flag = data.get("video") == expected and data.get("thumb") == expected
-                else:
-                    test_flag = isinstance(data.get("video"), InputFile) and isinstance(
-                        data.get("thumb"), InputFile
-                    )
-
-            monkeypatch.setattr(bot, "_post", make_assertion)
-            await bot.send_video(chat_id, file, thumb=file)
-            assert test_flag
-        finally:
-            bot._local_mode = False
-
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize(
         "default_bot,custom",
         [
@@ -304,83 +367,10 @@ async def test_send_video_default_allow_sending_without_reply(
                     chat_id, video, reply_to_message_id=reply_to_message.message_id
                 )
 
-    def test_de_json(self, bot):
-        json_dict = {
-            "file_id": self.video_file_id,
-            "file_unique_id": self.video_file_unique_id,
-            "width": self.width,
-            "height": self.height,
-            "duration": self.duration,
-            "mime_type": self.mime_type,
-            "file_size": self.file_size,
-            "file_name": self.file_name,
-        }
-        json_video = Video.de_json(json_dict, bot)
-        assert json_video.api_kwargs == {}
-
-        assert json_video.file_id == self.video_file_id
-        assert json_video.file_unique_id == self.video_file_unique_id
-        assert json_video.width == self.width
-        assert json_video.height == self.height
-        assert json_video.duration == self.duration
-        assert json_video.mime_type == self.mime_type
-        assert json_video.file_size == self.file_size
-        assert json_video.file_name == self.file_name
-
-    def test_to_dict(self, video):
-        video_dict = video.to_dict()
-
-        assert isinstance(video_dict, dict)
-        assert video_dict["file_id"] == video.file_id
-        assert video_dict["file_unique_id"] == video.file_unique_id
-        assert video_dict["width"] == video.width
-        assert video_dict["height"] == video.height
-        assert video_dict["duration"] == video.duration
-        assert video_dict["mime_type"] == video.mime_type
-        assert video_dict["file_size"] == video.file_size
-        assert video_dict["file_name"] == video.file_name
-
-    @pytest.mark.flaky(3, 1)
     async def test_error_send_empty_file(self, bot, chat_id):
         with pytest.raises(TelegramError):
             await bot.send_video(chat_id, open(os.devnull, "rb"))
 
-    @pytest.mark.flaky(3, 1)
     async def test_error_send_empty_file_id(self, bot, chat_id):
         with pytest.raises(TelegramError):
             await bot.send_video(chat_id, "")
-
-    async def test_error_without_required_args(self, bot, chat_id):
-        with pytest.raises(TypeError):
-            await bot.send_video(chat_id=chat_id)
-
-    async def test_get_file_instance_method(self, monkeypatch, video):
-        async def make_assertion(*_, **kwargs):
-            return kwargs["file_id"] == video.file_id
-
-        assert check_shortcut_signature(Video.get_file, Bot.get_file, ["file_id"], [])
-        assert await check_shortcut_call(video.get_file, video.get_bot(), "get_file")
-        assert await check_defaults_handling(video.get_file, video.get_bot())
-
-        monkeypatch.setattr(video.get_bot(), "get_file", make_assertion)
-        assert await video.get_file()
-
-    def test_equality(self, video):
-        a = Video(video.file_id, video.file_unique_id, self.width, self.height, self.duration)
-        b = Video("", video.file_unique_id, self.width, self.height, self.duration)
-        c = Video(video.file_id, video.file_unique_id, 0, 0, 0)
-        d = Video("", "", self.width, self.height, self.duration)
-        e = Voice(video.file_id, video.file_unique_id, self.duration)
-
-        assert a == b
-        assert hash(a) == hash(b)
-        assert a is not b
-
-        assert a == c
-        assert hash(a) == hash(c)
-
-        assert a != d
-        assert hash(a) != hash(d)
-
-        assert a != e
-        assert hash(a) != hash(e)
diff --git a/tests/test_videochat.py b/tests/test_videochat.py
index 81b36f9b852..9717bb26df4 100644
--- a/tests/test_videochat.py
+++ b/tests/test_videochat.py
@@ -30,17 +30,17 @@
 from telegram._utils.datetime import to_timestamp
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def user1():
     return User(first_name="Misses Test", id=123, is_bot=False)
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def user2():
     return User(first_name="Mister Test", id=124, is_bot=False)
 
 
-class TestVideoChatStarted:
+class TestVideoChatStartedNoReq:
     def test_slot_behaviour(self, mro_slots):
         action = VideoChatStarted()
         for attr in action.__slots__:
@@ -58,7 +58,7 @@ def test_to_dict(self):
         assert video_chat_dict == {}
 
 
-class TestVideoChatEnded:
+class TestVideoChatEndedNoReq:
     duration = 100
 
     def test_slot_behaviour(self, mro_slots):
@@ -97,7 +97,7 @@ def test_equality(self):
         assert hash(a) != hash(d)
 
 
-class TestVideoChatParticipantsInvited:
+class TestVideoChatParticipantsInvitedNoReq:
     def test_slot_behaviour(self, mro_slots, user1):
         action = VideoChatParticipantsInvited([user1])
         for attr in action.__slots__:
@@ -148,7 +148,7 @@ def test_equality(self, user1, user2):
         assert hash(a) != hash(e)
 
 
-class TestVideoChatScheduled:
+class TestVideoChatScheduledNoReq:
     start_date = dtm.datetime.now(dtm.timezone.utc)
 
     def test_slot_behaviour(self, mro_slots):
diff --git a/tests/test_videonote.py b/tests/test_videonote.py
index 59a62d092d8..c88e27c391c 100644
--- a/tests/test_videonote.py
+++ b/tests/test_videonote.py
@@ -16,6 +16,7 @@
 #
 # You should have received a copy of the GNU Lesser Public License
 # along with this program.  If not, see [http://www.gnu.org/licenses/].
+import asyncio
 import os
 from pathlib import Path
 
@@ -34,30 +35,29 @@
 
 @pytest.fixture(scope="function")
 def video_note_file():
-    f = data_file("telegram2.mp4").open("rb")
-    yield f
-    f.close()
+    with data_file("telegram2.mp4").open("rb") as f:
+        yield f
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 async def video_note(bot, chat_id):
     with data_file("telegram2.mp4").open("rb") as f:
         return (await bot.send_video_note(chat_id, video_note=f, read_timeout=50)).video_note
 
 
-class TestVideoNote:
+class Space:
     length = 240
     duration = 3
     file_size = 132084
-
     thumb_width = 240
     thumb_height = 240
     thumb_file_size = 11547
-
     caption = "VideoNoteTest - Caption"
     videonote_file_id = "5a3128a4d2a04750b5b58397f3b5e812"
     videonote_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
 
+
+class TestVideoNoteNoReq:
     def test_slot_behaviour(self, video_note, mro_slots):
         for attr in video_note.__slots__:
             assert getattr(video_note, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -78,37 +78,10 @@ def test_creation(self, video_note):
         assert video_note.thumb.file_unique_id != ""
 
     def test_expected_values(self, video_note):
-        assert video_note.length == self.length
-        assert video_note.duration == self.duration
-        assert video_note.file_size == self.file_size
+        assert video_note.length == Space.length
+        assert video_note.duration == Space.duration
+        assert video_note.file_size == Space.file_size
 
-    @pytest.mark.flaky(3, 1)
-    async def test_send_all_args(self, bot, chat_id, video_note_file, video_note, thumb_file):
-        message = await bot.send_video_note(
-            chat_id,
-            video_note_file,
-            duration=self.duration,
-            length=self.length,
-            disable_notification=False,
-            protect_content=True,
-            thumb=thumb_file,
-        )
-
-        assert isinstance(message.video_note, VideoNote)
-        assert isinstance(message.video_note.file_id, str)
-        assert isinstance(message.video_note.file_unique_id, str)
-        assert message.video_note.file_id != ""
-        assert message.video_note.file_unique_id != ""
-        assert message.video_note.length == video_note.length
-        assert message.video_note.duration == video_note.duration
-        assert message.video_note.file_size == video_note.file_size
-
-        assert message.video_note.thumb.file_size == self.thumb_file_size
-        assert message.video_note.thumb.width == self.thumb_width
-        assert message.video_note.thumb.height == self.thumb_height
-        assert message.has_protected_content
-
-    @pytest.mark.flaky(3, 1)
     async def test_send_video_note_custom_filename(
         self, bot, chat_id, video_note_file, monkeypatch
     ):
@@ -119,29 +92,6 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs):
 
         assert await bot.send_video_note(chat_id, video_note_file, filename="custom_filename")
 
-    @pytest.mark.flaky(3, 1)
-    async def test_get_and_download(self, bot, video_note):
-        path = Path("telegram2.mp4")
-        if path.is_file():
-            path.unlink()
-
-        new_file = await bot.get_file(video_note.file_id)
-
-        assert new_file.file_size == self.file_size
-        assert new_file.file_id == video_note.file_id
-        assert new_file.file_unique_id == video_note.file_unique_id
-        assert new_file.file_path.startswith("https://")
-
-        await new_file.download_to_drive("telegram2.mp4")
-
-        assert path.is_file()
-
-    @pytest.mark.flaky(3, 1)
-    async def test_resend(self, bot, chat_id, video_note):
-        message = await bot.send_video_note(chat_id, video_note.file_id)
-
-        assert message.video_note == video_note
-
     async def test_send_with_video_note(self, monkeypatch, bot, chat_id, video_note):
         async def make_assertion(url, request_data: RequestData, *args, **kwargs):
             return request_data.json_parameters["video_note"] == video_note.file_id
@@ -152,20 +102,20 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs):
 
     def test_de_json(self, bot):
         json_dict = {
-            "file_id": self.videonote_file_id,
-            "file_unique_id": self.videonote_file_unique_id,
-            "length": self.length,
-            "duration": self.duration,
-            "file_size": self.file_size,
+            "file_id": Space.videonote_file_id,
+            "file_unique_id": Space.videonote_file_unique_id,
+            "length": Space.length,
+            "duration": Space.duration,
+            "file_size": Space.file_size,
         }
         json_video_note = VideoNote.de_json(json_dict, bot)
         assert json_video_note.api_kwargs == {}
 
-        assert json_video_note.file_id == self.videonote_file_id
-        assert json_video_note.file_unique_id == self.videonote_file_unique_id
-        assert json_video_note.length == self.length
-        assert json_video_note.duration == self.duration
-        assert json_video_note.file_size == self.file_size
+        assert json_video_note.file_id == Space.videonote_file_id
+        assert json_video_note.file_unique_id == Space.videonote_file_unique_id
+        assert json_video_note.length == Space.length
+        assert json_video_note.duration == Space.duration
+        assert json_video_note.file_size == Space.file_size
 
     def test_to_dict(self, video_note):
         video_note_dict = video_note.to_dict()
@@ -203,7 +153,88 @@ async def make_assertion(_, data, *args, **kwargs):
         finally:
             bot._local_mode = False
 
-    @pytest.mark.flaky(3, 1)
+    async def test_error_without_required_args(self, bot, chat_id):
+        with pytest.raises(TypeError):
+            await bot.send_video_note(chat_id=chat_id)
+
+    async def test_get_file_instance_method(self, monkeypatch, video_note):
+        async def make_assertion(*_, **kwargs):
+            return kwargs["file_id"] == video_note.file_id
+
+        assert check_shortcut_signature(VideoNote.get_file, Bot.get_file, ["file_id"], [])
+        assert await check_shortcut_call(video_note.get_file, video_note.get_bot(), "get_file")
+        assert await check_defaults_handling(video_note.get_file, video_note.get_bot())
+
+        monkeypatch.setattr(video_note.get_bot(), "get_file", make_assertion)
+        assert await video_note.get_file()
+
+    def test_equality(self, video_note):
+        a = VideoNote(video_note.file_id, video_note.file_unique_id, Space.length, Space.duration)
+        b = VideoNote("", video_note.file_unique_id, Space.length, Space.duration)
+        c = VideoNote(video_note.file_id, video_note.file_unique_id, 0, 0)
+        d = VideoNote("", "", Space.length, Space.duration)
+        e = Voice(video_note.file_id, video_note.file_unique_id, Space.duration)
+
+        assert a == b
+        assert hash(a) == hash(b)
+        assert a is not b
+
+        assert a == c
+        assert hash(a) == hash(c)
+
+        assert a != d
+        assert hash(a) != hash(d)
+
+        assert a != e
+        assert hash(a) != hash(e)
+
+
+class TestVideoNoteReq:
+    async def test_send_all_args(self, bot, chat_id, video_note_file, video_note, thumb_file):
+        message = await bot.send_video_note(
+            chat_id,
+            video_note_file,
+            duration=Space.duration,
+            length=Space.length,
+            disable_notification=False,
+            protect_content=True,
+            thumb=thumb_file,
+        )
+
+        assert isinstance(message.video_note, VideoNote)
+        assert isinstance(message.video_note.file_id, str)
+        assert isinstance(message.video_note.file_unique_id, str)
+        assert message.video_note.file_id != ""
+        assert message.video_note.file_unique_id != ""
+        assert message.video_note.length == video_note.length
+        assert message.video_note.duration == video_note.duration
+        assert message.video_note.file_size == video_note.file_size
+
+        assert message.video_note.thumb.file_size == Space.thumb_file_size
+        assert message.video_note.thumb.width == Space.thumb_width
+        assert message.video_note.thumb.height == Space.thumb_height
+        assert message.has_protected_content
+
+    async def test_get_and_download(self, bot, video_note):
+        path = Path("telegram2.mp4")
+        if path.is_file():
+            path.unlink()
+
+        new_file = await bot.get_file(video_note.file_id)
+
+        assert new_file.file_size == Space.file_size
+        assert new_file.file_id == video_note.file_id
+        assert new_file.file_unique_id == video_note.file_unique_id
+        assert new_file.file_path.startswith("https://")
+
+        await new_file.download_to_drive("telegram2.mp4")
+
+        assert path.is_file()
+
+    async def test_resend(self, bot, chat_id, video_note):
+        message = await bot.send_video_note(chat_id, video_note.file_id)
+        assert message.video_note == video_note
+
     @pytest.mark.parametrize(
         "default_bot,custom",
         [
@@ -237,55 +268,20 @@ async def test_send_video_note_default_allow_sending_without_reply(
                     chat_id, video_note, reply_to_message_id=reply_to_message.message_id
                 )
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
     async def test_send_video_note_default_protect_content(self, chat_id, default_bot, video_note):
-        protected = await default_bot.send_video_note(chat_id, video_note)
+        tasks = asyncio.gather(
+            default_bot.send_video_note(chat_id, video_note),
+            default_bot.send_video_note(chat_id, video_note, protect_content=False),
+        )
+        protected, unprotected = await tasks
         assert protected.has_protected_content
-        unprotected = await default_bot.send_video_note(chat_id, video_note, protect_content=False)
         assert not unprotected.has_protected_content
 
-    @pytest.mark.flaky(3, 1)
     async def test_error_send_empty_file(self, bot, chat_id):
         with pytest.raises(TelegramError):
             await bot.send_video_note(chat_id, open(os.devnull, "rb"))
 
-    @pytest.mark.flaky(3, 1)
     async def test_error_send_empty_file_id(self, bot, chat_id):
         with pytest.raises(TelegramError):
             await bot.send_video_note(chat_id, "")
-
-    async def test_error_without_required_args(self, bot, chat_id):
-        with pytest.raises(TypeError):
-            await bot.send_video_note(chat_id=chat_id)
-
-    async def test_get_file_instance_method(self, monkeypatch, video_note):
-        async def make_assertion(*_, **kwargs):
-            return kwargs["file_id"] == video_note.file_id
-
-        assert check_shortcut_signature(VideoNote.get_file, Bot.get_file, ["file_id"], [])
-        assert await check_shortcut_call(video_note.get_file, video_note.get_bot(), "get_file")
-        assert await check_defaults_handling(video_note.get_file, video_note.get_bot())
-
-        monkeypatch.setattr(video_note.get_bot(), "get_file", make_assertion)
-        assert await video_note.get_file()
-
-    def test_equality(self, video_note):
-        a = VideoNote(video_note.file_id, video_note.file_unique_id, self.length, self.duration)
-        b = VideoNote("", video_note.file_unique_id, self.length, self.duration)
-        c = VideoNote(video_note.file_id, video_note.file_unique_id, 0, 0)
-        d = VideoNote("", "", self.length, self.duration)
-        e = Voice(video_note.file_id, video_note.file_unique_id, self.duration)
-
-        assert a == b
-        assert hash(a) == hash(b)
-        assert a is not b
-
-        assert a == c
-        assert hash(a) == hash(c)
-
-        assert a != d
-        assert hash(a) != hash(d)
-
-        assert a != e
-        assert hash(a) != hash(e)
diff --git a/tests/test_voice.py b/tests/test_voice.py
index 722fdb17593..4c5e7c2c92f 100644
--- a/tests/test_voice.py
+++ b/tests/test_voice.py
@@ -16,6 +16,7 @@
 #
 # You should have received a copy of the GNU Lesser Public License
 # along with this program.  If not, see [http://www.gnu.org/licenses/].
+import asyncio
 import os
 from pathlib import Path
 
@@ -35,28 +36,27 @@
 
 @pytest.fixture(scope="function")
 def voice_file():
-    f = data_file("telegram.ogg").open("rb")
-    yield f
-    f.close()
+    with data_file("telegram.ogg").open("rb") as f:
+        yield f
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 async def voice(bot, chat_id):
     with data_file("telegram.ogg").open("rb") as f:
         return (await bot.send_voice(chat_id, voice=f, read_timeout=50)).voice
 
 
-class TestVoice:
+class Space:
     duration = 3
     mime_type = "audio/ogg"
     file_size = 9199
-
     caption = "Test *voice*"
     voice_file_url = "https://python-telegram-bot.org/static/testfiles/telegram.ogg"
-
     voice_file_id = "5a3128a4d2a04750b5b58397f3b5e812"
     voice_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e"
 
+
+class TestVoiceNoReq:
     def test_slot_behaviour(self, voice, mro_slots):
         for attr in voice.__slots__:
             assert getattr(voice, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -71,17 +71,118 @@ async def test_creation(self, voice):
         assert voice.file_unique_id != ""
 
     def test_expected_values(self, voice):
-        assert voice.duration == self.duration
-        assert voice.mime_type == self.mime_type
-        assert voice.file_size == self.file_size
+        assert voice.duration == Space.duration
+        assert voice.mime_type == Space.mime_type
+        assert voice.file_size == Space.file_size
+
+    async def test_send_voice_custom_filename(self, bot, chat_id, voice_file, monkeypatch):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            return list(request_data.multipart_data.values())[0][0] == "custom_filename"
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+
+        assert await bot.send_voice(chat_id, voice_file, filename="custom_filename")
+
+    async def test_send_with_voice(self, monkeypatch, bot, chat_id, voice):
+        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
+            return request_data.json_parameters["voice"] == voice.file_id
+
+        monkeypatch.setattr(bot.request, "post", make_assertion)
+        message = await bot.send_voice(chat_id, voice=voice)
+        assert message
+
+    @pytest.mark.parametrize("local_mode", [True, False])
+    async def test_send_voice_local_files(self, monkeypatch, bot, chat_id, local_mode):
+        try:
+            bot._local_mode = local_mode
+            # For just test that the correct paths are passed as we have no local bot API set up
+            test_flag = False
+            file = data_file("telegram.jpg")
+            expected = file.as_uri()
+
+            async def make_assertion(_, data, *args, **kwargs):
+                nonlocal test_flag
+                if local_mode:
+                    test_flag = data.get("voice") == expected
+                else:
+                    test_flag = isinstance(data.get("voice"), InputFile)
+
+            monkeypatch.setattr(bot, "_post", make_assertion)
+            await bot.send_voice(chat_id, file)
+            assert test_flag
+        finally:
+            bot._local_mode = False
+
+    def test_de_json(self, bot):
+        json_dict = {
+            "file_id": Space.voice_file_id,
+            "file_unique_id": Space.voice_file_unique_id,
+            "duration": Space.duration,
+            "mime_type": Space.mime_type,
+            "file_size": Space.file_size,
+        }
+        json_voice = Voice.de_json(json_dict, bot)
+        assert json_voice.api_kwargs == {}
+
+        assert json_voice.file_id == Space.voice_file_id
+        assert json_voice.file_unique_id == Space.voice_file_unique_id
+        assert json_voice.duration == Space.duration
+        assert json_voice.mime_type == Space.mime_type
+        assert json_voice.file_size == Space.file_size
+
+    def test_to_dict(self, voice):
+        voice_dict = voice.to_dict()
+
+        assert isinstance(voice_dict, dict)
+        assert voice_dict["file_id"] == voice.file_id
+        assert voice_dict["file_unique_id"] == voice.file_unique_id
+        assert voice_dict["duration"] == voice.duration
+        assert voice_dict["mime_type"] == voice.mime_type
+        assert voice_dict["file_size"] == voice.file_size
+
+    async def test_error_without_required_args(self, bot, chat_id):
+        with pytest.raises(TypeError):
+            await bot.sendVoice(chat_id)
+
+    async def test_get_file_instance_method(self, monkeypatch, voice):
+        async def make_assertion(*_, **kwargs):
+            return kwargs["file_id"] == voice.file_id
+
+        assert check_shortcut_signature(Voice.get_file, Bot.get_file, ["file_id"], [])
+        assert await check_shortcut_call(voice.get_file, voice.get_bot(), "get_file")
+        assert await check_defaults_handling(voice.get_file, voice.get_bot())
+
+        monkeypatch.setattr(voice.get_bot(), "get_file", make_assertion)
+        assert await voice.get_file()
+
+    def test_equality(self, voice):
+        a = Voice(voice.file_id, voice.file_unique_id, Space.duration)
+        b = Voice("", voice.file_unique_id, Space.duration)
+        c = Voice(voice.file_id, voice.file_unique_id, 0)
+        d = Voice("", "", Space.duration)
+        e = Audio(voice.file_id, voice.file_unique_id, Space.duration)
+
+        assert a == b
+        assert hash(a) == hash(b)
+        assert a is not b
+
+        assert a == c
+        assert hash(a) == hash(c)
+
+        assert a != d
+        assert hash(a) != hash(d)
+
+        assert a != e
+        assert hash(a) != hash(e)
+
 
-    @pytest.mark.flaky(3, 1)
+class TestVoiceReq:
     async def test_send_all_args(self, bot, chat_id, voice_file, voice):
         message = await bot.send_voice(
             chat_id,
             voice_file,
-            duration=self.duration,
-            caption=self.caption,
+            duration=Space.duration,
+            caption=Space.caption,
             disable_notification=False,
             protect_content=True,
             parse_mode="Markdown",
@@ -95,19 +196,9 @@ async def test_send_all_args(self, bot, chat_id, voice_file, voice):
         assert message.voice.duration == voice.duration
         assert message.voice.mime_type == voice.mime_type
         assert message.voice.file_size == voice.file_size
-        assert message.caption == self.caption.replace("*", "")
+        assert message.caption == Space.caption.replace("*", "")
         assert message.has_protected_content
 
-    @pytest.mark.flaky(3, 1)
-    async def test_send_voice_custom_filename(self, bot, chat_id, voice_file, monkeypatch):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            return list(request_data.multipart_data.values())[0][0] == "custom_filename"
-
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-
-        assert await bot.send_voice(chat_id, voice_file, filename="custom_filename")
-
-    @pytest.mark.flaky(3, 1)
     async def test_get_and_download(self, bot, voice):
         path = Path("telegram.ogg")
         if path.is_file():
@@ -124,9 +215,8 @@ async def test_get_and_download(self, bot, voice):
 
         assert path.is_file()
 
-    @pytest.mark.flaky(3, 1)
     async def test_send_ogg_url_file(self, bot, chat_id, voice):
-        message = await bot.sendVoice(chat_id, self.voice_file_url, duration=self.duration)
+        message = await bot.sendVoice(chat_id, Space.voice_file_url, duration=Space.duration)
 
         assert isinstance(message.voice, Voice)
         assert isinstance(message.voice.file_id, str)
@@ -137,21 +227,11 @@ async def test_send_ogg_url_file(self, bot, chat_id, voice):
         assert message.voice.mime_type == voice.mime_type
         assert message.voice.file_size == voice.file_size
 
-    @pytest.mark.flaky(3, 1)
     async def test_resend(self, bot, chat_id, voice):
         message = await bot.sendVoice(chat_id, voice.file_id)
 
         assert message.voice == voice
 
-    async def test_send_with_voice(self, monkeypatch, bot, chat_id, voice):
-        async def make_assertion(url, request_data: RequestData, *args, **kwargs):
-            return request_data.json_parameters["voice"] == voice.file_id
-
-        monkeypatch.setattr(bot.request, "post", make_assertion)
-        message = await bot.send_voice(chat_id, voice=voice)
-        assert message
-
-    @pytest.mark.flaky(3, 1)
     async def test_send_voice_caption_entities(self, bot, chat_id, voice_file):
         test_string = "Italic Bold Code"
         entities = [
@@ -166,7 +246,6 @@ async def test_send_voice_caption_entities(self, bot, chat_id, voice_file):
         assert message.caption == test_string
         assert message.caption_entities == tuple(entities)
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_send_voice_default_parse_mode_1(self, default_bot, chat_id, voice):
         test_string = "Italic Bold Code"
@@ -176,7 +255,6 @@ async def test_send_voice_default_parse_mode_1(self, default_bot, chat_id, voice
         assert message.caption_markdown == test_markdown_string
         assert message.caption == test_string
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_send_voice_default_parse_mode_2(self, default_bot, chat_id, voice):
         test_markdown_string = "_Italic_ *Bold* `Code`"
@@ -187,7 +265,6 @@ async def test_send_voice_default_parse_mode_2(self, default_bot, chat_id, voice
         assert message.caption == test_markdown_string
         assert message.caption_markdown == escape_markdown(test_markdown_string)
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True)
     async def test_send_voice_default_parse_mode_3(self, default_bot, chat_id, voice):
         test_markdown_string = "_Italic_ *Bold* `Code`"
@@ -198,37 +275,16 @@ async def test_send_voice_default_parse_mode_3(self, default_bot, chat_id, voice
         assert message.caption == test_markdown_string
         assert message.caption_markdown == escape_markdown(test_markdown_string)
 
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
     async def test_send_voice_default_protect_content(self, chat_id, default_bot, voice):
-        protected = await default_bot.send_voice(chat_id, voice)
+        tasks = asyncio.gather(
+            default_bot.send_voice(chat_id, voice),
+            default_bot.send_voice(chat_id, voice, protect_content=False),
+        )
+        protected, unprotected = await tasks
         assert protected.has_protected_content
-        unprotected = await default_bot.send_voice(chat_id, voice, protect_content=False)
         assert not unprotected.has_protected_content
 
-    @pytest.mark.parametrize("local_mode", [True, False])
-    async def test_send_voice_local_files(self, monkeypatch, bot, chat_id, local_mode):
-        try:
-            bot._local_mode = local_mode
-            # For just test that the correct paths are passed as we have no local bot API set up
-            test_flag = False
-            file = data_file("telegram.jpg")
-            expected = file.as_uri()
-
-            async def make_assertion(_, data, *args, **kwargs):
-                nonlocal test_flag
-                if local_mode:
-                    test_flag = data.get("voice") == expected
-                else:
-                    test_flag = isinstance(data.get("voice"), InputFile)
-
-            monkeypatch.setattr(bot, "_post", make_assertion)
-            await bot.send_voice(chat_id, file)
-            assert test_flag
-        finally:
-            bot._local_mode = False
-
-    @pytest.mark.flaky(3, 1)
     @pytest.mark.parametrize(
         "default_bot,custom",
         [
@@ -262,74 +318,10 @@ async def test_send_voice_default_allow_sending_without_reply(
                     chat_id, voice, reply_to_message_id=reply_to_message.message_id
                 )
 
-    def test_de_json(self, bot):
-        json_dict = {
-            "file_id": self.voice_file_id,
-            "file_unique_id": self.voice_file_unique_id,
-            "duration": self.duration,
-            "mime_type": self.mime_type,
-            "file_size": self.file_size,
-        }
-        json_voice = Voice.de_json(json_dict, bot)
-        assert json_voice.api_kwargs == {}
-
-        assert json_voice.file_id == self.voice_file_id
-        assert json_voice.file_unique_id == self.voice_file_unique_id
-        assert json_voice.duration == self.duration
-        assert json_voice.mime_type == self.mime_type
-        assert json_voice.file_size == self.file_size
-
-    def test_to_dict(self, voice):
-        voice_dict = voice.to_dict()
-
-        assert isinstance(voice_dict, dict)
-        assert voice_dict["file_id"] == voice.file_id
-        assert voice_dict["file_unique_id"] == voice.file_unique_id
-        assert voice_dict["duration"] == voice.duration
-        assert voice_dict["mime_type"] == voice.mime_type
-        assert voice_dict["file_size"] == voice.file_size
-
-    @pytest.mark.flaky(3, 1)
     async def test_error_send_empty_file(self, bot, chat_id):
         with pytest.raises(TelegramError):
             await bot.sendVoice(chat_id, open(os.devnull, "rb"))
 
-    @pytest.mark.flaky(3, 1)
     async def test_error_send_empty_file_id(self, bot, chat_id):
         with pytest.raises(TelegramError):
             await bot.sendVoice(chat_id, "")
-
-    async def test_error_without_required_args(self, bot, chat_id):
-        with pytest.raises(TypeError):
-            await bot.sendVoice(chat_id)
-
-    async def test_get_file_instance_method(self, monkeypatch, voice):
-        async def make_assertion(*_, **kwargs):
-            return kwargs["file_id"] == voice.file_id
-
-        assert check_shortcut_signature(Voice.get_file, Bot.get_file, ["file_id"], [])
-        assert await check_shortcut_call(voice.get_file, voice.get_bot(), "get_file")
-        assert await check_defaults_handling(voice.get_file, voice.get_bot())
-
-        monkeypatch.setattr(voice.get_bot(), "get_file", make_assertion)
-        assert await voice.get_file()
-
-    def test_equality(self, voice):
-        a = Voice(voice.file_id, voice.file_unique_id, self.duration)
-        b = Voice("", voice.file_unique_id, self.duration)
-        c = Voice(voice.file_id, voice.file_unique_id, 0)
-        d = Voice("", "", self.duration)
-        e = Audio(voice.file_id, voice.file_unique_id, self.duration)
-
-        assert a == b
-        assert hash(a) == hash(b)
-        assert a is not b
-
-        assert a == c
-        assert hash(a) == hash(c)
-
-        assert a != d
-        assert hash(a) != hash(d)
-
-        assert a != e
-        assert hash(a) != hash(e)
diff --git a/tests/test_webappdata.py b/tests/test_webappdata.py
index 618d8e53a58..7f13d6c7d43 100644
--- a/tests/test_webappdata.py
+++ b/tests/test_webappdata.py
@@ -22,18 +22,17 @@
 from telegram import WebAppData
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def web_app_data():
-    return WebAppData(
-        data=TestWebAppData.data,
-        button_text=TestWebAppData.button_text,
-    )
+    return WebAppData(data=Space.data, button_text=Space.button_text)
 
 
-class TestWebAppData:
+class Space:
     data = "data"
     button_text = "button_text"
 
+
+class TestWebAppDataNoReq:
     def test_slot_behaviour(self, web_app_data, mro_slots):
         for attr in web_app_data.__slots__:
             assert getattr(web_app_data, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -43,20 +42,20 @@ def test_to_dict(self, web_app_data):
         web_app_data_dict = web_app_data.to_dict()
 
         assert isinstance(web_app_data_dict, dict)
-        assert web_app_data_dict["data"] == self.data
-        assert web_app_data_dict["button_text"] == self.button_text
+        assert web_app_data_dict["data"] == Space.data
+        assert web_app_data_dict["button_text"] == Space.button_text
 
     def test_de_json(self, bot):
-        json_dict = {"data": self.data, "button_text": self.button_text}
+        json_dict = {"data": Space.data, "button_text": Space.button_text}
         web_app_data = WebAppData.de_json(json_dict, bot)
         assert web_app_data.api_kwargs == {}
 
-        assert web_app_data.data == self.data
-        assert web_app_data.button_text == self.button_text
+        assert web_app_data.data == Space.data
+        assert web_app_data.button_text == Space.button_text
 
     def test_equality(self):
-        a = WebAppData(self.data, self.button_text)
-        b = WebAppData(self.data, self.button_text)
+        a = WebAppData(Space.data, Space.button_text)
+        b = WebAppData(Space.data, Space.button_text)
         c = WebAppData("", "")
         d = WebAppData("not_data", "not_button_text")
 
diff --git a/tests/test_webappinfo.py b/tests/test_webappinfo.py
index 42fb0c48e69..96c49a50c9a 100644
--- a/tests/test_webappinfo.py
+++ b/tests/test_webappinfo.py
@@ -22,14 +22,16 @@
 from telegram import WebAppInfo
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def web_app_info():
-    return WebAppInfo(url=TestWebAppInfo.url)
+    return WebAppInfo(url=Space.url)
 
 
-class TestWebAppInfo:
+class Space:
     url = "https://www.example.com"
 
+
+class TestWebAppInfoNoReq:
     def test_slot_behaviour(self, web_app_info, mro_slots):
         for attr in web_app_info.__slots__:
             assert getattr(web_app_info, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -39,18 +41,18 @@ def test_to_dict(self, web_app_info):
         web_app_info_dict = web_app_info.to_dict()
 
         assert isinstance(web_app_info_dict, dict)
-        assert web_app_info_dict["url"] == self.url
+        assert web_app_info_dict["url"] == Space.url
 
     def test_de_json(self, bot):
-        json_dict = {"url": self.url}
+        json_dict = {"url": Space.url}
         web_app_info = WebAppInfo.de_json(json_dict, bot)
         assert web_app_info.api_kwargs == {}
 
-        assert web_app_info.url == self.url
+        assert web_app_info.url == Space.url
 
     def test_equality(self):
-        a = WebAppInfo(self.url)
-        b = WebAppInfo(self.url)
+        a = WebAppInfo(Space.url)
+        b = WebAppInfo(Space.url)
         c = WebAppInfo("")
         d = WebAppInfo("not_url")
 
diff --git a/tests/test_webhookinfo.py b/tests/test_webhookinfo.py
index 575f11abfb9..2c28c1361e1 100644
--- a/tests/test_webhookinfo.py
+++ b/tests/test_webhookinfo.py
@@ -25,21 +25,21 @@
 from telegram._utils.datetime import from_timestamp
 
 
-@pytest.fixture(scope="class")
+@pytest.fixture(scope="module")
 def webhook_info():
     return WebhookInfo(
-        url=TestWebhookInfo.url,
-        has_custom_certificate=TestWebhookInfo.has_custom_certificate,
-        pending_update_count=TestWebhookInfo.pending_update_count,
-        ip_address=TestWebhookInfo.ip_address,
-        last_error_date=TestWebhookInfo.last_error_date,
-        max_connections=TestWebhookInfo.max_connections,
-        allowed_updates=TestWebhookInfo.allowed_updates,
-        last_synchronization_error_date=TestWebhookInfo.last_synchronization_error_date,
+        url=Space.url,
+        has_custom_certificate=Space.has_custom_certificate,
+        pending_update_count=Space.pending_update_count,
+        ip_address=Space.ip_address,
+        last_error_date=Space.last_error_date,
+        max_connections=Space.max_connections,
+        allowed_updates=Space.allowed_updates,
+        last_synchronization_error_date=Space.last_synchronization_error_date,
     )
 
 
-class TestWebhookInfo:
+class Space:
     url = "http://www.google.com"
     has_custom_certificate = False
     pending_update_count = 5
@@ -49,6 +49,8 @@ class TestWebhookInfo:
     allowed_updates = ["type1", "type2"]
     last_synchronization_error_date = time.time()
 
+
+class TestWebhookInfoNoReq:
     def test_slot_behaviour(self, webhook_info, mro_slots):
         for attr in webhook_info.__slots__:
             assert getattr(webhook_info, attr, "err") != "err", f"got extra slot '{attr}'"
@@ -58,42 +60,42 @@ def test_to_dict(self, webhook_info):
         webhook_info_dict = webhook_info.to_dict()
 
         assert isinstance(webhook_info_dict, dict)
-        assert webhook_info_dict["url"] == self.url
-        assert webhook_info_dict["pending_update_count"] == self.pending_update_count
-        assert webhook_info_dict["last_error_date"] == self.last_error_date
-        assert webhook_info_dict["max_connections"] == self.max_connections
-        assert webhook_info_dict["allowed_updates"] == self.allowed_updates
-        assert webhook_info_dict["ip_address"] == self.ip_address
+        assert webhook_info_dict["url"] == Space.url
+        assert webhook_info_dict["pending_update_count"] == Space.pending_update_count
+        assert webhook_info_dict["last_error_date"] == Space.last_error_date
+        assert webhook_info_dict["max_connections"] == Space.max_connections
+        assert webhook_info_dict["allowed_updates"] == Space.allowed_updates
+        assert webhook_info_dict["ip_address"] == Space.ip_address
         assert (
             webhook_info_dict["last_synchronization_error_date"]
-            == self.last_synchronization_error_date
+            == Space.last_synchronization_error_date
         )
 
     def test_de_json(self, bot):
         json_dict = {
-            "url": self.url,
-            "has_custom_certificate": self.has_custom_certificate,
-            "pending_update_count": self.pending_update_count,
-            "last_error_date": self.last_error_date,
-            "max_connections": self.max_connections,
-            "allowed_updates": self.allowed_updates,
-            "ip_address": self.ip_address,
-            "last_synchronization_error_date": self.last_synchronization_error_date,
+            "url": Space.url,
+            "has_custom_certificate": Space.has_custom_certificate,
+            "pending_update_count": Space.pending_update_count,
+            "last_error_date": Space.last_error_date,
+            "max_connections": Space.max_connections,
+            "allowed_updates": Space.allowed_updates,
+            "ip_address": Space.ip_address,
+            "last_synchronization_error_date": Space.last_synchronization_error_date,
         }
         webhook_info = WebhookInfo.de_json(json_dict, bot)
         assert webhook_info.api_kwargs == {}
 
-        assert webhook_info.url == self.url
-        assert webhook_info.has_custom_certificate == self.has_custom_certificate
-        assert webhook_info.pending_update_count == self.pending_update_count
+        assert webhook_info.url == Space.url
+        assert webhook_info.has_custom_certificate == Space.has_custom_certificate
+        assert webhook_info.pending_update_count == Space.pending_update_count
         assert isinstance(webhook_info.last_error_date, datetime)
-        assert webhook_info.last_error_date == from_timestamp(self.last_error_date)
-        assert webhook_info.max_connections == self.max_connections
-        assert webhook_info.allowed_updates == tuple(self.allowed_updates)
-        assert webhook_info.ip_address == self.ip_address
+        assert webhook_info.last_error_date == from_timestamp(Space.last_error_date)
+        assert webhook_info.max_connections == Space.max_connections
+        assert webhook_info.allowed_updates == tuple(Space.allowed_updates)
+        assert webhook_info.ip_address == Space.ip_address
         assert isinstance(webhook_info.last_synchronization_error_date, datetime)
         assert webhook_info.last_synchronization_error_date == from_timestamp(
-            self.last_synchronization_error_date
+            Space.last_synchronization_error_date
         )
 
         none = WebhookInfo.de_json(None, bot)
@@ -101,24 +103,24 @@ def test_de_json(self, bot):
 
     def test_always_tuple_allowed_updates(self):
         webhook_info = WebhookInfo(
-            self.url, self.has_custom_certificate, self.pending_update_count
+            Space.url, Space.has_custom_certificate, Space.pending_update_count
         )
         assert webhook_info.allowed_updates == ()
 
     def test_equality(self):
         a = WebhookInfo(
-            url=self.url,
-            has_custom_certificate=self.has_custom_certificate,
-            pending_update_count=self.pending_update_count,
-            last_error_date=self.last_error_date,
-            max_connections=self.max_connections,
+            url=Space.url,
+            has_custom_certificate=Space.has_custom_certificate,
+            pending_update_count=Space.pending_update_count,
+            last_error_date=Space.last_error_date,
+            max_connections=Space.max_connections,
         )
         b = WebhookInfo(
-            url=self.url,
-            has_custom_certificate=self.has_custom_certificate,
-            pending_update_count=self.pending_update_count,
-            last_error_date=self.last_error_date,
-            max_connections=self.max_connections,
+            url=Space.url,
+            has_custom_certificate=Space.has_custom_certificate,
+            pending_update_count=Space.pending_update_count,
+            last_error_date=Space.last_error_date,
+            max_connections=Space.max_connections,
         )
         c = WebhookInfo(
             url="http://github.com",


Code review comments:
diff_hunk: @@ -170,57 +172,61 @@ def test_equality(self):
 
 class TestInvoiceReq:
     async def test_send_required_args_only(self, bot, chat_id, provider_token):
-        message = await bot.send_invoice(
-            chat_id=chat_id,
-            title=Space.title,
-            description=Space.description,
-            payload=Space.payload,
-            provider_token=provider_token,
-            currency=Space.currency,
-            prices=Space.prices,
+        send_inv_task = asyncio.create_task(
+            bot.send_invoice(
+                chat_id=chat_id,
+                title=Space.title,
+                description=Space.description,
+                payload=Space.payload,
+                provider_token=provider_token,
+                currency=Space.currency,
+                prices=Space.prices,
+            )
+        )
+        create_inv_link_task = asyncio.create_task(
+            bot.create_invoice_link(
+                title=Space.title,
+                description=Space.description,
+                payload=Space.payload,
+                provider_token=provider_token,
+                currency=Space.currency,
+                prices=Space.prices,
+            )
path: tests/test_invoice.py
text: @user1:
please revert the changes for this tests, the tasks are not gathered and this decreases readeability IMO

diff_hunk: @@ -131,23 +130,23 @@ def test_bot_api_version_info(self):
 
 class TestConstantsReq:
     async def test_max_message_length(self, bot, chat_id):
-        await bot.send_message(chat_id=chat_id, text="a" * constants.MessageLimit.MAX_TEXT_LENGTH)
-
-        with pytest.raises(
-            BadRequest,
-            match="Message is too long",
-        ):
-            await bot.send_message(
-                chat_id=chat_id, text="a" * (constants.MessageLimit.MAX_TEXT_LENGTH + 1)
-            )
+        tasks = asyncio.gather(
+            bot.send_message(chat_id, text="a" * constants.MessageLimit.MAX_TEXT_LENGTH),
+            bot.send_message(chat_id, text="a" * (constants.MessageLimit.MAX_TEXT_LENGTH + 1)),
+            return_exceptions=True,
+        )
+        results = await tasks
+        assert len(results) == 2
+        assert isinstance(results[1], BadRequest) and "Message is too long" in str(results[1])
path: tests/test_constants.py
text: @user1:
please use the `good_msg, bad_msg` thingy as below in `max_caption_length`

diff_hunk: @@ -170,57 +172,61 @@ def test_equality(self):
 
 class TestInvoiceReq:
     async def test_send_required_args_only(self, bot, chat_id, provider_token):
-        message = await bot.send_invoice(
-            chat_id=chat_id,
-            title=Space.title,
-            description=Space.description,
-            payload=Space.payload,
-            provider_token=provider_token,
-            currency=Space.currency,
-            prices=Space.prices,
+        send_inv_task = asyncio.create_task(
+            bot.send_invoice(
+                chat_id=chat_id,
+                title=Space.title,
+                description=Space.description,
+                payload=Space.payload,
+                provider_token=provider_token,
+                currency=Space.currency,
+                prices=Space.prices,
+            )
+        )
+        create_inv_link_task = asyncio.create_task(
+            bot.create_invoice_link(
+                title=Space.title,
+                description=Space.description,
+                payload=Space.payload,
+                provider_token=provider_token,
+                currency=Space.currency,
+                prices=Space.prices,
+            )
         )
 
+        message = await send_inv_task
         assert message.invoice.currency == Space.currency
         assert message.invoice.start_parameter == ""
         assert message.invoice.description == Space.description
         assert message.invoice.title == Space.title
         assert message.invoice.total_amount == Space.total_amount
 
-        link = await bot.create_invoice_link(
-            title=Space.title,
-            description=Space.description,
-            payload=Space.payload,
-            provider_token=provider_token,
-            currency=Space.currency,
-            prices=Space.prices,
-        )
+        link = await create_inv_link_task
         assert isinstance(link, str)
         assert link != ""
+        assert send_inv_task.done() and create_inv_link_task.done()
 
     @pytest.mark.parametrize("default_bot", [{"protect_content": True}], indirect=True)
     async def test_send_invoice_default_protect_content(
         self, chat_id, default_bot, provider_token
     ):
-        protected = await default_bot.send_invoice(
-            chat_id,
-            Space.title,
-            Space.description,
-            Space.payload,
-            provider_token,
-            Space.currency,
-            Space.prices,
+        tasks = asyncio.gather(
+            *(
+                default_bot.send_invoice(
+                    chat_id,
+                    Space.title,
+                    Space.description,
+                    Space.payload,
+                    provider_token,
+                    Space.currency,
+                    Space.prices,
+                    **i,
+                )
+                for i in ({}, {"protect_content": False})
path: tests/test_invoice.py
text: @user1:
`i` -> `kwargs`

diff_hunk: @@ -157,23 +158,18 @@ async def test_get_and_download(self, bot, chat_photo):
         if jpg_file.is_file():
             jpg_file.unlink()
 
-        new_file = await bot.get_file(chat_photo.small_file_id)
+        tasks = {bot.get_file(chat_photo.small_file_id), bot.get_file(chat_photo.big_file_id)}
 
-        assert new_file.file_unique_id == chat_photo.small_file_unique_id
-        assert new_file.file_path.startswith("https://")
+        for task in asyncio.as_completed(tasks):
+            file = await task
+            assert file.file_unique_id in (
+                chat_photo.small_file_unique_id,
+                chat_photo.big_file_unique_id,
+            )
path: tests/test_chatphoto.py
text: @user1:
I would prefer if we could make the precise assertion