class BotTestCase(unittest.TestCase): """Common functionality for bot test case. A :class:`unittest.TestCase` with bot and plugin test fixtures. Creates a bot from :attr:`CONFIG`, binding it to ``self.bot``, and also binding every plugin in :attr:`PLUGINS` to ``self.plugin``. """ CONFIG = "" PLUGINS = [] def setUp(self): """Create bot and plugin bindings.""" # Bot and protocol stuff, suffixed with _ so they can't clash with # possible/likely plugin names self.bot_ = Bot(StringIO(dedent(self.CONFIG))) self.bot_.bot_setup() self.transport_ = proto_helpers.StringTransport() self.protocol_ = BotProtocol(self.bot_) self.protocol_.transport = self.transport_ for p in self.PLUGINS: setattr(self, p, self.bot_.plugins[p]) def tearDown(self): """Lose references to bot and plugins.""" self.bot_ = None self.transport_ = None self.protocol_ = None for p in self.PLUGINS: setattr(self, p, None)
def test_no_provide_method(self, event_loop, config_example_mode): """Check that an error happens when target plugin doesn't implement provide().""" bot = Bot(plugins=[self.MockPlugin3, self.MockPlugin4], config={"@bot": { "plugins": ["mockplugin4", "mockplugin3"] }}) with pytest.raises(PluginFeatureError): bot.bot_setup()
def test_use_called_provide(self, event_loop, config_example_mode): """Check that provide() method is called during setup().""" bot = Bot(plugins=[self.MockPlugin1, self.MockPlugin2], config={"@bot": { "plugins": ["mockplugin2", "mockplugin1"] }}) assert bot.plugins["mockplugin2"].handler_mock.mock_calls == [] # Setup bot, access provided value, assert provide() was called bot.bot_setup() assert bot.plugins["mockplugin1"].a == "baz" assert bot.plugins["mockplugin2"].handler_mock.mock_calls == [ mock.call("provide", "mockplugin1", {"foo": "bar"}), ]
def test_dependency_cycle(self, event_loop, config_example_mode): """Check that plugin dependency cycles are handled.""" with pytest.raises(ValueError): Bot(plugins=[self.MockPlugin4, self.MockPlugin5], config={"@bot": { "plugins": ["mockplugin4", "mockplugin5"] }})
def test_dependency_order(self, event_loop, config_example_mode): """Check that plugin dependencies can be satisfied regardless of order in config.""" bot = Bot(plugins=[self.MockPlugin2, self.MockPlugin3], config={"@bot": { "plugins": ["mockplugin2", "mockplugin3"] }}) assert isinstance(bot.plugins["mockplugin2"], self.MockPlugin2)
def test_use_dependency_not_met(self, event_loop, config_example_mode): """Check that an error happens when loading a plugin that use()s a non-loaded plugin.""" with pytest.raises(PluginDependencyUnmet): Bot(plugins=[self.MockPlugin1, self.MockPlugin2], config={"@bot": { "plugins": ["mockplugin1"] }})
def test_single_dependency_met(self, event_loop, config_example_mode): """Check that plugin loads correctly if dependencies are met.""" bot = Bot(plugins=[self.MockPlugin2, self.MockPlugin3], config={"@bot": { "plugins": ["mockplugin3", "mockplugin2"] }}) assert isinstance(bot.plugins["mockplugin2"], self.MockPlugin2)
def test_single_dependency_not_met(self, event_loop, config_example_mode): """Check that an exception happens if a plugin's dependencies are not met.""" with pytest.raises(PluginDependencyUnmet): Bot(plugins=[self.MockPlugin2, self.MockPlugin3], config={"@bot": { "plugins": ["mockplugin2"] }})
def test_multiple_dependency_partially_met(self, event_loop, config_example_mode): """Check that plugin fails to load if only *some* dependencies are met.""" with pytest.raises(PluginDependencyUnmet): Bot(plugins=[self.MockPlugin1, self.MockPlugin2, self.MockPlugin3], config={"@bot": { "plugins": ["mockplugin2", "mockplugin1"] }})
def test_provide_called_only_once(self, event_loop, config_example_mode): """Check that provide() method is only called once for each plugin.""" bot = Bot(plugins=[self.MockPlugin1, self.MockPlugin2], config={"@bot": { "plugins": ["mockplugin2", "mockplugin1"] }}) assert bot.plugins["mockplugin2"].handler_mock.mock_calls == [] # Setup bot, access provided value, assert provide() was called bot.bot_setup() assert bot.plugins["mockplugin1"].a == "baz" assert bot.plugins["mockplugin2"].handler_mock.mock_calls == [ mock.call("provide", "mockplugin1", {"foo": "bar"}), ] # Access provided value again, assert provide() wasn't called a second time bot.plugins["mockplugin2"].handler_mock.reset_mock() assert bot.plugins["mockplugin1"].a == "baz" assert bot.plugins["mockplugin2"].handler_mock.mock_calls == []
def setUp(self): """Create bot and plugin bindings.""" # Bot and protocol stuff, suffixed with _ so they can't clash with # possible/likely plugin names self.bot_ = Bot(StringIO(dedent(self.CONFIG))) self.bot_.bot_setup() self.transport_ = proto_helpers.StringTransport() self.protocol_ = BotProtocol(self.bot_) self.protocol_.transport = self.transport_ for p in self.PLUGINS: setattr(self, p, self.bot_.plugins[p])
def setUp(self): """Create bot and plugin bindings.""" # Bot and protocol stuff, suffixed with _ so they can't clash with # possible/likely plugin names self.bot_ = Bot(StringIO(dedent(self.CONFIG))) self.bot_.bot_setup() self.protocol_ = mock_client(BotClient, self.bot_) self.protocol_.connect() self.protocol_.reset_mock() self.transport_ = self.protocol_.transport for p in self.PLUGINS: setattr(self, p, self.bot_.plugins[p])