aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_helpers.py (follow)
Commit message (Collapse)AuthorAgeLines
* Appeased the linterGravatar Xithrius2023-11-08-1/+0
|
* Migrate code style to ruffGravatar Chris Lovering2023-04-11-15/+14
| | | | | Co-authored-by: Boris Muratov <[email protected]> Co-authored-by: wookie184 <[email protected]>
* fix "isistance" typoGravatar Amrou Bellalouna2022-09-16-1/+1
|
* Update test helpers with breaking d.py changesGravatar Chris Lovering2022-04-18-1/+1
| | | | | | | region was removed from the guild object, so this has been replaced with features add_cog is now async, so it is now an async_mock during tests Two new required voice_channel attrs were added channel.type is required to be set to ChannelType due to a new isinstance check in d.py
* Revert "Update all references of discord.py to disnake"Gravatar Chris Lovering2022-03-15-14/+14
| | | | This reverts commit 960619c23300c56c8aaa454edc7241e2badf80ad.
* Update all references of discord.py to disnakeGravatar Chris Lovering2022-03-05-14/+14
| | | | All of the tag content is out of scope for this PR.
* Use unittest's AsyncMock instead of our AsyncMockGravatar Sebastiaan Zeeff2020-02-23-53/+10
| | | | | | Python 3.8 introduced an `unittest.mock.AsyncMock` class that can be used to mock coroutines and other types of asynchronous operations like async iterators and async context managers. As we were using our custom, but limited, AsyncMock, I have replaced our mock with unittest's AsyncMock. Since Python 3.8 also introduces a different way of automatically detecting which attributes should be mocked with an AsyncMock, I've changed our CustomMockMixin to use this new method as well. Together with a couple other small changes, this means that our Custom Mocks now use a lazy method of detecting coroutine attributes, which significantly speeds up the test suite.
* Use IsolatedAsyncioTestCase instead of async_testGravatar Sebastiaan Zeeff2020-02-23-8/+0
| | | | Since we upgraded to Python 3.8, we can now use the new IsolatedAsyncioTestCase test class to use coroutine-based test methods instead of our own, custom async_test decorator. I have changed the base class for all of our test classes that use coroutine-based test methods and removed the now obsolete decorator from our helpers.
* Prevent await warnings for MockBot's create_taskGravatar Sebastiaan Zeeff2019-11-13-0/+12
| | | | | | | Previously, the coroutine object passed to `MockBot.loop.create_task` would trigger a `RuntimeWarning` for not being awaited as we do not actually create a task for it. To prevent these warnings, coroutine objects passed will now automatically be closed.
* Prevent setting unknown attributes on d.py mocksGravatar Sebastiaan Zeeff2019-11-13-67/+32
| | | | | | | | | | | | | | | | Our custom `discord.py` now follow the specifications of the object they are mocking more strictly by using the `spec_set` instead of the `spec` kwarg to initialize the specifications. This means that trying to set an attribute that does not follow the specifications will now also result in an `AttributeError`. To make sure we are not trying to set illegal attributes during the default initialization of the mock objects, I've changed the way we handle default values of parameters. This does introduce a breaking change: Instead of passing a `suffix_id`, the `id` attribute should now be passed using the exact name. `id`. This commit also makes sure existing tests follow this change.
* Enhance custom mock helpersGravatar Sebastiaan Zeeff2019-10-30-4/+54
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | I have enhanced the custom mocks defined in `tests/helpers.py` in a couple of important ways. 1. Automatically create AsyncMock attributes using `inspect` Our previous approach, hard-coding AsynckMock attributes for all the coroutine function methods defined for the class we are trying to mock is prone to human error and not resilient against changes introduced in updates of the library we are using. Instead, I have now created a helper method in our `CustomMockMixin` (formerly `GetChildMockMixin`) that automatically inspects the spec instance we've passed for `coroutine functions` using the `inspect` module. It then sets the according attributes with instances of the AsyncMock class. There is one caveat: `discord.py` very rarely defines regular methods that return a coroutine object. Since the returned coroutine should still be awaited, these regular methods should also be mocked with an AsyncMock. However, since they are regular methods, `inspect` does not detect them and they have to be added manually. (The only case of this I've found so far is `Client.wait_for`.) 2. Properly set special attributes using `kwargs.get` As we want attributes that point to other discord.py objects to use our custom mocks (.e.g, `Message.author` should use `MockMember`), the `__init__` method of our custom mocks make sure to correctly instantiate these attributes. However, the way we previously did that means we can't instantiate the custom mock with a mock instance we provide, since this special instantiation would overwrite the custom object we'd passed. I've solved this by using `kwargs.get`, with a new mock as the default value. This makes sure we only create a new mock if we didn't pass a custom one: ```py class MockMesseage: def __init__(self, **kwargs): self.author = kwargs.get('author', MockMember()) ``` As you can see, we will only create a new MockMember if we did not pass an `author` argument. 3. Factoring out duplicate lines Since our `CustomMockMixin` is a parent to all of our custom mock types, it makes sense to use it to factor out common code of all of our custom mocks. I've made the following changes: - Set a default child mock type in the mixin. - Create an `__init__` that takes care of the `inspect` of point 1 This means we won't have to repeat this in all of the child classes. 4. Three new Mock types: Emoji, PartialEmoji, and Reaction I have added three more custom mocks: - MockEmoji - MockPartialEmoji - MockReaction
* Change generation of child mocksGravatar Sebastiaan Zeeff2019-10-28-3/+15
| | | | | | | | | | | | | | | | | | | | | | | | - https://docs.python.org/3/library/unittest.mock.html We previously used an override of the `__new__` method to prevent our custom mock types from instantiating their children with their own type instead of a general mock type like `MagicMock` or `Mock`. As it turns out, the Python documentation suggests another method of doing this that does not involve overriding `__new__`. This commit implements this new method to make sure we're using the idiomatic way of handling this. The suggested method is overriding the `_get_child_mock` method in the subclass. To make our code DRY, I've created a mixin that should come BEFORE the mock type we're subclassing in the MRO. --- In addition, I have also added this new mixin to our `AsyncMock` class to make sure that its `__call__` method returns a proper mock object after it has been awaited. This makes sure that subsequent attribute access on the returned object is mocked as expected.
* Add more specialized Mocks to tests.helpersGravatar Sebastiaan Zeeff2019-10-14-179/+206
| | | | | | | | | | | | | | | | | | This commit introduces some new Mock-types to the already existing Mock-types for discord.py objects. The total list is now: - MockGuild - MockRole - MockMember - MockBot - MockContext - MockTextChannel - MockMessage In addition, I've added all coroutines in the documentation for these discord.py objects as `AsyncMock` attributes to ease testing. Tests ensure that the attributes set for the Mocks exist for the actual discord.py objects as well.
* Migrate pytest to unittestGravatar Sebastiaan Zeeff2019-10-11-0/+339
After a discussion in the core developers channel, we have decided to migrate from `pytest` to `unittest` as the testing framework. This commit sets up the repository to use `unittest` and migrates the first couple of tests files to the new framework. What I have done to migrate to `unitest`: - Removed all `pytest` test files, since they are incompatible. - Removed `pytest`-related dependencies from the Pipfile. - Added `coverage.py` to the Pipfile dev-packages and relocked. - Added convenience scripts to Pipfile for running the test suite. - Adjust to `azure-pipelines.yml` to use `coverage.py` and `unittest`. - Migrated four test files from `pytest` to `unittest` format. In addition, I've added five helper Mock subclasses in `helpers.py` and created a `TestCase` subclass in `base.py` to add an assertion that asserts that no log records were logged within the context of the context manager. Obviously, these new utility functions and classes are fully tested in their respective `test_` files. Finally, I've started with an introductory guide for writing tests for our bot in `README.md`.