Discord.py: Testing with py.test

Created on 3 May 2016  路  5Comments  路  Source: Rapptz/discord.py

I adapted the addition function from examples folder into a class so I could move command functionality into a separate module. It's in cogs/addition.py:

from discord.ext import commands

class Math:
    def __init__(self, bot):
        self.bot = bot

    @commands.command()
    async def add(self, left: int, right: int):
        """Adds two numbers together."""
        await self.bot.say(left + right)

def setup(bot):
    bot.add_cog(Math(bot))

How would I go about testing the add function? I tried the following code:

from cogs import addition
from discord.ext import commands

bot = commands.Bot(command_prefix='.', description='None')

def test_coin_flip():
    cl = addition.Math(bot)
    assert cl.add(5, 4) == 9

but once I run it I get TypeError:

============================= test session starts =============================
platform win32 -- Python 3.5.1, pytest-2.8.1, py-1.4.30, pluggy-0.3.1
rootdir: D:\Dev\discord-cloudbot\tests, inifile: 
collected 1 items

D:\Dev\discord-cloudbot\tests\test_cogs.py F
def test_coin_flip():
        cl = addition.Math(bot)
>       assert cl.add(5, 4) == 9
E       TypeError: 'Command' object is not callable
question

Most helpful comment

I'd be impressed if you could unit test a bot that requires an external service as input.

boy do I have news for you

All 5 comments

I'd be impressed if you could unit test a bot that requires an external service as input.

To get the wrapped function from a Command object you use Command.callback (this will be unbound) And you can pass arguments directly in this case.

You can also call Command.invoke(ctx) to call the bound method (which is probably what you want.) This will also run any checks bound to the command as well. You would have to build up a Context object and cannot pass arguments directly.

e.g

cog = MyCog()

ctx = Context(fake_context_params...)
result = cog.my_command.invoke(ctx)

# or 

result = cog.my_command.callback(cog, args...)

Note that in your example, your add command doesn't return anything, it calls bot.say - which is different. Make sure you understand what you're trying to test - testing something like this will require a fair bit of mocking. You'd be better off separating your logic and testing that unit separately, rather than testing commands directly.

You'd be better off separating your logic and testing that unit separately, rather than testing commands directly.

Yeah, that's exactly what I need to do. A momentary lapse of judgement from my part.

Not related to this repo, but someone on the discord just brought this to my attention, might work as a solution for now. I'm going to check it out.
https://github.com/DXsmiley/dismock

I'd be impressed if you could unit test a bot that requires an external service as input.

boy do I have news for you

Was this page helpful?
0 / 5 - 0 ratings

Related issues

reuscam picture reuscam  路  3Comments

Rimmy50 picture Rimmy50  路  3Comments

JackL0 picture JackL0  路  3Comments

adhoc92 picture adhoc92  路  3Comments

MrBrahm picture MrBrahm  路  3Comments