Add test harness
This commit is contained in:
parent
d55e111767
commit
d9914ca104
19
.gitignore
vendored
19
.gitignore
vendored
@ -1,12 +1,9 @@
|
||||
libs
|
||||
*__pycache__*
|
||||
docs/_build
|
||||
__pycache__
|
||||
.DS_Store
|
||||
botenv
|
||||
dist
|
||||
build
|
||||
pyircbot.egg-info
|
||||
dev
|
||||
docs/builder/build.sh
|
||||
examples/config.test.json
|
||||
osxenv
|
||||
|
||||
/.cache
|
||||
/docs/_build
|
||||
/testenv
|
||||
/dist
|
||||
/build
|
||||
/pyircbot.egg-info
|
||||
|
1
examples/data/data/ASCII/test.txt
Normal file
1
examples/data/data/ASCII/test.txt
Normal file
@ -0,0 +1 @@
|
||||
hello world!
|
40
requirements-test.txt
Normal file
40
requirements-test.txt
Normal file
@ -0,0 +1,40 @@
|
||||
appdirs==1.4.3
|
||||
certifi==2017.4.17
|
||||
chardet==3.0.4
|
||||
cheroot==5.9.1
|
||||
CherryPy==12.0.1
|
||||
decorator==4.0.11
|
||||
idna==2.5
|
||||
ipdb==0.10.3
|
||||
ipython==6.0.0
|
||||
ipython-genutils==0.2.0
|
||||
jaraco.classes==1.4.3
|
||||
jedi==0.10.2
|
||||
mock==2.0.0
|
||||
msgbus==0.0.1
|
||||
packaging==16.8
|
||||
pbr==3.1.1
|
||||
pexpect==4.2.1
|
||||
pickleshare==0.7.4
|
||||
portend==2.2
|
||||
praw==5.0.1
|
||||
prawcore==0.11.0
|
||||
prompt-toolkit==1.0.14
|
||||
ptyprocess==0.5.1
|
||||
py==1.5.2
|
||||
Pygments==2.2.0
|
||||
PyJWT==1.5.3
|
||||
pyparsing==2.2.0
|
||||
PySocks==1.6.7
|
||||
pytest==3.2.5
|
||||
pytz==2017.3
|
||||
pyzmq==16.0.2
|
||||
requests==2.18.1
|
||||
simplegeneric==0.8.1
|
||||
six==1.11.0
|
||||
tempora==1.9
|
||||
traitlets==4.3.2
|
||||
twilio==6.9.0
|
||||
update-checker==0.16
|
||||
urllib3==1.21.1
|
||||
wcwidth==0.1.7
|
@ -1,4 +1,4 @@
|
||||
#!/bin/bash -x
|
||||
#!/bin/bash
|
||||
|
||||
CONFPATH=${1:-examples/config.json}
|
||||
|
||||
|
6
run-tests.sh
Executable file
6
run-tests.sh
Executable file
@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
export PYTHONUNBUFFERED=1
|
||||
export PYTHONPATH=.
|
||||
|
||||
py.test -s tests/
|
41
tests/lib.py
Normal file
41
tests/lib.py
Normal file
@ -0,0 +1,41 @@
|
||||
import os
|
||||
import sys
|
||||
import pytest
|
||||
from pyircbot.pyircbot import PrimitiveBot
|
||||
from pyircbot.irccore import IRCEvent, UserPrefix
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), "../pyircbot/modules/"))
|
||||
|
||||
|
||||
class FakeBaseBot(PrimitiveBot):
|
||||
"""
|
||||
Class that simulates a bot base class. You need to add mocks for any methods you expect called, beyond privmsg.
|
||||
"""
|
||||
|
||||
def __init__(self, config):
|
||||
super().__init__(config)
|
||||
self.act_PRIVMSG = MagicMock()
|
||||
|
||||
def feed_line(self, trailing, cmd="PRIVMSG", args=["#test"], sender=("chatter", "root", "cia.gov")):
|
||||
"""
|
||||
Feed a message into the bot.
|
||||
"""
|
||||
msg = IRCEvent(cmd,
|
||||
args,
|
||||
UserPrefix(*sender),
|
||||
trailing)
|
||||
|
||||
for module_name, module in self.moduleInstances.items():# TODO dedupe this block across the various base classes
|
||||
for hook in module.irchooks:
|
||||
validation = hook.validator(msg, self)
|
||||
if validation:
|
||||
hook.method(msg, validation)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fakebot():
|
||||
bot = FakeBaseBot({"bot": {"datadir": "./examples/data/"},
|
||||
"module_configs": {}})
|
||||
return bot
|
30
tests/modules/calc.py
Normal file
30
tests/modules/calc.py
Normal file
@ -0,0 +1,30 @@
|
||||
import pytest
|
||||
from pyircbot.modules.Calc import Calc
|
||||
from pyircbot.pyircbot import ModuleLoader
|
||||
|
||||
|
||||
class FakeBaseBot(ModuleLoader):
|
||||
|
||||
" IRC methods "
|
||||
def act_PRIVMSG(self, towho, message):
|
||||
"""Use the `/msg` command
|
||||
|
||||
:param towho: the target #channel or user's name
|
||||
:type towho: str
|
||||
:param message: the message to send
|
||||
:type message: str"""
|
||||
# self.sendRaw("PRIVMSG %s :%s" % (towho, message))
|
||||
print("act_PRIVMSG(towho={}, message={})".format(towho, message))
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fakebot():
|
||||
bot = FakeBaseBot()
|
||||
bot.botconfig = {"bot": {"datadir": "./examples/data/"}}
|
||||
bot.loadmodule("SQLite")
|
||||
bot.loadmodule("Calc")
|
||||
return bot
|
||||
|
||||
|
||||
def test_foo(fakebot):
|
||||
print(fakebot)
|
13
tests/modules/test_ascii.py
Normal file
13
tests/modules/test_ascii.py
Normal file
@ -0,0 +1,13 @@
|
||||
import pytest
|
||||
from tests.lib import * # NOQA - fixtures
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def bot(fakebot):
|
||||
fakebot.loadmodule("ASCII")
|
||||
return fakebot
|
||||
|
||||
|
||||
def test_ascii(bot):
|
||||
bot.feed_line(".ascii test")
|
||||
bot.act_PRIVMSG.assert_called_once_with('#test', 'hello world!')
|
81
tests/modules/test_calc.py
Normal file
81
tests/modules/test_calc.py
Normal file
@ -0,0 +1,81 @@
|
||||
import pytest
|
||||
from contextlib import closing
|
||||
from tests.lib import * # NOQA - fixtures
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def calcbot(fakebot):
|
||||
"""
|
||||
Provide a bot loaded with the Calc module. Clear the database.
|
||||
"""
|
||||
fakebot.botconfig["module_configs"]["Calc"] = {
|
||||
"allowDelete": True,
|
||||
"delaySubmit": 0,
|
||||
"delayCalc": 0,
|
||||
"delayCalcSpecific": 0,
|
||||
"delayMatch": 0}
|
||||
fakebot.loadmodule("SQLite")
|
||||
with closing(fakebot.moduleInstances["SQLite"].opendb("calc.db")) as db:
|
||||
for q in ["DELETE FROM calc_addedby;",
|
||||
"DELETE FROM calc_channels;",
|
||||
"DELETE FROM calc_definitions;",
|
||||
"DELETE FROM calc_words;"]:
|
||||
db.query(q)
|
||||
fakebot.loadmodule("Calc")
|
||||
return fakebot
|
||||
|
||||
|
||||
def test_calc_empty(calcbot):
|
||||
calcbot.feed_line("calc")
|
||||
calcbot.act_PRIVMSG.assert_called_once_with('#test', 'This channel has no calcs, chatter :(')
|
||||
calcbot.act_PRIVMSG.reset_mock()
|
||||
|
||||
|
||||
def test_calc_adds(calcbot):
|
||||
_add_fact(calcbot, "foo", "bar")
|
||||
_add_fact(calcbot, "foo2", "bar2")
|
||||
|
||||
calcbot.feed_line(".quote foo2")
|
||||
calcbot.act_PRIVMSG.assert_called_once_with('#test', 'foo2 \x03= bar2 \x0314[added by: chatter]')
|
||||
calcbot.act_PRIVMSG.reset_mock()
|
||||
|
||||
|
||||
def _add_fact(calcbot, fact, value):
|
||||
calcbot.feed_line("calc {} = {}".format(fact, value))
|
||||
calcbot.act_PRIVMSG.assert_called_once_with('#test', 'Thanks for the info, chatter.')
|
||||
calcbot.act_PRIVMSG.reset_mock()
|
||||
|
||||
|
||||
def test_match(calcbot):
|
||||
_add_fact(calcbot, "xxx", "bar")
|
||||
_add_fact(calcbot, "yyy", "bar2")
|
||||
calcbot.feed_line(".match x")
|
||||
calcbot.act_PRIVMSG.assert_called_once_with('#test', 'chatter: 1 match (xxx\x03)')
|
||||
|
||||
|
||||
def test_delete(calcbot):
|
||||
_add_fact(calcbot, "xxx", "bar")
|
||||
_add_fact(calcbot, "yyy", "bar2")
|
||||
calcbot.feed_line(".calc xxx =")
|
||||
calcbot.act_PRIVMSG.assert_called_once_with('#test', 'Calc deleted, chatter.')
|
||||
calcbot.act_PRIVMSG.reset_mock()
|
||||
calcbot.feed_line(".calc xxx")
|
||||
calcbot.act_PRIVMSG.assert_called_once_with('#test', "Sorry chatter, I don't know what 'xxx' is.")
|
||||
|
||||
|
||||
def test_unicode(calcbot):
|
||||
_add_fact(calcbot, "👌👌👌", "uncode keys")
|
||||
_add_fact(calcbot, "uncode values", "👌👌👌")
|
||||
calcbot.feed_line(".calc 👌👌👌")
|
||||
calcbot.act_PRIVMSG.assert_called_once_with('#test', '👌👌👌 \x03= uncode keys \x0314[added by: chatter]')
|
||||
calcbot.act_PRIVMSG.reset_mock()
|
||||
calcbot.feed_line(".match 👌")
|
||||
calcbot.act_PRIVMSG.assert_called_once_with('#test', "chatter: 1 match (👌👌👌\x03)")
|
||||
|
||||
|
||||
def test_delete_disable(calcbot):
|
||||
calcbot.botconfig["module_configs"]["Calc"]["allowDelete"] = False
|
||||
_add_fact(calcbot, "xxx", "bar")
|
||||
_add_fact(calcbot, "yyy", "bar2")
|
||||
calcbot.feed_line("calc xxx =")
|
||||
calcbot.act_PRIVMSG.assert_not_called()
|
19
tests/modules/test_modinfo.py
Normal file
19
tests/modules/test_modinfo.py
Normal file
@ -0,0 +1,19 @@
|
||||
import pytest
|
||||
from tests.lib import * # NOQA - fixtures
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def bot(fakebot):
|
||||
fakebot.loadmodule("ModInfo")
|
||||
return fakebot
|
||||
|
||||
|
||||
def test_help(bot):
|
||||
bot.feed_line(".help")
|
||||
bot.act_PRIVMSG.assert_called_once_with('#test',
|
||||
'ModInfo: .help [command] show the manual for all or [commands]')
|
||||
|
||||
|
||||
def test_helpindex(bot):
|
||||
bot.feed_line(".helpindex")
|
||||
bot.act_PRIVMSG.assert_called_once_with('#test', 'chatter: commands: .help')
|
74
tests/modules/test_nickuser.py
Normal file
74
tests/modules/test_nickuser.py
Normal file
@ -0,0 +1,74 @@
|
||||
import pytest
|
||||
from contextlib import closing
|
||||
from tests.lib import * # NOQA - fixtures
|
||||
|
||||
# TODO:
|
||||
# - Responds to pms where the dest != the bot's nick
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def nickbot(fakebot):
|
||||
"""
|
||||
Provide a bot loaded with the Calc module. Clear the database.
|
||||
"""
|
||||
fakebot.botconfig["module_configs"]["Calc"] = {
|
||||
"allowDelete": True,
|
||||
"delaySubmit": 0,
|
||||
"delayCalc": 0,
|
||||
"delayCalcSpecific": 0,
|
||||
"delayMatch": 0}
|
||||
fakebot.loadmodule("SQLite")
|
||||
with closing(fakebot.moduleInstances["SQLite"].opendb("attributes.db")) as db:
|
||||
for q in ["DELETE FROM attribute;",
|
||||
"DELETE FROM items;",
|
||||
"DELETE FROM `values`;"]:
|
||||
db.query(q)
|
||||
fakebot.loadmodule("AttributeStorageLite")
|
||||
fakebot.loadmodule("NickUser")
|
||||
return fakebot
|
||||
|
||||
|
||||
def pm(nickbot, line):
|
||||
nickbot.feed_line(line, args=['bot'])
|
||||
|
||||
|
||||
def test_blind_login(nickbot):
|
||||
pm(nickbot, ".login foobar")
|
||||
nickbot.act_PRIVMSG.assert_called_once_with('chatter', '.login: You must first set a password with .setpass')
|
||||
|
||||
|
||||
def test_register(nickbot):
|
||||
pm(nickbot, ".setpass foobar")
|
||||
nickbot.act_PRIVMSG.assert_called_once_with('chatter', '.setpass: Your password has been set to "foobar".')
|
||||
nickbot.act_PRIVMSG.reset_mock()
|
||||
|
||||
|
||||
def test_register_login(nickbot):
|
||||
test_register(nickbot)
|
||||
pm(nickbot, ".login foobar")
|
||||
nickbot.act_PRIVMSG.assert_called_once_with('chatter', '.login: You have been logged in from: cia.gov')
|
||||
nickbot.act_PRIVMSG.reset_mock()
|
||||
|
||||
|
||||
def test_badpass(nickbot):
|
||||
test_register(nickbot)
|
||||
pm(nickbot, ".login oopsie")
|
||||
nickbot.act_PRIVMSG.assert_called_once_with('chatter', '.login: incorrect password.')
|
||||
|
||||
|
||||
def test_logout(nickbot):
|
||||
test_register_login(nickbot)
|
||||
pm(nickbot, ".logout")
|
||||
nickbot.act_PRIVMSG.assert_called_once_with('chatter', '.logout: You have been logged out.')
|
||||
nickbot.act_PRIVMSG.reset_mock()
|
||||
pm(nickbot, ".logout")
|
||||
nickbot.act_PRIVMSG.assert_called_once_with('chatter', '.logout: You must first be logged in')
|
||||
|
||||
|
||||
def test_changepass(nickbot):
|
||||
test_register_login(nickbot)
|
||||
pm(nickbot, ".setpass foobar newpass")
|
||||
nickbot.act_PRIVMSG.assert_called_once_with('chatter', '.setpass: Your password has been set to "newpass".')
|
||||
nickbot.act_PRIVMSG.reset_mock()
|
||||
pm(nickbot, ".setpass wrong newpass2")
|
||||
nickbot.act_PRIVMSG.assert_called_once_with('chatter', '.setpass: Old password incorrect.')
|
Loading…
Reference in New Issue
Block a user