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