Writing tests for interactive bots
This page gives an overview of the unit testing framework for interactive bots.
Bots in the main
python-zulip-api
repository are required to include a reasonable set of unit tests, so that
future developers can easily refactor them.
Unit tests for bots make heavy use of mocking. If you want to get comfortable with mocking,
mocking strategies, etc. you should check out our mocking guide.
A simple example
Let's have a look at a simple test suite for the helloworld
bot.
from zulip_bots.test_lib import StubBotTestCase
class TestHelpBot(StubBotTestCase):
bot_name: str = "helloworld"
def test_bot(self) -> None:
dialog = [
('', 'beep boop'),
('help', 'beep boop'),
('foo', 'beep boop'),
]
self.verify_dialog(dialog)
The helloworld bot replies with "beep boop" to every message @-mentioning it. We
want our test to verify that the bot actually does that.
Note that our helper method verify_dialog simulates the conversation for us, and
we just need to set up a list of tuples with expected results.
The best way to learn about bot tests is to read all the existing tests in the
bots subdirectories.
Testing your test
Once you have written a test suite, you want to verify that everything works as expected.
Advanced testing
This section shows advanced testing techniques for more complicated bots that have
configuration files or interact with third-party APIs.
The code for the bot testing library can be found here.
Testing bots with config files
Some bots, such as Giphy,
support or require user configuration options to control how the bot works.
To test such a bot, you can use the following pattern:
with self.mock_config_info(dict(api_key=12345)):
# self.verify_reply(...)
mock_config_info() replaces the actual step of reading configuration from the file
system and gives your test "dummy data" instead.
Testing bots with internet access
Some bots, such as Giphy,
depend on a third-party service, such as the Giphy web app, in order to work. Because
we want our test suite to be reliable and not add load to these third-party APIs, tests
for these services need to have "test fixtures": sample HTTP request/response pairs to
be used by the tests. You can specify which one to use in your test code using the
following helper method:
with self.mock_http_conversation('test_fixture_name'):
# self.assert_bot_response(...)
mock_http_conversation(fixture_name) patches requests.get and returns the data specified
in the file fixtures/{fixture_name}.json. Use the following JSON code as a skeleton for new
fixtures:
{
"request": {
"api_url": "http://api.example.com/",
"params": {
}
},
"response": {
},
"response-headers": {
}
}
For an example, check out the giphy bot.
Tip: You can use requestbin or a similar
tool to capture payloads from the service your bot is interacting
with.
Examples
Check out our bots
to see examples of bot tests.
Related articles