| @@ -1,5 +1,3 @@ | |||||
| # Ignore python bytecode: | |||||
| *.pyc | *.pyc | ||||
| # Ignore OS X's stuff: | |||||
| *.egg-info | |||||
| .DS_Store | .DS_Store | ||||
| @@ -59,7 +59,7 @@ class BaseCommand(object): | |||||
| """ | """ | ||||
| self.bot = bot | self.bot = bot | ||||
| self.config = bot.config | self.config = bot.config | ||||
| self.logger = bot.commands.getLogger(self.name) | |||||
| self.logger = bot.commands.logger.getChild(self.name) | |||||
| def _wrap_process(self, data): | def _wrap_process(self, data): | ||||
| """Make a quick connection alias and then process() the message.""" | """Make a quick connection alias and then process() the message.""" | ||||
| @@ -95,7 +95,7 @@ class BaseCommand(object): | |||||
| class CommandManager(object): | class CommandManager(object): | ||||
| def __init__(self, bot): | def __init__(self, bot): | ||||
| self.bot = bot | self.bot = bot | ||||
| self.logger = bot.logger.getLogger("commands") | |||||
| self.logger = bot.logger.getChild("commands") | |||||
| self._commands = {} | self._commands = {} | ||||
| self._command_access_lock = Lock() | self._command_access_lock = Lock() | ||||
| @@ -40,7 +40,7 @@ class Frontend(IRCConnection): | |||||
| def __init__(self, bot): | def __init__(self, bot): | ||||
| self.bot = bot | self.bot = bot | ||||
| self.logger = bot.logger.getLogger("frontend") | |||||
| self.logger = bot.logger.getChild("frontend") | |||||
| cf = bot.config.irc["frontend"] | cf = bot.config.irc["frontend"] | ||||
| base = super(Frontend, self) | base = super(Frontend, self) | ||||
| @@ -39,7 +39,7 @@ class Watcher(IRCConnection): | |||||
| def __init__(self, bot): | def __init__(self, bot): | ||||
| self.bot = bot | self.bot = bot | ||||
| self.logger = bot.logger.getLogger("watcher") | |||||
| self.logger = bot.logger.getChild("watcher") | |||||
| cf = bot.config.irc["watcher"] | cf = bot.config.irc["watcher"] | ||||
| base = super(Watcher, self) | base = super(Watcher, self) | ||||
| @@ -51,7 +51,7 @@ class BaseTask(object): | |||||
| """ | """ | ||||
| self.bot = bot | self.bot = bot | ||||
| self.config = bot.config | self.config = bot.config | ||||
| self.logger = bot.tasks.logger.getLogger(self.name) | |||||
| self.logger = bot.tasks.logger.getChild(self.name) | |||||
| self.setup() | self.setup() | ||||
| def setup(self): | def setup(self): | ||||
| @@ -135,7 +135,7 @@ class BaseTask(object): | |||||
| class TaskManager(object): | class TaskManager(object): | ||||
| def __init__(self, bot): | def __init__(self, bot): | ||||
| self.bot = bot | self.bot = bot | ||||
| self.logger = bot.logger.getLogger("tasks") | |||||
| self.logger = bot.logger.getChild("tasks") | |||||
| self._tasks = {} | self._tasks = {} | ||||
| self._task_access_lock = Lock() | self._task_access_lock = Lock() | ||||
| @@ -21,7 +21,7 @@ | |||||
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| # SOFTWARE. | # SOFTWARE. | ||||
| from setuptools import setup | |||||
| from setuptools import setup, find_packages | |||||
| from earwigbot import __version__ | from earwigbot import __version__ | ||||
| @@ -30,7 +30,7 @@ with open("README.rst") as fp: | |||||
| setup( | setup( | ||||
| name = "earwigbot", | name = "earwigbot", | ||||
| packages = ["earwigbot"], | |||||
| packages = find_packages(exclude=("tests",)), | |||||
| entry_points = {"console_scripts": ["earwigbot = earwigbot.util:main"]}, | entry_points = {"console_scripts": ["earwigbot = earwigbot.util:main"]}, | ||||
| install_requires = ["PyYAML >= 3.10", # Config parsing | install_requires = ["PyYAML >= 3.10", # Config parsing | ||||
| "oursql >= 0.9.3", # Talking with MediaWiki databases | "oursql >= 0.9.3", # Talking with MediaWiki databases | ||||
| @@ -23,26 +23,41 @@ | |||||
| """ | """ | ||||
| EarwigBot's Unit Tests | EarwigBot's Unit Tests | ||||
| This package __init__ file provides some support code for unit tests. | |||||
| This __init__ file provides some support code for unit tests. | |||||
| Test cases: | |||||
| -- CommandTestCase provides setUp() for creating a fake connection, plus | |||||
| some other helpful methods for testing IRC commands. | |||||
| Fake objects: | |||||
| -- FakeBot implements Bot, using the Fake* equivalents of all objects | |||||
| whenever possible. | |||||
| -- FakeBotConfig implements BotConfig with silent logging. | |||||
| -- FakeIRCConnection implements IRCConnection, using an internal string | |||||
| buffer for data instead of sending it over a socket. | |||||
| CommandTestCase is a subclass of unittest.TestCase that provides setUp() for | |||||
| creating a fake connection and some other helpful methods. It uses | |||||
| FakeConnection, a subclass of classes.Connection, but with an internal string | |||||
| instead of a socket for data. | |||||
| """ | """ | ||||
| import logging | |||||
| from os import path | |||||
| import re | import re | ||||
| from threading import Lock | |||||
| from unittest import TestCase | from unittest import TestCase | ||||
| from earwigbot.bot import Bot | |||||
| from earwigbot.commands import CommandManager | |||||
| from earwigbot.config import BotConfig | |||||
| from earwigbot.irc import IRCConnection, Data | from earwigbot.irc import IRCConnection, Data | ||||
| from earwigbot.tasks import TaskManager | |||||
| from earwigbot.wiki import SitesDBManager | |||||
| class CommandTestCase(TestCase): | class CommandTestCase(TestCase): | ||||
| re_sender = re.compile(":(.*?)!(.*?)@(.*?)\Z") | re_sender = re.compile(":(.*?)!(.*?)@(.*?)\Z") | ||||
| def setUp(self, command): | def setUp(self, command): | ||||
| self.connection = FakeConnection() | |||||
| self.connection._connect() | |||||
| self.command = command(self.connection) | |||||
| self.bot = FakeBot(path.dirname(__file__)) | |||||
| self.command = command(self.bot) | |||||
| self.command.connection = self.connection = self.bot.frontend | |||||
| def get_single(self): | def get_single(self): | ||||
| data = self.connection._get().split("\n") | data = self.connection._get().split("\n") | ||||
| @@ -93,15 +108,37 @@ class CommandTestCase(TestCase): | |||||
| return self.maker(line, line[2][1:]) | return self.maker(line, line[2][1:]) | ||||
| class FakeConnection(IRCConnection): | |||||
| def __init__(self): | |||||
| pass | |||||
| class FakeBot(Bot): | |||||
| def __init__(self, root_dir): | |||||
| self.config = FakeBotConfig(root_dir) | |||||
| self.logger = logging.getLogger("earwigbot") | |||||
| self.commands = CommandManager(self) | |||||
| self.tasks = TaskManager(self) | |||||
| self.wiki = SitesDBManager(self.config) | |||||
| self.frontend = FakeIRCConnection(self) | |||||
| self.watcher = FakeIRCConnection(self) | |||||
| self.component_lock = Lock() | |||||
| self._keep_looping = True | |||||
| class FakeBotConfig(BotConfig): | |||||
| def _setup_logging(self): | |||||
| logger = logging.getLogger("earwigbot") | |||||
| logger.addHandler(logging.NullHandler()) | |||||
| class FakeIRCConnection(IRCConnection): | |||||
| def __init__(self, bot): | |||||
| self.bot = bot | |||||
| self._is_running = False | |||||
| self._connect() | |||||
| def _connect(self): | def _connect(self): | ||||
| self._buffer = "" | self._buffer = "" | ||||
| def _close(self): | def _close(self): | ||||
| pass | |||||
| self._buffer = "" | |||||
| def _get(self, size=4096): | def _get(self, size=4096): | ||||
| data, self._buffer = self._buffer, "" | data, self._buffer = self._buffer, "" | ||||
| @@ -23,7 +23,7 @@ | |||||
| import unittest | import unittest | ||||
| from earwigbot.commands.calc import Command | from earwigbot.commands.calc import Command | ||||
| from earwigbot.tests import CommandTestCase | |||||
| from tests import CommandTestCase | |||||
| class TestCalc(CommandTestCase): | class TestCalc(CommandTestCase): | ||||
| @@ -23,7 +23,7 @@ | |||||
| import unittest | import unittest | ||||
| from earwigbot.commands.test import Command | from earwigbot.commands.test import Command | ||||
| from earwigbot.tests import CommandTestCase | |||||
| from tests import CommandTestCase | |||||
| class TestTest(CommandTestCase): | class TestTest(CommandTestCase): | ||||
| @@ -38,12 +38,12 @@ class TestTest(CommandTestCase): | |||||
| self.assertTrue(self.command.check(self.make_msg("TEST", "foo"))) | self.assertTrue(self.command.check(self.make_msg("TEST", "foo"))) | ||||
| def test_process(self): | def test_process(self): | ||||
| def _test(): | |||||
| def test(): | |||||
| self.command.process(self.make_msg("test")) | self.command.process(self.make_msg("test")) | ||||
| self.assertSaidIn(["Hey \x02Foo\x0F!", "'sup \x02Foo\x0F?"]) | self.assertSaidIn(["Hey \x02Foo\x0F!", "'sup \x02Foo\x0F?"]) | ||||
| for i in xrange(64): | for i in xrange(64): | ||||
| _test() | |||||
| test() | |||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||
| unittest.main(verbosity=2) | unittest.main(verbosity=2) | ||||