Add test harness

This commit is contained in:
dave 2017-11-27 19:04:22 -08:00
parent d55e111767
commit d9914ca104
11 changed files with 314 additions and 12 deletions

19
.gitignore vendored
View File

@ -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

View File

@ -0,0 +1 @@
hello world!

40
requirements-test.txt Normal file
View 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

View File

@ -1,4 +1,4 @@
#!/bin/bash -x
#!/bin/bash
CONFPATH=${1:-examples/config.json}

6
run-tests.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
export PYTHONUNBUFFERED=1
export PYTHONPATH=.
py.test -s tests/

41
tests/lib.py Normal file
View 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
View 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)

View 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!')

View 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()

View 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')

View 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.')