CraftSpider / dpytest

A package that assists in writing tests for discord.py
MIT License
103 stars 24 forks source link

Various AttributeErrors trying to upgrade from 0.0.22 #52

Closed Edward-Knight closed 3 years ago

Edward-Knight commented 3 years ago

Hi, this is sort of a follow up from #39.

I can run dpytest 0.0.22, but upgrading to 0.0.23 or later gives me various AttributeErrors. I wasn't sure which versions of discord.py it's meant to be compatible with, so I wrote a script to test a bunch of them.

testdpy.py (same as #39):

import pytest
from discord.ext import commands
import discord.ext.test as dpytest

@pytest.mark.asyncio
async def test_bot():
    bot = commands.Bot(command_prefix="/")

    @bot.command()
    async def ping(ctx):
        await ctx.send("pong")

    # Load any extensions/cogs you want to in here

    dpytest.configure(bot)

    await dpytest.message("/ping")
    dpytest.verify_message("pong")

testdpy.sh:

#!/bin/bash

set -o errexit
set -o nounset
set -o pipefail

pip install pytest dpytest &>/dev/null
pip freeze

dpytest_versions="0.5.0 0.4.0 0.2.0 0.1.1 0.1.0 0.0.23 0.0.22"
for test_version in ${dpytest_versions}; do
    echo "=== Testing dpytest==${test_version}"
    pip install "dpytest==${test_version}" &> /dev/null

    dpy_versions="1.7.3 1.7.2 1.7.1 1.7.0 1.6.0 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0"
    for dpy_version in ${dpy_versions}; do
        echo -n "Testing discord.py==${dpy_version}... "
        pip install "discord.py==${dpy_version}" &> /dev/null
        if error=$(pytest testdpy.py); then
            echo "Passed!"
        else
            echo "${error}" | grep ^E
        fi
    done
done

And the results, from running on the python:3.8 docker image:

Expand
aiohttp==3.7.4.post0
async-timeout==3.0.1
attrs==21.2.0
chardet==4.0.0
discord.py==1.7.3
dpytest==0.5.0
idna==3.2
iniconfig==1.1.1
multidict==5.1.0
packaging==20.9
pluggy==0.13.1
py==1.10.0
pyparsing==2.4.7
pytest==6.2.4
pytest-asyncio==0.15.1
toml==0.10.2
typing-extensions==3.10.0.0
yarl==1.6.3
=== Testing dpytest==0.5.0
Testing discord.py==1.7.3... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.2... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.1... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.0... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.6.0... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.5.1... E       AttributeError: 'ConnectionState' object has no attribute 'member_cache_flags'
Testing discord.py==1.5.0... E       AttributeError: 'ConnectionState' object has no attribute 'member_cache_flags'
Testing discord.py==1.4.2... E       AttributeError: 'Bot' object has no attribute 'intents'
Testing discord.py==1.4.1... E       AttributeError: 'Bot' object has no attribute 'intents'
Testing discord.py==1.4.0... E       AttributeError: 'Bot' object has no attribute 'intents'
=== Testing dpytest==0.4.0
Testing discord.py==1.7.3... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.2... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.1... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.0... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.6.0... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.5.1... E       AttributeError: 'ConnectionState' object has no attribute 'member_cache_flags'
Testing discord.py==1.5.0... E       AttributeError: 'ConnectionState' object has no attribute 'member_cache_flags'
Testing discord.py==1.4.2... E       AttributeError: 'Bot' object has no attribute 'intents'
Testing discord.py==1.4.1... E       AttributeError: 'Bot' object has no attribute 'intents'
Testing discord.py==1.4.0... E       AttributeError: 'Bot' object has no attribute 'intents'
=== Testing dpytest==0.2.0
Testing discord.py==1.7.3... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.2... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.1... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.0... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.6.0... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.5.1... E       AttributeError: 'ConnectionState' object has no attribute 'member_cache_flags'
Testing discord.py==1.5.0... E       AttributeError: 'ConnectionState' object has no attribute 'member_cache_flags'
Testing discord.py==1.4.2... E       AttributeError: 'Bot' object has no attribute 'intents'
Testing discord.py==1.4.1... E       AttributeError: 'Bot' object has no attribute 'intents'
Testing discord.py==1.4.0... E       AttributeError: 'Bot' object has no attribute 'intents'
=== Testing dpytest==0.1.1
Testing discord.py==1.7.3... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.2... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.1... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.0... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.6.0... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.5.1... E       AttributeError: 'ConnectionState' object has no attribute 'member_cache_flags'
Testing discord.py==1.5.0... E       AttributeError: 'ConnectionState' object has no attribute 'member_cache_flags'
Testing discord.py==1.4.2... E       AttributeError: 'Bot' object has no attribute 'intents'
Testing discord.py==1.4.1... E       AttributeError: 'Bot' object has no attribute 'intents'
Testing discord.py==1.4.0... E       AttributeError: 'Bot' object has no attribute 'intents'
=== Testing dpytest==0.1.0
Testing discord.py==1.7.3... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.2... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.1... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.0... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.6.0... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.5.1... E       AttributeError: 'ConnectionState' object has no attribute 'member_cache_flags'
Testing discord.py==1.5.0... E       AttributeError: 'ConnectionState' object has no attribute 'member_cache_flags'
Testing discord.py==1.4.2... E       AttributeError: 'Bot' object has no attribute 'intents'
Testing discord.py==1.4.1... E       AttributeError: 'Bot' object has no attribute 'intents'
Testing discord.py==1.4.0... E       AttributeError: 'Bot' object has no attribute 'intents'
=== Testing dpytest==0.0.23
Testing discord.py==1.7.3... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.2... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.1... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.0... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.6.0... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.5.1... E       AttributeError: 'ConnectionState' object has no attribute 'member_cache_flags'
Testing discord.py==1.5.0... E       AttributeError: 'ConnectionState' object has no attribute 'member_cache_flags'
Testing discord.py==1.4.2... E       AttributeError: 'Bot' object has no attribute 'intents'
Testing discord.py==1.4.1... E       AttributeError: 'Bot' object has no attribute 'intents'
Testing discord.py==1.4.0... E       AttributeError: 'Bot' object has no attribute 'intents'
=== Testing dpytest==0.0.22
Testing discord.py==1.7.3... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.2... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.1... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.7.0... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.6.0... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.5.1... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.5.0... E       AttributeError: 'NoneType' object has no attribute 'id'
Testing discord.py==1.4.2... Passed!
Testing discord.py==1.4.1... Passed!
Testing discord.py==1.4.0... Passed!

Any help would be greatly appreciated! 😊

itsTheFae commented 3 years ago

There are changes in dpytest most recent versions that will break your existing tests. The issue you are having here is related to discord.py gateway intents though. Since version 1.5 of discord.py they require intents to be set for certain features. Some of dpytest also depends on intents being set or certain processing used by dpytest is ignored by discord.py. The ignored processing causes incomplete or missing objects - the error you have here.

Try to run these tests again but add the intents parameter to your commands.Bot call. You will need to specify the members intent even if your bot doesn't use it, and other intents may be required depending on your tests. Check this documentation for more info about intents: https://discordpy.readthedocs.io/en/stable/intents.html

Edward-Knight commented 3 years ago

Thank you very much for your swift response!

I adjusted the test code to:

import discord.ext.test as dpytest
import pytest
from discord import Intents
from discord.ext import commands

@pytest.mark.asyncio
async def test_bot():
    bot = commands.Bot("/", intents=Intents(members=True))

    @bot.command()
    async def ping(ctx):
        await ctx.send("pong")

    dpytest.configure(bot)

    await dpytest.message("/ping")
    assert dpytest.verify().message().content("pong")

And I now get the results:

=== Testing dpytest==0.5.0
Testing discord.py==1.7.3... Passed!
Testing discord.py==1.7.2... Passed!
Testing discord.py==1.7.1... Passed!
Testing discord.py==1.7.0... Passed!
Testing discord.py==1.6.0... Passed!
Testing discord.py==1.5.1... E       AttributeError: 'ConnectionState' object has no attribute 'member_cache_flags'
Testing discord.py==1.5.0... E       AttributeError: 'ConnectionState' object has no attribute 'member_cache_flags'