Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing with py.test #197

Closed
klvbdmh opened this issue May 3, 2016 · 5 comments
Closed

Testing with py.test #197

klvbdmh opened this issue May 3, 2016 · 5 comments
Labels
question This is a question about the library

Comments

@klvbdmh
Copy link

klvbdmh commented May 3, 2016

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
@Fuyukai
Copy link
Contributor

Fuyukai commented May 3, 2016

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

@khazhyk
Copy link
Collaborator

khazhyk commented May 3, 2016

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.

@khazhyk khazhyk added the question This is a question about the library label May 3, 2016
@klvbdmh
Copy link
Author

klvbdmh commented May 3, 2016

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.

@Cobular
Copy link

Cobular commented Apr 14, 2019

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

@ldeluigi
Copy link

ldeluigi commented May 5, 2020

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question This is a question about the library
Projects
None yet
Development

No branches or pull requests

5 participants