test_marvin_actions
Tests for all Marvin actions
1#! /usr/bin/env python3 2# -*- coding: utf-8 -*- 3 4""" 5Tests for all Marvin actions 6""" 7 8import json 9import os 10 11from datetime import date, timedelta 12from unittest import mock, TestCase 13 14import requests 15 16from bot import Bot 17import marvin_actions 18import marvin_general_actions 19 20class ActionTest(TestCase): 21 """Test Marvin actions""" 22 strings = {} 23 24 @classmethod 25 def setUpClass(cls): 26 with open("marvin_strings.json", encoding="utf-8") as f: 27 cls.strings = json.load(f) 28 29 30 def executeAction(self, action, message): 31 """Execute an action for a message and return the response""" 32 return action(Bot.tokenize(message)) 33 34 35 def assertActionOutput(self, action, message, expectedOutput): 36 """Call an action on message and assert expected output""" 37 actualOutput = self.executeAction(action, message) 38 39 self.assertEqual(actualOutput, expectedOutput) 40 41 42 def assertActionSilent(self, action, message): 43 """Call an action with provided message and assert no output""" 44 self.assertActionOutput(action, message, None) 45 46 47 def assertStringsOutput(self, action, message, expectedoutputKey, subkey=None): 48 """Call an action with provided message and assert the output is equal to DB""" 49 expectedOutput = self.strings.get(expectedoutputKey) 50 if subkey is not None: 51 if isinstance(expectedOutput, list): 52 expectedOutput = expectedOutput[subkey] 53 else: 54 expectedOutput = expectedOutput.get(subkey) 55 self.assertActionOutput(action, message, expectedOutput) 56 57 58 def assertBBQResponse(self, todaysDate, bbqDate, expectedMessageKey): 59 """Assert that the proper bbq message is returned, given a date""" 60 url = self.strings.get("barbecue").get("url") 61 message = self.strings.get("barbecue").get(expectedMessageKey) 62 if isinstance(message, list): 63 message = message[1] 64 if expectedMessageKey in ["base", "week", "eternity"]: 65 message = message % bbqDate 66 67 with mock.patch("marvin_actions.datetime") as d, mock.patch("marvin_actions.random") as r: 68 d.date.today.return_value = todaysDate 69 r.randint.return_value = 1 70 expected = f"{url}. {message}" 71 self.assertActionOutput(marvin_actions.marvinTimeToBBQ, "dags att grilla", expected) 72 73 74 def assertNameDayOutput(self, exampleFile, expectedOutput): 75 """Assert that the proper nameday message is returned, given an inputfile""" 76 with open(os.path.join("namedayFiles", f"{exampleFile}.json"), "r", encoding="UTF-8") as f: 77 response = requests.models.Response() 78 response._content = str.encode(json.dumps(json.load(f))) 79 with mock.patch("marvin_actions.requests") as r: 80 r.get.return_value = response 81 self.assertActionOutput(marvin_actions.marvinNameday, "nameday", expectedOutput) 82 83 def assertJokeOutput(self, exampleFile, expectedOutput): 84 """Assert that a joke is returned, given an input file""" 85 with open(os.path.join("jokeFiles", f"{exampleFile}.json"), "r", encoding="UTF-8") as f: 86 response = requests.models.Response() 87 response._content = str.encode(json.dumps(json.load(f))) 88 with mock.patch("marvin_actions.requests") as r: 89 r.get.return_value = response 90 self.assertActionOutput(marvin_actions.marvinJoke, "joke", expectedOutput) 91 92 def assertSunOutput(self, expectedOutput): 93 """Test that marvin knows when the sun comes up, given an input file""" 94 with open(os.path.join("sunFiles", "sun.json"), "r", encoding="UTF-8") as f: 95 response = requests.models.Response() 96 response._content = str.encode(json.dumps(json.load(f))) 97 with mock.patch("marvin_actions.requests") as r: 98 r.get.return_value = response 99 self.assertActionOutput(marvin_actions.marvinSun, "sol", expectedOutput) 100 101 def testSmile(self): 102 """Test that marvin can smile""" 103 with mock.patch("marvin_actions.random") as r: 104 r.randint.return_value = 1 105 self.assertStringsOutput(marvin_actions.marvinSmile, "le lite?", "smile", 1) 106 self.assertActionSilent(marvin_actions.marvinSmile, "sur idag?") 107 108 def testWhois(self): 109 """Test that marvin responds to whois""" 110 self.assertStringsOutput(marvin_actions.marvinWhoIs, "vem är marvin?", "whois") 111 self.assertActionSilent(marvin_actions.marvinWhoIs, "vemär") 112 113 def testGoogle(self): 114 """Test that marvin can help google stuff""" 115 with mock.patch("marvin_actions.random") as r: 116 r.randint.return_value = 1 117 self.assertActionOutput( 118 marvin_actions.marvinGoogle, 119 "kan du googla mos", 120 "LMGTFY https://www.google.se/search?q=mos") 121 self.assertActionOutput( 122 marvin_actions.marvinGoogle, 123 "kan du googla google mos", 124 "LMGTFY https://www.google.se/search?q=google+mos") 125 self.assertActionSilent(marvin_actions.marvinGoogle, "du kan googla") 126 self.assertActionSilent(marvin_actions.marvinGoogle, "gogool") 127 128 def testExplainShell(self): 129 """Test that marvin can explain shell commands""" 130 url = "https://explainshell.com/explain?cmd=pwd" 131 self.assertActionOutput(marvin_actions.marvinExplainShell, "explain pwd", url) 132 self.assertActionOutput(marvin_actions.marvinExplainShell, "can you explain pwd", url) 133 self.assertActionOutput( 134 marvin_actions.marvinExplainShell, 135 "förklara pwd|grep -o $user", 136 f"{url}%7Cgrep+-o+%24user") 137 138 self.assertActionSilent(marvin_actions.marvinExplainShell, "explains") 139 140 def testSource(self): 141 """Test that marvin responds to questions about source code""" 142 self.assertStringsOutput(marvin_actions.marvinSource, "source", "source") 143 self.assertStringsOutput(marvin_actions.marvinSource, "källkod", "source") 144 self.assertActionSilent(marvin_actions.marvinSource, "opensource") 145 146 def testBudord(self): 147 """Test that marvin knows all the commandments""" 148 for n, _ in enumerate(self.strings.get("budord")): 149 self.assertStringsOutput(marvin_actions.marvinBudord, f"budord #{n}", "budord", f"#{n}") 150 151 self.assertStringsOutput(marvin_actions.marvinBudord,"visa stentavla 1", "budord", "#1") 152 self.assertActionSilent(marvin_actions.marvinBudord, "var är stentavlan?") 153 154 def testQuote(self): 155 """Test that marvin can quote The Hitchhikers Guide to the Galaxy""" 156 with mock.patch("marvin_actions.random") as r: 157 r.randint.return_value = 1 158 self.assertStringsOutput(marvin_actions.marvinQuote, "ge os ett citat", "hitchhiker", 1) 159 self.assertStringsOutput(marvin_actions.marvinQuote, "filosofi", "hitchhiker", 1) 160 self.assertStringsOutput(marvin_actions.marvinQuote, "filosofera", "hitchhiker", 1) 161 self.assertActionSilent(marvin_actions.marvinQuote, "noquote") 162 163 for i,_ in enumerate(self.strings.get("hitchhiker")): 164 r.randint.return_value = i 165 self.assertStringsOutput(marvin_actions.marvinQuote, "quote", "hitchhiker", i) 166 167 def testVideoOfToday(self): 168 """Test that marvin can link to a different video each day of the week""" 169 with mock.patch("marvin_actions.datetime") as dt: 170 for d in range(1, 8): 171 day = date(2024, 11, 25) + timedelta(days=d) 172 dt.date.today.return_value = day 173 weekday = day.strftime("%A") 174 weekdayPhrase = self.strings.get("video-of-today").get(weekday).get("message") 175 videoPhrase = self.strings.get("video-of-today").get(weekday).get("url") 176 response = f"{weekdayPhrase} En passande video är {videoPhrase}" 177 self.assertActionOutput(marvin_actions.marvinVideoOfToday, "dagens video", response) 178 self.assertActionSilent(marvin_actions.marvinVideoOfToday, "videoidag") 179 180 def testHelp(self): 181 """Test that marvin can provide a help menu""" 182 self.assertStringsOutput(marvin_actions.marvinHelp, "help", "menu") 183 self.assertActionSilent(marvin_actions.marvinHelp, "halp") 184 185 def testSayHi(self): 186 """Test that marvin responds to greetings""" 187 with mock.patch("marvin_actions.random") as r: 188 for skey, s in enumerate(self.strings.get("smile")): 189 for hkey, h in enumerate(self.strings.get("hello")): 190 for fkey, f in enumerate(self.strings.get("friendly")): 191 r.randint.side_effect = [skey, hkey, fkey] 192 self.assertActionOutput(marvin_actions.marvinSayHi, "hej", f"{s} {h} {f}") 193 self.assertActionSilent(marvin_actions.marvinSayHi, "korsning") 194 195 def testLunchLocations(self): 196 """Test that marvin can provide lunch suggestions for certain places""" 197 locations = ["karlskrona", "goteborg", "angelholm", "hassleholm", "malmo"] 198 with mock.patch("marvin_actions.random") as r: 199 for location in locations: 200 for i, place in enumerate(self.strings.get("lunch").get("location").get(location)): 201 r.randint.side_effect = [0, i] 202 self.assertActionOutput( 203 marvin_actions.marvinLunch, f"mat {location}", f"Ska vi ta {place}?") 204 r.randint.side_effect = [1, 2] 205 self.assertActionOutput( 206 marvin_actions.marvinLunch, "dags att luncha", "Jag är lite sugen på Indiska?") 207 self.assertActionSilent(marvin_actions.marvinLunch, "matdags") 208 209 def testStrip(self): 210 """Test that marvin can recommend comics""" 211 messageFormat = self.strings.get("commitstrip").get("message") 212 expected = messageFormat.format(url=self.strings.get("commitstrip").get("url")) 213 self.assertActionOutput(marvin_actions.marvinStrip, "lite strip kanske?", expected) 214 self.assertActionSilent(marvin_actions.marvinStrip, "nostrip") 215 216 def testRandomStrip(self): 217 """Test that marvin can recommend random comics""" 218 messageFormat = self.strings.get("commitstrip").get("message") 219 expected = messageFormat.format(url=self.strings.get("commitstrip").get("urlPage") + "123") 220 with mock.patch("marvin_actions.random") as r: 221 r.randint.return_value = 123 222 self.assertActionOutput(marvin_actions.marvinStrip, "random strip kanske?", expected) 223 224 def testTimeToBBQ(self): 225 """Test that marvin knows when the next BBQ is""" 226 self.assertBBQResponse(date(2024, 5, 17), date(2024, 5, 17), "today") 227 self.assertBBQResponse(date(2024, 5, 16), date(2024, 5, 17), "tomorrow") 228 self.assertBBQResponse(date(2024, 5, 10), date(2024, 5, 17), "week") 229 self.assertBBQResponse(date(2024, 5, 1), date(2024, 5, 17), "base") 230 self.assertBBQResponse(date(2023, 10, 17), date(2024, 5, 17), "eternity") 231 232 self.assertBBQResponse(date(2024, 9, 20), date(2024, 9, 20), "today") 233 self.assertBBQResponse(date(2024, 9, 19), date(2024, 9, 20), "tomorrow") 234 self.assertBBQResponse(date(2024, 9, 13), date(2024, 9, 20), "week") 235 self.assertBBQResponse(date(2024, 9, 4), date(2024, 9, 20), "base") 236 237 def testNameDayReaction(self): 238 """Test that marvin only responds to nameday when asked""" 239 self.assertActionSilent(marvin_actions.marvinNameday, "anything") 240 241 def testNameDayRequest(self): 242 """Test that marvin sends a proper request for nameday info""" 243 with mock.patch("marvin_actions.requests") as r, mock.patch("marvin_actions.datetime") as d: 244 d.datetime.now.return_value = date(2024, 1, 2) 245 self.executeAction(marvin_actions.marvinNameday, "namnsdag") 246 self.assertEqual(r.get.call_args.args[0], "https://api.dryg.net/dagar/v2.1/2024/1/2") 247 248 def testNameDayResponse(self): 249 """Test that marvin properly parses nameday responses""" 250 self.assertNameDayOutput("single", "Idag har Svea namnsdag") 251 self.assertNameDayOutput("double", "Idag har Alfred och Alfrida namnsdag") 252 self.assertNameDayOutput("triple", "Idag har Kasper, Melker och Baltsar namnsdag") 253 self.assertNameDayOutput("nobody", "Ingen har namnsdag idag") 254 255 def testNameDayError(self): 256 """Tests that marvin returns the proper error message when nameday API is down""" 257 with mock.patch("marvin_actions.requests.get", side_effect=Exception("API Down!")): 258 self.assertStringsOutput( 259 marvin_actions.marvinNameday, 260 "har någon namnsdag idag?", 261 "nameday", 262 "error") 263 264 def testJokeRequest(self): 265 """Test that marvin sends a proper request for a joke""" 266 with mock.patch("marvin_actions.requests") as r: 267 self.executeAction(marvin_actions.marvinJoke, "joke") 268 self.assertEqual( 269 r.get.call_args.args[0], 270 "https://api.chucknorris.io/jokes/random?category=dev") 271 272 def testJoke(self): 273 """Test that marvin sends a joke when requested""" 274 self.assertJokeOutput("joke", "There is no Esc key on Chuck Norris' keyboard, because no one escapes Chuck Norris.") 275 276 def testJokeError(self): 277 """Tests that marvin returns the proper error message when joke API is down""" 278 with mock.patch("marvin_actions.requests.get", side_effect=Exception("API Down!")): 279 self.assertStringsOutput(marvin_actions.marvinJoke, "kör ett skämt", "joke", "error") 280 281 def testSun(self): 282 """Test that marvin sends the sunrise and sunset times """ 283 self.assertSunOutput( 284 "Idag går solen upp 7:12 och ner 18:21. Iallafall i trakterna kring BTH.") 285 286 def testSunError(self): 287 """Tests that marvin returns the proper error message when joke API is down""" 288 with mock.patch("marvin_actions.requests.get", side_effect=Exception("API Down!")): 289 self.assertStringsOutput(marvin_actions.marvinSun, "när går solen ner?", "sun", "error") 290 291 def testUptime(self): 292 """Test that marvin can provide the link to the uptime tournament""" 293 self.assertStringsOutput(marvin_actions.marvinUptime, "visa lite uptime", "uptime", "info") 294 self.assertActionSilent(marvin_actions.marvinUptime, "uptimetävling") 295 296 def testStream(self): 297 """Test that marvin can provide the link to the stream""" 298 self.assertStringsOutput(marvin_actions.marvinStream, "ska mos streama?", "stream", "info") 299 self.assertActionSilent(marvin_actions.marvinStream, "är mos en streamer?") 300 301 def testPrinciple(self): 302 """Test that marvin can recite some software principles""" 303 principles = self.strings.get("principle") 304 for key, value in principles.items(): 305 self.assertActionOutput(marvin_actions.marvinPrinciple, f"princip {key}", value) 306 with mock.patch("marvin_actions.random") as r: 307 r.choice.return_value = "dry" 308 self.assertStringsOutput(marvin_actions.marvinPrinciple, "princip", "principle", "dry") 309 self.assertActionSilent(marvin_actions.marvinPrinciple, "principlös") 310 311 def testCommitRequest(self): 312 """Test that marvin sends proper requests when generating commit messages""" 313 with mock.patch("marvin_actions.requests") as r: 314 self.executeAction(marvin_actions.marvinCommit, "vad skriver man efter commit -m?") 315 self.assertEqual(r.get.call_args.args[0], "https://whatthecommit.com/index.txt") 316 317 def testCommitResponse(self): 318 """Test that marvin properly handles responses when generating commit messages""" 319 message = "Secret sauce #9" 320 response = requests.models.Response() 321 response._content = str.encode(message) 322 with mock.patch("marvin_actions.requests") as r: 323 r.get.return_value = response 324 expected = f"Använd detta meddelandet: '{message}'" 325 self.assertActionOutput(marvin_actions.marvinCommit, "commit", expected) 326 327 def testWeatherRequest(self): 328 """Test that marvin sends the expected requests for weather info""" 329 with mock.patch("marvin_actions.requests") as r: 330 self.executeAction(marvin_actions.marvinWeather, "väder") 331 for url in ["https://opendata-download-metobs.smhi.se/api/version/1.0/parameter/13/station/65090/period/latest-hour/data.json", 332 "https://opendata-download-metobs.smhi.se/api/version/1.0/parameter/13/codes.json", 333 "https://opendata-download-metfcst.smhi.se/api/category/pmp3g/version/2/geotype/point/lon/15.5890/lat/56.1500/data.json"]: 334 self.assertTrue(mock.call(url, timeout=5) in r.get.call_args_list) 335 336 def testWeatherResponse(self): 337 """Test that marvin properly parses weather responses""" 338 responses = [] 339 for responseFile in ["station.json", "codes.json", "weather.json"]: 340 with open(os.path.join("weatherFiles", responseFile), "r", encoding="UTF-8") as f: 341 response = requests.models.Response() 342 response._content = str.encode(json.dumps(json.load(f))) 343 responses.append(response) 344 345 with mock.patch("marvin_actions.requests") as r: 346 r.get.side_effect = responses 347 expected = "Karlskrona just nu: 11.7 °C. Inget signifikant väder observerat." 348 self.assertActionOutput(marvin_actions.marvinWeather, "väder", expected) 349 350 def testCommitReaction(self): 351 """Test that marvin only generates commit messages when asked""" 352 self.assertActionSilent(marvin_actions.marvinCommit, "nocommit") 353 354 355 def testCommitError(self): 356 """Tests that marvin sends the proper message when get commit fails""" 357 with mock.patch("marvin_actions.requests.get", side_effect=Exception('API Down!')): 358 self.assertStringsOutput( 359 marvin_actions.marvinCommit, 360 "vad skriver man efter commit -m?", 361 "commit", 362 "error") 363 364 def testMorning(self): 365 """Test that marvin wishes good morning, at most once per day""" 366 marvin_general_actions.lastDateGreeted = None 367 with mock.patch("marvin_general_actions.datetime") as d: 368 d.date.today.return_value = date(2024, 5, 17) 369 with mock.patch("marvin_general_actions.random") as r: 370 r.choice.return_value = "Morgon" 371 self.assertActionOutput(marvin_general_actions.marvinMorning, "morrn", "Morgon") 372 # Should only greet once per day 373 self.assertActionSilent(marvin_general_actions.marvinMorning, "morgon") 374 # Should greet again tomorrow 375 d.date.today.return_value = date(2024, 5, 18) 376 self.assertActionOutput(marvin_general_actions.marvinMorning, "godmorgon", "Morgon")
21class ActionTest(TestCase): 22 """Test Marvin actions""" 23 strings = {} 24 25 @classmethod 26 def setUpClass(cls): 27 with open("marvin_strings.json", encoding="utf-8") as f: 28 cls.strings = json.load(f) 29 30 31 def executeAction(self, action, message): 32 """Execute an action for a message and return the response""" 33 return action(Bot.tokenize(message)) 34 35 36 def assertActionOutput(self, action, message, expectedOutput): 37 """Call an action on message and assert expected output""" 38 actualOutput = self.executeAction(action, message) 39 40 self.assertEqual(actualOutput, expectedOutput) 41 42 43 def assertActionSilent(self, action, message): 44 """Call an action with provided message and assert no output""" 45 self.assertActionOutput(action, message, None) 46 47 48 def assertStringsOutput(self, action, message, expectedoutputKey, subkey=None): 49 """Call an action with provided message and assert the output is equal to DB""" 50 expectedOutput = self.strings.get(expectedoutputKey) 51 if subkey is not None: 52 if isinstance(expectedOutput, list): 53 expectedOutput = expectedOutput[subkey] 54 else: 55 expectedOutput = expectedOutput.get(subkey) 56 self.assertActionOutput(action, message, expectedOutput) 57 58 59 def assertBBQResponse(self, todaysDate, bbqDate, expectedMessageKey): 60 """Assert that the proper bbq message is returned, given a date""" 61 url = self.strings.get("barbecue").get("url") 62 message = self.strings.get("barbecue").get(expectedMessageKey) 63 if isinstance(message, list): 64 message = message[1] 65 if expectedMessageKey in ["base", "week", "eternity"]: 66 message = message % bbqDate 67 68 with mock.patch("marvin_actions.datetime") as d, mock.patch("marvin_actions.random") as r: 69 d.date.today.return_value = todaysDate 70 r.randint.return_value = 1 71 expected = f"{url}. {message}" 72 self.assertActionOutput(marvin_actions.marvinTimeToBBQ, "dags att grilla", expected) 73 74 75 def assertNameDayOutput(self, exampleFile, expectedOutput): 76 """Assert that the proper nameday message is returned, given an inputfile""" 77 with open(os.path.join("namedayFiles", f"{exampleFile}.json"), "r", encoding="UTF-8") as f: 78 response = requests.models.Response() 79 response._content = str.encode(json.dumps(json.load(f))) 80 with mock.patch("marvin_actions.requests") as r: 81 r.get.return_value = response 82 self.assertActionOutput(marvin_actions.marvinNameday, "nameday", expectedOutput) 83 84 def assertJokeOutput(self, exampleFile, expectedOutput): 85 """Assert that a joke is returned, given an input file""" 86 with open(os.path.join("jokeFiles", f"{exampleFile}.json"), "r", encoding="UTF-8") as f: 87 response = requests.models.Response() 88 response._content = str.encode(json.dumps(json.load(f))) 89 with mock.patch("marvin_actions.requests") as r: 90 r.get.return_value = response 91 self.assertActionOutput(marvin_actions.marvinJoke, "joke", expectedOutput) 92 93 def assertSunOutput(self, expectedOutput): 94 """Test that marvin knows when the sun comes up, given an input file""" 95 with open(os.path.join("sunFiles", "sun.json"), "r", encoding="UTF-8") as f: 96 response = requests.models.Response() 97 response._content = str.encode(json.dumps(json.load(f))) 98 with mock.patch("marvin_actions.requests") as r: 99 r.get.return_value = response 100 self.assertActionOutput(marvin_actions.marvinSun, "sol", expectedOutput) 101 102 def testSmile(self): 103 """Test that marvin can smile""" 104 with mock.patch("marvin_actions.random") as r: 105 r.randint.return_value = 1 106 self.assertStringsOutput(marvin_actions.marvinSmile, "le lite?", "smile", 1) 107 self.assertActionSilent(marvin_actions.marvinSmile, "sur idag?") 108 109 def testWhois(self): 110 """Test that marvin responds to whois""" 111 self.assertStringsOutput(marvin_actions.marvinWhoIs, "vem är marvin?", "whois") 112 self.assertActionSilent(marvin_actions.marvinWhoIs, "vemär") 113 114 def testGoogle(self): 115 """Test that marvin can help google stuff""" 116 with mock.patch("marvin_actions.random") as r: 117 r.randint.return_value = 1 118 self.assertActionOutput( 119 marvin_actions.marvinGoogle, 120 "kan du googla mos", 121 "LMGTFY https://www.google.se/search?q=mos") 122 self.assertActionOutput( 123 marvin_actions.marvinGoogle, 124 "kan du googla google mos", 125 "LMGTFY https://www.google.se/search?q=google+mos") 126 self.assertActionSilent(marvin_actions.marvinGoogle, "du kan googla") 127 self.assertActionSilent(marvin_actions.marvinGoogle, "gogool") 128 129 def testExplainShell(self): 130 """Test that marvin can explain shell commands""" 131 url = "https://explainshell.com/explain?cmd=pwd" 132 self.assertActionOutput(marvin_actions.marvinExplainShell, "explain pwd", url) 133 self.assertActionOutput(marvin_actions.marvinExplainShell, "can you explain pwd", url) 134 self.assertActionOutput( 135 marvin_actions.marvinExplainShell, 136 "förklara pwd|grep -o $user", 137 f"{url}%7Cgrep+-o+%24user") 138 139 self.assertActionSilent(marvin_actions.marvinExplainShell, "explains") 140 141 def testSource(self): 142 """Test that marvin responds to questions about source code""" 143 self.assertStringsOutput(marvin_actions.marvinSource, "source", "source") 144 self.assertStringsOutput(marvin_actions.marvinSource, "källkod", "source") 145 self.assertActionSilent(marvin_actions.marvinSource, "opensource") 146 147 def testBudord(self): 148 """Test that marvin knows all the commandments""" 149 for n, _ in enumerate(self.strings.get("budord")): 150 self.assertStringsOutput(marvin_actions.marvinBudord, f"budord #{n}", "budord", f"#{n}") 151 152 self.assertStringsOutput(marvin_actions.marvinBudord,"visa stentavla 1", "budord", "#1") 153 self.assertActionSilent(marvin_actions.marvinBudord, "var är stentavlan?") 154 155 def testQuote(self): 156 """Test that marvin can quote The Hitchhikers Guide to the Galaxy""" 157 with mock.patch("marvin_actions.random") as r: 158 r.randint.return_value = 1 159 self.assertStringsOutput(marvin_actions.marvinQuote, "ge os ett citat", "hitchhiker", 1) 160 self.assertStringsOutput(marvin_actions.marvinQuote, "filosofi", "hitchhiker", 1) 161 self.assertStringsOutput(marvin_actions.marvinQuote, "filosofera", "hitchhiker", 1) 162 self.assertActionSilent(marvin_actions.marvinQuote, "noquote") 163 164 for i,_ in enumerate(self.strings.get("hitchhiker")): 165 r.randint.return_value = i 166 self.assertStringsOutput(marvin_actions.marvinQuote, "quote", "hitchhiker", i) 167 168 def testVideoOfToday(self): 169 """Test that marvin can link to a different video each day of the week""" 170 with mock.patch("marvin_actions.datetime") as dt: 171 for d in range(1, 8): 172 day = date(2024, 11, 25) + timedelta(days=d) 173 dt.date.today.return_value = day 174 weekday = day.strftime("%A") 175 weekdayPhrase = self.strings.get("video-of-today").get(weekday).get("message") 176 videoPhrase = self.strings.get("video-of-today").get(weekday).get("url") 177 response = f"{weekdayPhrase} En passande video är {videoPhrase}" 178 self.assertActionOutput(marvin_actions.marvinVideoOfToday, "dagens video", response) 179 self.assertActionSilent(marvin_actions.marvinVideoOfToday, "videoidag") 180 181 def testHelp(self): 182 """Test that marvin can provide a help menu""" 183 self.assertStringsOutput(marvin_actions.marvinHelp, "help", "menu") 184 self.assertActionSilent(marvin_actions.marvinHelp, "halp") 185 186 def testSayHi(self): 187 """Test that marvin responds to greetings""" 188 with mock.patch("marvin_actions.random") as r: 189 for skey, s in enumerate(self.strings.get("smile")): 190 for hkey, h in enumerate(self.strings.get("hello")): 191 for fkey, f in enumerate(self.strings.get("friendly")): 192 r.randint.side_effect = [skey, hkey, fkey] 193 self.assertActionOutput(marvin_actions.marvinSayHi, "hej", f"{s} {h} {f}") 194 self.assertActionSilent(marvin_actions.marvinSayHi, "korsning") 195 196 def testLunchLocations(self): 197 """Test that marvin can provide lunch suggestions for certain places""" 198 locations = ["karlskrona", "goteborg", "angelholm", "hassleholm", "malmo"] 199 with mock.patch("marvin_actions.random") as r: 200 for location in locations: 201 for i, place in enumerate(self.strings.get("lunch").get("location").get(location)): 202 r.randint.side_effect = [0, i] 203 self.assertActionOutput( 204 marvin_actions.marvinLunch, f"mat {location}", f"Ska vi ta {place}?") 205 r.randint.side_effect = [1, 2] 206 self.assertActionOutput( 207 marvin_actions.marvinLunch, "dags att luncha", "Jag är lite sugen på Indiska?") 208 self.assertActionSilent(marvin_actions.marvinLunch, "matdags") 209 210 def testStrip(self): 211 """Test that marvin can recommend comics""" 212 messageFormat = self.strings.get("commitstrip").get("message") 213 expected = messageFormat.format(url=self.strings.get("commitstrip").get("url")) 214 self.assertActionOutput(marvin_actions.marvinStrip, "lite strip kanske?", expected) 215 self.assertActionSilent(marvin_actions.marvinStrip, "nostrip") 216 217 def testRandomStrip(self): 218 """Test that marvin can recommend random comics""" 219 messageFormat = self.strings.get("commitstrip").get("message") 220 expected = messageFormat.format(url=self.strings.get("commitstrip").get("urlPage") + "123") 221 with mock.patch("marvin_actions.random") as r: 222 r.randint.return_value = 123 223 self.assertActionOutput(marvin_actions.marvinStrip, "random strip kanske?", expected) 224 225 def testTimeToBBQ(self): 226 """Test that marvin knows when the next BBQ is""" 227 self.assertBBQResponse(date(2024, 5, 17), date(2024, 5, 17), "today") 228 self.assertBBQResponse(date(2024, 5, 16), date(2024, 5, 17), "tomorrow") 229 self.assertBBQResponse(date(2024, 5, 10), date(2024, 5, 17), "week") 230 self.assertBBQResponse(date(2024, 5, 1), date(2024, 5, 17), "base") 231 self.assertBBQResponse(date(2023, 10, 17), date(2024, 5, 17), "eternity") 232 233 self.assertBBQResponse(date(2024, 9, 20), date(2024, 9, 20), "today") 234 self.assertBBQResponse(date(2024, 9, 19), date(2024, 9, 20), "tomorrow") 235 self.assertBBQResponse(date(2024, 9, 13), date(2024, 9, 20), "week") 236 self.assertBBQResponse(date(2024, 9, 4), date(2024, 9, 20), "base") 237 238 def testNameDayReaction(self): 239 """Test that marvin only responds to nameday when asked""" 240 self.assertActionSilent(marvin_actions.marvinNameday, "anything") 241 242 def testNameDayRequest(self): 243 """Test that marvin sends a proper request for nameday info""" 244 with mock.patch("marvin_actions.requests") as r, mock.patch("marvin_actions.datetime") as d: 245 d.datetime.now.return_value = date(2024, 1, 2) 246 self.executeAction(marvin_actions.marvinNameday, "namnsdag") 247 self.assertEqual(r.get.call_args.args[0], "https://api.dryg.net/dagar/v2.1/2024/1/2") 248 249 def testNameDayResponse(self): 250 """Test that marvin properly parses nameday responses""" 251 self.assertNameDayOutput("single", "Idag har Svea namnsdag") 252 self.assertNameDayOutput("double", "Idag har Alfred och Alfrida namnsdag") 253 self.assertNameDayOutput("triple", "Idag har Kasper, Melker och Baltsar namnsdag") 254 self.assertNameDayOutput("nobody", "Ingen har namnsdag idag") 255 256 def testNameDayError(self): 257 """Tests that marvin returns the proper error message when nameday API is down""" 258 with mock.patch("marvin_actions.requests.get", side_effect=Exception("API Down!")): 259 self.assertStringsOutput( 260 marvin_actions.marvinNameday, 261 "har någon namnsdag idag?", 262 "nameday", 263 "error") 264 265 def testJokeRequest(self): 266 """Test that marvin sends a proper request for a joke""" 267 with mock.patch("marvin_actions.requests") as r: 268 self.executeAction(marvin_actions.marvinJoke, "joke") 269 self.assertEqual( 270 r.get.call_args.args[0], 271 "https://api.chucknorris.io/jokes/random?category=dev") 272 273 def testJoke(self): 274 """Test that marvin sends a joke when requested""" 275 self.assertJokeOutput("joke", "There is no Esc key on Chuck Norris' keyboard, because no one escapes Chuck Norris.") 276 277 def testJokeError(self): 278 """Tests that marvin returns the proper error message when joke API is down""" 279 with mock.patch("marvin_actions.requests.get", side_effect=Exception("API Down!")): 280 self.assertStringsOutput(marvin_actions.marvinJoke, "kör ett skämt", "joke", "error") 281 282 def testSun(self): 283 """Test that marvin sends the sunrise and sunset times """ 284 self.assertSunOutput( 285 "Idag går solen upp 7:12 och ner 18:21. Iallafall i trakterna kring BTH.") 286 287 def testSunError(self): 288 """Tests that marvin returns the proper error message when joke API is down""" 289 with mock.patch("marvin_actions.requests.get", side_effect=Exception("API Down!")): 290 self.assertStringsOutput(marvin_actions.marvinSun, "när går solen ner?", "sun", "error") 291 292 def testUptime(self): 293 """Test that marvin can provide the link to the uptime tournament""" 294 self.assertStringsOutput(marvin_actions.marvinUptime, "visa lite uptime", "uptime", "info") 295 self.assertActionSilent(marvin_actions.marvinUptime, "uptimetävling") 296 297 def testStream(self): 298 """Test that marvin can provide the link to the stream""" 299 self.assertStringsOutput(marvin_actions.marvinStream, "ska mos streama?", "stream", "info") 300 self.assertActionSilent(marvin_actions.marvinStream, "är mos en streamer?") 301 302 def testPrinciple(self): 303 """Test that marvin can recite some software principles""" 304 principles = self.strings.get("principle") 305 for key, value in principles.items(): 306 self.assertActionOutput(marvin_actions.marvinPrinciple, f"princip {key}", value) 307 with mock.patch("marvin_actions.random") as r: 308 r.choice.return_value = "dry" 309 self.assertStringsOutput(marvin_actions.marvinPrinciple, "princip", "principle", "dry") 310 self.assertActionSilent(marvin_actions.marvinPrinciple, "principlös") 311 312 def testCommitRequest(self): 313 """Test that marvin sends proper requests when generating commit messages""" 314 with mock.patch("marvin_actions.requests") as r: 315 self.executeAction(marvin_actions.marvinCommit, "vad skriver man efter commit -m?") 316 self.assertEqual(r.get.call_args.args[0], "https://whatthecommit.com/index.txt") 317 318 def testCommitResponse(self): 319 """Test that marvin properly handles responses when generating commit messages""" 320 message = "Secret sauce #9" 321 response = requests.models.Response() 322 response._content = str.encode(message) 323 with mock.patch("marvin_actions.requests") as r: 324 r.get.return_value = response 325 expected = f"Använd detta meddelandet: '{message}'" 326 self.assertActionOutput(marvin_actions.marvinCommit, "commit", expected) 327 328 def testWeatherRequest(self): 329 """Test that marvin sends the expected requests for weather info""" 330 with mock.patch("marvin_actions.requests") as r: 331 self.executeAction(marvin_actions.marvinWeather, "väder") 332 for url in ["https://opendata-download-metobs.smhi.se/api/version/1.0/parameter/13/station/65090/period/latest-hour/data.json", 333 "https://opendata-download-metobs.smhi.se/api/version/1.0/parameter/13/codes.json", 334 "https://opendata-download-metfcst.smhi.se/api/category/pmp3g/version/2/geotype/point/lon/15.5890/lat/56.1500/data.json"]: 335 self.assertTrue(mock.call(url, timeout=5) in r.get.call_args_list) 336 337 def testWeatherResponse(self): 338 """Test that marvin properly parses weather responses""" 339 responses = [] 340 for responseFile in ["station.json", "codes.json", "weather.json"]: 341 with open(os.path.join("weatherFiles", responseFile), "r", encoding="UTF-8") as f: 342 response = requests.models.Response() 343 response._content = str.encode(json.dumps(json.load(f))) 344 responses.append(response) 345 346 with mock.patch("marvin_actions.requests") as r: 347 r.get.side_effect = responses 348 expected = "Karlskrona just nu: 11.7 °C. Inget signifikant väder observerat." 349 self.assertActionOutput(marvin_actions.marvinWeather, "väder", expected) 350 351 def testCommitReaction(self): 352 """Test that marvin only generates commit messages when asked""" 353 self.assertActionSilent(marvin_actions.marvinCommit, "nocommit") 354 355 356 def testCommitError(self): 357 """Tests that marvin sends the proper message when get commit fails""" 358 with mock.patch("marvin_actions.requests.get", side_effect=Exception('API Down!')): 359 self.assertStringsOutput( 360 marvin_actions.marvinCommit, 361 "vad skriver man efter commit -m?", 362 "commit", 363 "error") 364 365 def testMorning(self): 366 """Test that marvin wishes good morning, at most once per day""" 367 marvin_general_actions.lastDateGreeted = None 368 with mock.patch("marvin_general_actions.datetime") as d: 369 d.date.today.return_value = date(2024, 5, 17) 370 with mock.patch("marvin_general_actions.random") as r: 371 r.choice.return_value = "Morgon" 372 self.assertActionOutput(marvin_general_actions.marvinMorning, "morrn", "Morgon") 373 # Should only greet once per day 374 self.assertActionSilent(marvin_general_actions.marvinMorning, "morgon") 375 # Should greet again tomorrow 376 d.date.today.return_value = date(2024, 5, 18) 377 self.assertActionOutput(marvin_general_actions.marvinMorning, "godmorgon", "Morgon")
Test Marvin actions
25 @classmethod 26 def setUpClass(cls): 27 with open("marvin_strings.json", encoding="utf-8") as f: 28 cls.strings = json.load(f)
Hook method for setting up class fixture before running tests in the class.
31 def executeAction(self, action, message): 32 """Execute an action for a message and return the response""" 33 return action(Bot.tokenize(message))
Execute an action for a message and return the response
36 def assertActionOutput(self, action, message, expectedOutput): 37 """Call an action on message and assert expected output""" 38 actualOutput = self.executeAction(action, message) 39 40 self.assertEqual(actualOutput, expectedOutput)
Call an action on message and assert expected output
43 def assertActionSilent(self, action, message): 44 """Call an action with provided message and assert no output""" 45 self.assertActionOutput(action, message, None)
Call an action with provided message and assert no output
48 def assertStringsOutput(self, action, message, expectedoutputKey, subkey=None): 49 """Call an action with provided message and assert the output is equal to DB""" 50 expectedOutput = self.strings.get(expectedoutputKey) 51 if subkey is not None: 52 if isinstance(expectedOutput, list): 53 expectedOutput = expectedOutput[subkey] 54 else: 55 expectedOutput = expectedOutput.get(subkey) 56 self.assertActionOutput(action, message, expectedOutput)
Call an action with provided message and assert the output is equal to DB
59 def assertBBQResponse(self, todaysDate, bbqDate, expectedMessageKey): 60 """Assert that the proper bbq message is returned, given a date""" 61 url = self.strings.get("barbecue").get("url") 62 message = self.strings.get("barbecue").get(expectedMessageKey) 63 if isinstance(message, list): 64 message = message[1] 65 if expectedMessageKey in ["base", "week", "eternity"]: 66 message = message % bbqDate 67 68 with mock.patch("marvin_actions.datetime") as d, mock.patch("marvin_actions.random") as r: 69 d.date.today.return_value = todaysDate 70 r.randint.return_value = 1 71 expected = f"{url}. {message}" 72 self.assertActionOutput(marvin_actions.marvinTimeToBBQ, "dags att grilla", expected)
Assert that the proper bbq message is returned, given a date
75 def assertNameDayOutput(self, exampleFile, expectedOutput): 76 """Assert that the proper nameday message is returned, given an inputfile""" 77 with open(os.path.join("namedayFiles", f"{exampleFile}.json"), "r", encoding="UTF-8") as f: 78 response = requests.models.Response() 79 response._content = str.encode(json.dumps(json.load(f))) 80 with mock.patch("marvin_actions.requests") as r: 81 r.get.return_value = response 82 self.assertActionOutput(marvin_actions.marvinNameday, "nameday", expectedOutput)
Assert that the proper nameday message is returned, given an inputfile
84 def assertJokeOutput(self, exampleFile, expectedOutput): 85 """Assert that a joke is returned, given an input file""" 86 with open(os.path.join("jokeFiles", f"{exampleFile}.json"), "r", encoding="UTF-8") as f: 87 response = requests.models.Response() 88 response._content = str.encode(json.dumps(json.load(f))) 89 with mock.patch("marvin_actions.requests") as r: 90 r.get.return_value = response 91 self.assertActionOutput(marvin_actions.marvinJoke, "joke", expectedOutput)
Assert that a joke is returned, given an input file
93 def assertSunOutput(self, expectedOutput): 94 """Test that marvin knows when the sun comes up, given an input file""" 95 with open(os.path.join("sunFiles", "sun.json"), "r", encoding="UTF-8") as f: 96 response = requests.models.Response() 97 response._content = str.encode(json.dumps(json.load(f))) 98 with mock.patch("marvin_actions.requests") as r: 99 r.get.return_value = response 100 self.assertActionOutput(marvin_actions.marvinSun, "sol", expectedOutput)
Test that marvin knows when the sun comes up, given an input file
102 def testSmile(self): 103 """Test that marvin can smile""" 104 with mock.patch("marvin_actions.random") as r: 105 r.randint.return_value = 1 106 self.assertStringsOutput(marvin_actions.marvinSmile, "le lite?", "smile", 1) 107 self.assertActionSilent(marvin_actions.marvinSmile, "sur idag?")
Test that marvin can smile
109 def testWhois(self): 110 """Test that marvin responds to whois""" 111 self.assertStringsOutput(marvin_actions.marvinWhoIs, "vem är marvin?", "whois") 112 self.assertActionSilent(marvin_actions.marvinWhoIs, "vemär")
Test that marvin responds to whois
114 def testGoogle(self): 115 """Test that marvin can help google stuff""" 116 with mock.patch("marvin_actions.random") as r: 117 r.randint.return_value = 1 118 self.assertActionOutput( 119 marvin_actions.marvinGoogle, 120 "kan du googla mos", 121 "LMGTFY https://www.google.se/search?q=mos") 122 self.assertActionOutput( 123 marvin_actions.marvinGoogle, 124 "kan du googla google mos", 125 "LMGTFY https://www.google.se/search?q=google+mos") 126 self.assertActionSilent(marvin_actions.marvinGoogle, "du kan googla") 127 self.assertActionSilent(marvin_actions.marvinGoogle, "gogool")
Test that marvin can help google stuff
129 def testExplainShell(self): 130 """Test that marvin can explain shell commands""" 131 url = "https://explainshell.com/explain?cmd=pwd" 132 self.assertActionOutput(marvin_actions.marvinExplainShell, "explain pwd", url) 133 self.assertActionOutput(marvin_actions.marvinExplainShell, "can you explain pwd", url) 134 self.assertActionOutput( 135 marvin_actions.marvinExplainShell, 136 "förklara pwd|grep -o $user", 137 f"{url}%7Cgrep+-o+%24user") 138 139 self.assertActionSilent(marvin_actions.marvinExplainShell, "explains")
Test that marvin can explain shell commands
141 def testSource(self): 142 """Test that marvin responds to questions about source code""" 143 self.assertStringsOutput(marvin_actions.marvinSource, "source", "source") 144 self.assertStringsOutput(marvin_actions.marvinSource, "källkod", "source") 145 self.assertActionSilent(marvin_actions.marvinSource, "opensource")
Test that marvin responds to questions about source code
147 def testBudord(self): 148 """Test that marvin knows all the commandments""" 149 for n, _ in enumerate(self.strings.get("budord")): 150 self.assertStringsOutput(marvin_actions.marvinBudord, f"budord #{n}", "budord", f"#{n}") 151 152 self.assertStringsOutput(marvin_actions.marvinBudord,"visa stentavla 1", "budord", "#1") 153 self.assertActionSilent(marvin_actions.marvinBudord, "var är stentavlan?")
Test that marvin knows all the commandments
155 def testQuote(self): 156 """Test that marvin can quote The Hitchhikers Guide to the Galaxy""" 157 with mock.patch("marvin_actions.random") as r: 158 r.randint.return_value = 1 159 self.assertStringsOutput(marvin_actions.marvinQuote, "ge os ett citat", "hitchhiker", 1) 160 self.assertStringsOutput(marvin_actions.marvinQuote, "filosofi", "hitchhiker", 1) 161 self.assertStringsOutput(marvin_actions.marvinQuote, "filosofera", "hitchhiker", 1) 162 self.assertActionSilent(marvin_actions.marvinQuote, "noquote") 163 164 for i,_ in enumerate(self.strings.get("hitchhiker")): 165 r.randint.return_value = i 166 self.assertStringsOutput(marvin_actions.marvinQuote, "quote", "hitchhiker", i)
Test that marvin can quote The Hitchhikers Guide to the Galaxy
168 def testVideoOfToday(self): 169 """Test that marvin can link to a different video each day of the week""" 170 with mock.patch("marvin_actions.datetime") as dt: 171 for d in range(1, 8): 172 day = date(2024, 11, 25) + timedelta(days=d) 173 dt.date.today.return_value = day 174 weekday = day.strftime("%A") 175 weekdayPhrase = self.strings.get("video-of-today").get(weekday).get("message") 176 videoPhrase = self.strings.get("video-of-today").get(weekday).get("url") 177 response = f"{weekdayPhrase} En passande video är {videoPhrase}" 178 self.assertActionOutput(marvin_actions.marvinVideoOfToday, "dagens video", response) 179 self.assertActionSilent(marvin_actions.marvinVideoOfToday, "videoidag")
Test that marvin can link to a different video each day of the week
181 def testHelp(self): 182 """Test that marvin can provide a help menu""" 183 self.assertStringsOutput(marvin_actions.marvinHelp, "help", "menu") 184 self.assertActionSilent(marvin_actions.marvinHelp, "halp")
Test that marvin can provide a help menu
186 def testSayHi(self): 187 """Test that marvin responds to greetings""" 188 with mock.patch("marvin_actions.random") as r: 189 for skey, s in enumerate(self.strings.get("smile")): 190 for hkey, h in enumerate(self.strings.get("hello")): 191 for fkey, f in enumerate(self.strings.get("friendly")): 192 r.randint.side_effect = [skey, hkey, fkey] 193 self.assertActionOutput(marvin_actions.marvinSayHi, "hej", f"{s} {h} {f}") 194 self.assertActionSilent(marvin_actions.marvinSayHi, "korsning")
Test that marvin responds to greetings
196 def testLunchLocations(self): 197 """Test that marvin can provide lunch suggestions for certain places""" 198 locations = ["karlskrona", "goteborg", "angelholm", "hassleholm", "malmo"] 199 with mock.patch("marvin_actions.random") as r: 200 for location in locations: 201 for i, place in enumerate(self.strings.get("lunch").get("location").get(location)): 202 r.randint.side_effect = [0, i] 203 self.assertActionOutput( 204 marvin_actions.marvinLunch, f"mat {location}", f"Ska vi ta {place}?") 205 r.randint.side_effect = [1, 2] 206 self.assertActionOutput( 207 marvin_actions.marvinLunch, "dags att luncha", "Jag är lite sugen på Indiska?") 208 self.assertActionSilent(marvin_actions.marvinLunch, "matdags")
Test that marvin can provide lunch suggestions for certain places
210 def testStrip(self): 211 """Test that marvin can recommend comics""" 212 messageFormat = self.strings.get("commitstrip").get("message") 213 expected = messageFormat.format(url=self.strings.get("commitstrip").get("url")) 214 self.assertActionOutput(marvin_actions.marvinStrip, "lite strip kanske?", expected) 215 self.assertActionSilent(marvin_actions.marvinStrip, "nostrip")
Test that marvin can recommend comics
217 def testRandomStrip(self): 218 """Test that marvin can recommend random comics""" 219 messageFormat = self.strings.get("commitstrip").get("message") 220 expected = messageFormat.format(url=self.strings.get("commitstrip").get("urlPage") + "123") 221 with mock.patch("marvin_actions.random") as r: 222 r.randint.return_value = 123 223 self.assertActionOutput(marvin_actions.marvinStrip, "random strip kanske?", expected)
Test that marvin can recommend random comics
225 def testTimeToBBQ(self): 226 """Test that marvin knows when the next BBQ is""" 227 self.assertBBQResponse(date(2024, 5, 17), date(2024, 5, 17), "today") 228 self.assertBBQResponse(date(2024, 5, 16), date(2024, 5, 17), "tomorrow") 229 self.assertBBQResponse(date(2024, 5, 10), date(2024, 5, 17), "week") 230 self.assertBBQResponse(date(2024, 5, 1), date(2024, 5, 17), "base") 231 self.assertBBQResponse(date(2023, 10, 17), date(2024, 5, 17), "eternity") 232 233 self.assertBBQResponse(date(2024, 9, 20), date(2024, 9, 20), "today") 234 self.assertBBQResponse(date(2024, 9, 19), date(2024, 9, 20), "tomorrow") 235 self.assertBBQResponse(date(2024, 9, 13), date(2024, 9, 20), "week") 236 self.assertBBQResponse(date(2024, 9, 4), date(2024, 9, 20), "base")
Test that marvin knows when the next BBQ is
238 def testNameDayReaction(self): 239 """Test that marvin only responds to nameday when asked""" 240 self.assertActionSilent(marvin_actions.marvinNameday, "anything")
Test that marvin only responds to nameday when asked
242 def testNameDayRequest(self): 243 """Test that marvin sends a proper request for nameday info""" 244 with mock.patch("marvin_actions.requests") as r, mock.patch("marvin_actions.datetime") as d: 245 d.datetime.now.return_value = date(2024, 1, 2) 246 self.executeAction(marvin_actions.marvinNameday, "namnsdag") 247 self.assertEqual(r.get.call_args.args[0], "https://api.dryg.net/dagar/v2.1/2024/1/2")
Test that marvin sends a proper request for nameday info
249 def testNameDayResponse(self): 250 """Test that marvin properly parses nameday responses""" 251 self.assertNameDayOutput("single", "Idag har Svea namnsdag") 252 self.assertNameDayOutput("double", "Idag har Alfred och Alfrida namnsdag") 253 self.assertNameDayOutput("triple", "Idag har Kasper, Melker och Baltsar namnsdag") 254 self.assertNameDayOutput("nobody", "Ingen har namnsdag idag")
Test that marvin properly parses nameday responses
256 def testNameDayError(self): 257 """Tests that marvin returns the proper error message when nameday API is down""" 258 with mock.patch("marvin_actions.requests.get", side_effect=Exception("API Down!")): 259 self.assertStringsOutput( 260 marvin_actions.marvinNameday, 261 "har någon namnsdag idag?", 262 "nameday", 263 "error")
Tests that marvin returns the proper error message when nameday API is down
265 def testJokeRequest(self): 266 """Test that marvin sends a proper request for a joke""" 267 with mock.patch("marvin_actions.requests") as r: 268 self.executeAction(marvin_actions.marvinJoke, "joke") 269 self.assertEqual( 270 r.get.call_args.args[0], 271 "https://api.chucknorris.io/jokes/random?category=dev")
Test that marvin sends a proper request for a joke
273 def testJoke(self): 274 """Test that marvin sends a joke when requested""" 275 self.assertJokeOutput("joke", "There is no Esc key on Chuck Norris' keyboard, because no one escapes Chuck Norris.")
Test that marvin sends a joke when requested
277 def testJokeError(self): 278 """Tests that marvin returns the proper error message when joke API is down""" 279 with mock.patch("marvin_actions.requests.get", side_effect=Exception("API Down!")): 280 self.assertStringsOutput(marvin_actions.marvinJoke, "kör ett skämt", "joke", "error")
Tests that marvin returns the proper error message when joke API is down
282 def testSun(self): 283 """Test that marvin sends the sunrise and sunset times """ 284 self.assertSunOutput( 285 "Idag går solen upp 7:12 och ner 18:21. Iallafall i trakterna kring BTH.")
Test that marvin sends the sunrise and sunset times
287 def testSunError(self): 288 """Tests that marvin returns the proper error message when joke API is down""" 289 with mock.patch("marvin_actions.requests.get", side_effect=Exception("API Down!")): 290 self.assertStringsOutput(marvin_actions.marvinSun, "när går solen ner?", "sun", "error")
Tests that marvin returns the proper error message when joke API is down
292 def testUptime(self): 293 """Test that marvin can provide the link to the uptime tournament""" 294 self.assertStringsOutput(marvin_actions.marvinUptime, "visa lite uptime", "uptime", "info") 295 self.assertActionSilent(marvin_actions.marvinUptime, "uptimetävling")
Test that marvin can provide the link to the uptime tournament
297 def testStream(self): 298 """Test that marvin can provide the link to the stream""" 299 self.assertStringsOutput(marvin_actions.marvinStream, "ska mos streama?", "stream", "info") 300 self.assertActionSilent(marvin_actions.marvinStream, "är mos en streamer?")
Test that marvin can provide the link to the stream
302 def testPrinciple(self): 303 """Test that marvin can recite some software principles""" 304 principles = self.strings.get("principle") 305 for key, value in principles.items(): 306 self.assertActionOutput(marvin_actions.marvinPrinciple, f"princip {key}", value) 307 with mock.patch("marvin_actions.random") as r: 308 r.choice.return_value = "dry" 309 self.assertStringsOutput(marvin_actions.marvinPrinciple, "princip", "principle", "dry") 310 self.assertActionSilent(marvin_actions.marvinPrinciple, "principlös")
Test that marvin can recite some software principles
312 def testCommitRequest(self): 313 """Test that marvin sends proper requests when generating commit messages""" 314 with mock.patch("marvin_actions.requests") as r: 315 self.executeAction(marvin_actions.marvinCommit, "vad skriver man efter commit -m?") 316 self.assertEqual(r.get.call_args.args[0], "https://whatthecommit.com/index.txt")
Test that marvin sends proper requests when generating commit messages
318 def testCommitResponse(self): 319 """Test that marvin properly handles responses when generating commit messages""" 320 message = "Secret sauce #9" 321 response = requests.models.Response() 322 response._content = str.encode(message) 323 with mock.patch("marvin_actions.requests") as r: 324 r.get.return_value = response 325 expected = f"Använd detta meddelandet: '{message}'" 326 self.assertActionOutput(marvin_actions.marvinCommit, "commit", expected)
Test that marvin properly handles responses when generating commit messages
328 def testWeatherRequest(self): 329 """Test that marvin sends the expected requests for weather info""" 330 with mock.patch("marvin_actions.requests") as r: 331 self.executeAction(marvin_actions.marvinWeather, "väder") 332 for url in ["https://opendata-download-metobs.smhi.se/api/version/1.0/parameter/13/station/65090/period/latest-hour/data.json", 333 "https://opendata-download-metobs.smhi.se/api/version/1.0/parameter/13/codes.json", 334 "https://opendata-download-metfcst.smhi.se/api/category/pmp3g/version/2/geotype/point/lon/15.5890/lat/56.1500/data.json"]: 335 self.assertTrue(mock.call(url, timeout=5) in r.get.call_args_list)
Test that marvin sends the expected requests for weather info
337 def testWeatherResponse(self): 338 """Test that marvin properly parses weather responses""" 339 responses = [] 340 for responseFile in ["station.json", "codes.json", "weather.json"]: 341 with open(os.path.join("weatherFiles", responseFile), "r", encoding="UTF-8") as f: 342 response = requests.models.Response() 343 response._content = str.encode(json.dumps(json.load(f))) 344 responses.append(response) 345 346 with mock.patch("marvin_actions.requests") as r: 347 r.get.side_effect = responses 348 expected = "Karlskrona just nu: 11.7 °C. Inget signifikant väder observerat." 349 self.assertActionOutput(marvin_actions.marvinWeather, "väder", expected)
Test that marvin properly parses weather responses
351 def testCommitReaction(self): 352 """Test that marvin only generates commit messages when asked""" 353 self.assertActionSilent(marvin_actions.marvinCommit, "nocommit")
Test that marvin only generates commit messages when asked
356 def testCommitError(self): 357 """Tests that marvin sends the proper message when get commit fails""" 358 with mock.patch("marvin_actions.requests.get", side_effect=Exception('API Down!')): 359 self.assertStringsOutput( 360 marvin_actions.marvinCommit, 361 "vad skriver man efter commit -m?", 362 "commit", 363 "error")
Tests that marvin sends the proper message when get commit fails
365 def testMorning(self): 366 """Test that marvin wishes good morning, at most once per day""" 367 marvin_general_actions.lastDateGreeted = None 368 with mock.patch("marvin_general_actions.datetime") as d: 369 d.date.today.return_value = date(2024, 5, 17) 370 with mock.patch("marvin_general_actions.random") as r: 371 r.choice.return_value = "Morgon" 372 self.assertActionOutput(marvin_general_actions.marvinMorning, "morrn", "Morgon") 373 # Should only greet once per day 374 self.assertActionSilent(marvin_general_actions.marvinMorning, "morgon") 375 # Should greet again tomorrow 376 d.date.today.return_value = date(2024, 5, 18) 377 self.assertActionOutput(marvin_general_actions.marvinMorning, "godmorgon", "Morgon")
Test that marvin wishes good morning, at most once per day