bots: Add complete tests for offline testing of xkcd bot.
Add patch method to mock 'randint' method to check when
xkcd bot is called with 'random' command.
MODIFY
zulip_bots/MANIFEST.in
zulip_bots/MANIFEST.in
@@ -9,4 +9,9 @@ include zulip_bots/bots/wikipedia/fixtures/test_single_word.json
include zulip_bots/bots/wikipedia/fixtures/test_multi_word.json
include zulip_bots/bots/wikipedia/fixtures/test_incorrect_query.json
include zulip_bots/bots/wikipedia/fixtures/test_number_query.json
+include zulip_bots/bots/xkcd/fixtures/test_latest.json
+include zulip_bots/bots/xkcd/fixtures/test_random.json
+include zulip_bots/bots/xkcd/fixtures/test_specific_id.json
+include zulip_bots/bots/xkcd/fixtures/test_not_existing_id.json
+include zulip_bots/bots/xkcd/fixtures/test_not_existing_id_2.json

ADD
zulip_bots/zulip_bots/bots/xkcd/fixtures/test_latest.json
+{
+ "request": {
+ "api_url":"https://xkcd.com/info.0.json"
+ },
+ "response": {
+ "data": {
+ "status_code":200
+ },
+ "month":"7",
+ "num":1866,
+ "link":"",
+ "year":"2017",
+ "news":"",
+ "safe_title":"Russell's Teapot",
+ "transcript":"",
+ "alt":"Unfortunately, NASA regulations state that Bertrand Russell-related payloads can only be launched within launch vehicles which do not launch themselves.",
+ "img":"https://imgs.xkcd.com/comics/russells_teapot.png",
+ "title":"Russell's Teapot",
+ "day":"21"
+
+ },
+ "response-headers":{
+ "status":200,
+ "ok":true,
+ "content-type":"application/json; charset=utf-8"
+ }
+}

ADD
zulip_bots/zulip_bots/bots/xkcd/fixtures/test_not_existing_id.json
+{
+ "request": {
+ "api_url":"https://xkcd.com/999999999/info.0.json"
+ },
+ "response": {
+ "data": {
+ "status_code":404
+ }
+ },
+ "response-headers":{
+ "status":404,
+ "ok":true,
+ "content-type":"application/json; charset=utf-8"
+ }
+}

ADD
zulip_bots/zulip_bots/bots/xkcd/fixtures/test_not_existing_id_2.json
+{
+ "request": {
+ "api_url":"https://xkcd.com/0/info.0.json"
+ },
+ "response": {
+ "data": {
+ "status_code":404
+ }
+ },
+ "response-headers":{
+ "status":404,
+ "ok":true,
+ "content-type":"application/json; charset=utf-8"
+ }
+}

ADD
zulip_bots/zulip_bots/bots/xkcd/fixtures/test_random.json
+{
+ "request": {
+ "api_url":"https://xkcd.com/1800/info.0.json"
+ },
+ "response": {
+ "data": {
+ "status_code":200
+ },
+ "month":"2",
+ "num":1800,
+ "link":"",
+ "year":"2017",
+ "news":"",
+ "safe_title":"Chess Notation",
+ "transcript":"",
+ "alt":"I've decided to score all my conversations using chess win-loss notation. (??)",
+ "img":"https://imgs.xkcd.com/comics/chess_notation.png",
+ "title":"Chess Notation",
+ "day":"17"
+ },
+ "response-headers":{
+ "status":200,
+ "ok":true,
+ "content-type":"application/json; charset=utf-8"
+ }
+}

ADD
zulip_bots/zulip_bots/bots/xkcd/fixtures/test_specific_id.json
+{
+ "request": {
+ "api_url":"https://xkcd.com/1/info.0.json"
+ },
+ "response": {
+ "data": {
+ "status_code":200
+ },
+ "month":"1",
+ "num":1,
+ "link":"",
+ "year":"2006",
+ "news":"",
+ "safe_title":"Barrel - Part 1",
+ "transcript":"[[A boy sits in a barrel which is floating in an ocean.]]\nBoy: I wonder where I'll float next?\n[[The barrel drifts into the distance. Nothing else can be seen.]]\n{{Alt: Don't we all.}}",
+ "alt":"Don't we all.",
+ "img":"https://imgs.xkcd.com/comics/barrel_cropped_(1).jpg",
+ "title":"Barrel - Part 1",
+ "day":"1"
+ },
+ "response-headers":{
+ "status":200,
+ "ok":true,
+ "content-type":"application/json; charset=utf-8"
+ }
+}

MODIFY
zulip_bots/zulip_bots/bots/xkcd/test_xkcd.py
zulip_bots/zulip_bots/bots/xkcd/test_xkcd.py
@@ -4,6 +4,7 @@ from __future__ import absolute_import
from __future__ import print_function
import mock
+from mock import MagicMock, patch
from zulip_bots.test_lib import BotTestCase
class TestXkcdBot(BotTestCase):
@@ -19,17 +20,83 @@ class TestXkcdBot(BotTestCase):
* `@xkcd random` to fetch a random comic strip from xkcd.
* `@xkcd <comic id>` to fetch a comic strip based on `<comic id>` e.g `@xkcd 1234`.'''
invalid_id_txt = "Sorry, there is likely no xkcd comic strip with id: #"
- expected = {
- "": err_txt+commands,
- "help": help_txt+commands,
- "x": err_txt+commands,
- "0": invalid_id_txt + "0",
- "1": ("#1: **Barrel - Part 1**\n[Don't we all.]"
- "(https://imgs.xkcd.com/comics/barrel_cropped_(1).jpg)"),
- "1800": ("#1800: **Chess Notation**\n"
- "[I've decided to score all my conversations "
- "using chess win-loss notation. (??)]"
- "(https://imgs.xkcd.com/comics/chess_notation.png)"),
- "999999999": invalid_id_txt + "999999999",
- }
- self.check_expected_responses(expected)
+
+ # 'latest' query
+ bot_response = ("#1866: **Russell's Teapot**\n"
+ "[Unfortunately, NASA regulations state that Bertrand Russell-related "
+ "payloads can only be launched within launch vehicles which do not launch "
+ "themselves.](https://imgs.xkcd.com/comics/russells_teapot.png)")
+ with self.mock_http_conversation('test_latest'):
+ self.assert_bot_response(
+ message = {'content': 'latest'},
+ response = {'content': bot_response},
+ expected_method='send_reply'
+ )
+
+ # 'random' query
+ bot_response = ("#1800: **Chess Notation**\n"
+ "[I've decided to score all my conversations using chess win-loss "
+ "notation. (??)](https://imgs.xkcd.com/comics/chess_notation.png)")
+ with self.mock_http_conversation('test_random'):
+ # Mock randint function.
+ with patch('bots.xkcd.xkcd.random.randint') as randint:
+ mock_rand_value = mock.MagicMock()
+ mock_rand_value.return_value = 1800
+ randint.return_value = mock_rand_value.return_value
+
+ self.assert_bot_response(
+ message = {'content': 'random'},
+ response = {'content': bot_response},
+ expected_method='send_reply'
+ )
+
+ # specific comic ID query
+ bot_response = ("#1: **Barrel - Part 1**\n[Don't we all.]"
+ "(https://imgs.xkcd.com/comics/barrel_cropped_(1).jpg)")
+ with self.mock_http_conversation('test_specific_id'):
+ self.assert_bot_response(
+ message = {'content': '1'},
+ response = {'content': bot_response},
+ expected_method='send_reply'
+ )
+
+ # Comic ID doesn't exist.
+ bot_response = invalid_id_txt + "999999999"
+ with self.mock_http_conversation('test_not_existing_id'):
+ self.assert_bot_response(
+ message = {'content': '999999999'},
+ response = {'content': bot_response},
+ expected_method='send_reply'
+ )
+
+ bot_response = invalid_id_txt + "0"
+ with self.mock_http_conversation('test_not_existing_id_2'):
+ self.assert_bot_response(
+ message = {'content': '0'},
+ response = {'content': bot_response},
+ expected_method='send_reply'
+ )
+
+ # Empty query, no request made to the Internet.
+ bot_response = err_txt+commands
+ self.assert_bot_response(
+ message = {'content': ''},
+ response = {'content': bot_response},
+ expected_method='send_reply'
+ )
+
+ # 'help' command.
+ bot_response = help_txt+commands
+ self.assert_bot_response(
+ message = {'content': 'help'},
+ response = {'content': bot_response},
+ expected_method='send_reply'
+ )
+
+ # wrong command.
+ bot_response = err_txt+commands
+ self.assert_bot_response(
+ message = {'content': 'x'},
+ response = {'content': bot_response},
+ expected_method='send_reply'
+ )

MODIFY
zulip_bots/zulip_bots/bots/xkcd/xkcd.py
zulip_bots/zulip_bots/bots/xkcd/xkcd.py
-from random import randint
+import random
import logging
import requests
@@ -89,7 +89,7 @@ def fetch_xkcd_query(mode, comic_id=None):
raise XkcdServerError()
latest_id = latest.json()['num']
- random_id = randint(1, latest_id)
+ random_id = random.randint(1, latest_id)
url = XKCD_TEMPLATE_URL % (str(random_id))
elif mode == XkcdBotCommand.COMIC_ID: # Fetch specific comic strip by id number.

bots: Add complete tests for offline testing of xkcd bot.

Add patch method to mock 'randint' method to check when
xkcd bot is called with 'random' command.