From 820e8183d7e201543e002b75baa9a5d6a1225357 Mon Sep 17 00:00:00 2001 From: Matzey Date: Fri, 19 Apr 2024 20:47:53 +0200 Subject: [PATCH 01/11] switched two QLineEdit Fields with QComboBox I switched two QLineEdit Field with QComboBox Fields, since those QLineEdit had the user type in a decision between two values. --- resources/form.scss | 17 ++++++++++++++++- src/main.py | 23 +++++++++++++++++------ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/resources/form.scss b/resources/form.scss index f7d636b..a6e3a98 100644 --- a/resources/form.scss +++ b/resources/form.scss @@ -16,7 +16,7 @@ $font-size: 16px; .QLineEdit { color: $secondary-accent-color; - border:none; + border: none; border-bottom: 2px solid $accent-color; padding-bottom: 2px; background: $main-color; @@ -27,16 +27,31 @@ $font-size: 16px; border-radius: 5px; color: $accent-color; background-color: $main-color; + &:hover { border: 2px solid $secondary-color; background-color: $secondary-color; } + &:pressed { border: 2px solid $accent-color; background-color: $accent-color; } + &:disabled { color: $main-color; background-color: $main-color; } +} + +.QComboBox { + color: $secondary-accent-color; + border: none; + border-bottom: 2px solid $accent-color; + padding-bottom: 2px; + background: $main-color; +} + +QComboBox QAbstractItemView { + background-color: $secondary-color; } \ No newline at end of file diff --git a/src/main.py b/src/main.py index 91bd195..c218a2e 100644 --- a/src/main.py +++ b/src/main.py @@ -6,8 +6,8 @@ from PySide6.QtWidgets import ( # pylint: disable=E0611 QApplication, QMainWindow, QLabel, - QLineEdit, QPushButton, QVBoxLayout, - QWidget, QHBoxLayout + QComboBox, QLineEdit, QPushButton, + QVBoxLayout, QWidget, QHBoxLayout ) from PySide6.QtGui import QPixmap, QImage # pylint: disable=E0611 from PySide6.QtCore import Qt # pylint: disable=E0611 @@ -112,8 +112,8 @@ def __init__(self): "game_name": QLineEdit(), "facial_expression": QLineEdit("smile"), "looking_at": QLineEdit("viewer"), - "indoors": QLineEdit("indoors"), - "daytime": QLineEdit("night"), + "indoors": QComboBox(), + "daytime": QComboBox(), "additional_tags": QLineEdit() } self.inputs_labels = { @@ -139,6 +139,9 @@ def __init__(self): "prev_button": QPushButton("<"), "next_button": QPushButton(">"), } + self.inputs["indoors"].addItems(["indoors", "outdoors"]) + self.inputs["daytime"].addItems(["day", "night"]) + self.setup_ui() self.show_input_fields() @@ -194,8 +197,15 @@ def generate_image(self): "Please enter an anime character name.") return self.input_controls["generate_button"].setDisabled(True) - input_values = {key: widget.text().lower().replace(',', ' ').lstrip().rstrip() - for key, widget in self.inputs.items()} + + input_values = {} + for key, widget in self.inputs.items(): + if type(widget) == type(QComboBox()): + input_values[key] = widget.currentText().lower().replace(',', ' ').lstrip().rstrip() + print(input_values[key]) + else: + input_values[key] = widget.text().lower().replace(',', ' ').lstrip().rstrip() + threading.Thread(target=self.image_generator.process_image, args=(input_values, self)).start() @@ -215,6 +225,7 @@ def show_image(self): for item in self.image_controls.values(): item.show() + if len(self.image_generator.images) != 1: for item in self.image_navigation_buttons.values(): item.show() From 25fc333b4adc0ff4f4975f55dcd0533b4a7e7734 Mon Sep 17 00:00:00 2001 From: Matzey Date: Fri, 19 Apr 2024 21:03:41 +0200 Subject: [PATCH 02/11] removed a print --- src/main.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main.py b/src/main.py index c218a2e..7878f4c 100644 --- a/src/main.py +++ b/src/main.py @@ -202,7 +202,6 @@ def generate_image(self): for key, widget in self.inputs.items(): if type(widget) == type(QComboBox()): input_values[key] = widget.currentText().lower().replace(',', ' ').lstrip().rstrip() - print(input_values[key]) else: input_values[key] = widget.text().lower().replace(',', ' ').lstrip().rstrip() From 13e5606a47ea012802a974544e5bd88c4257bf22 Mon Sep 17 00:00:00 2001 From: Matzey Date: Sun, 21 Apr 2024 11:14:58 +0200 Subject: [PATCH 03/11] Mocked tests for test_game_info --- requirements.txt | 1 + src/image/game_info.py | 3 +- src/tests/test_game_info.py | 108 +++++++++++++++++++++++++----------- 3 files changed, 79 insertions(+), 33 deletions(-) diff --git a/requirements.txt b/requirements.txt index 62a2c4d..5470baf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,3 +7,4 @@ thefuzz==0.22.1 torch==2.2.2 transformers==4.39.2 accelerate==0.28.0 +mock==5.1.0 \ No newline at end of file diff --git a/src/image/game_info.py b/src/image/game_info.py index 34ec73b..ce3e4bd 100644 --- a/src/image/game_info.py +++ b/src/image/game_info.py @@ -73,7 +73,6 @@ def authenticate(self): """ if self.token and time.time() - self.authentication_time < self.token['expires_in']: return - url = "https://id.twitch.tv/oauth2/token" payload = { "client_id": self.client_id, @@ -84,6 +83,8 @@ def authenticate(self): response.raise_for_status() self.token = response.json() self.authentication_time = time.time() + return + def get_game_info(self, name): """ diff --git a/src/tests/test_game_info.py b/src/tests/test_game_info.py index afc3152..4eb7ce7 100644 --- a/src/tests/test_game_info.py +++ b/src/tests/test_game_info.py @@ -1,5 +1,7 @@ import time import unittest +from unittest.mock import patch, Mock +from requests.exceptions import HTTPError from src.image.game_info import ( GameInfo, get_year_recency, get_summary_keywords, is_relevant_adjective @@ -7,45 +9,87 @@ class TestGameInfo(unittest.TestCase): - def setUp(self): + def __init__(self, methodName: str = "runTest") -> None: + super().__init__(methodName) self.game_info = GameInfo() - def test_authenticate(self): + @patch('requests.post') + def test_authenticate(self, mock_post): + """ + Test Twitch API Authentication + """ + mock_response = Mock() + response_body = { + "access_token": "someAccessToken", + "expires_in": 9112004, + "token_type": "bearer" + } + mock_response.json.return_value = response_body + mock_post.return_value = mock_response + self.game_info.authenticate() + self.assertIsNotNone(self.game_info.token) - self.assertIsNotNone(self.game_info.authentication_time) - self.assertTrue(time.time() - self.game_info.authentication_time - < self.game_info.token['expires_in']) - - def test_get_game_info(self): - game_data = self.game_info.get_game_info('Tekken 7') - - self.assertIsNotNone(game_data) - self.assertEqual(game_data['name'], 'Tekken 7') - self.assertEqual(game_data['first_release_date'], 1424217600) - self.assertEqual(game_data['genres'], [4]) - self.assertEqual(game_data['summary'], 'Experience the epic conclusion of the ' - 'Mishima clan and unravel the ' - 'reasons behind each step of their ceaseless fight. ' - 'Powered by Unreal ' - 'Engine 4, Tekken 7 features stunning story-driven ' - 'cinematic battles ' - 'and intense duels that can be enjoyed with friends ' - 'and rivals alike ' - 'through innovative fight mechanics.') - - def test_get_genres(self): - genres = self.game_info.get_genres([4]) - - self.assertEqual(genres, ['Fighting']) - - def test_get_game_keywords(self): + self.assertTrue(time.time() - response_body["expires_in"] + < self.game_info.authentication_time) + + @patch("requests.post") + @patch("src.image.game_info.GameInfo.authenticate", Mock()) + def test_get_game_info(self, mock_post_info): + """ + Test IGDB Response on https://api.igdb.com/v4/games + """ + mock_response = Mock() + response_body = [{ + 'id': 7498, + 'first_release_date': 1424217600, + 'genres': [4], + 'name': 'Tekken 7', + 'summary': 'Experience the epic conclusion of the Mishima clan and unravel the reasons behind each step of their ceaseless fight. Powered by Unreal Engine 4, Tekken 7 features stunning story-driven cinematic battles and intense duels that can be enjoyed with friends and rivals alike through innovative fight mechanics.' + }, {}] + mock_response.json.return_value = response_body + mock_post_info.return_value = mock_response + + self.game_info.token = {"access_token": "someAccessToken", "expires_in": 9112004, "token_type": "bearer"} + info = self.game_info.get_game_info("Tekken 7") + + self.assertEqual(response_body[0], info) + + @patch("requests.post") + @patch("src.image.game_info.GameInfo.authenticate", Mock()) + def test_get_genres(self, mock_post): + """ + Test IGDB Response on https://api.igdb.com/v4/genres + """ + mock_response = Mock() + response_body = [{ + "id": 4, + "name": "Fighting" + }] + mock_response.json.return_value = response_body + mock_post.return_value = mock_response + + self.game_info.token = {"access_token": "someAccessToken", "expires_in": 9112004, "token_type": "bearer"} + self.game_info.get_genres([4]) + + self.assertEqual(response_body[0]["name"], 'Fighting') + + @patch("requests.get") + def test_get_game_keywords(self, mock_get): + """ + Test IGDB Response on https://api.igdb.com/v4/genres + """ + mock_response = Mock() + response_body = { + "mid": ["clan", "Experience", "epic", "conclusion", "reasons", "Fighting"] + } + mock_response.json.return_value = response_body + mock_get.return_value = mock_response + keywords = self.game_info.get_game_keywords('Tekken 7') self.assertIsNotNone(keywords) - self.assertEqual(keywords[0], 'mid') - # The order of the keywords may vary - self.assertIn('Fighting', keywords[1]) + self.assertIn("Fighting", keywords[1]) def test_get_year_recency(self): self.assertEqual(get_year_recency(time.time()), 'newest') From 5cf7cf1f4bfe7b8e4d168bd7bed1ce4b5c10f675 Mon Sep 17 00:00:00 2001 From: Matzey Date: Sun, 21 Apr 2024 20:47:54 +0200 Subject: [PATCH 04/11] added mocked requests for test_character_info --- src/image/character_info.py | 9 +++---- src/tests/test_character_info.py | 41 +++++++++++++++++++++++++------- src/tests/test_game_info.py | 1 - 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/image/character_info.py b/src/image/character_info.py index e242bdf..1cf7f87 100644 --- a/src/image/character_info.py +++ b/src/image/character_info.py @@ -7,13 +7,14 @@ "/animagine-xl-3.1/raw/main/wildcard/characterfull.txt") -def get_all_characters(): +def get_all_characters() -> list[str]: """ Get all characters from the character list. """ - with requests.get(CHARACTER_LIST_URL, timeout=3) as response: - response.raise_for_status() - return response.text.split("\n") + response = requests.get(CHARACTER_LIST_URL, timeout=3) + response.raise_for_status() + text: list[str] = response.text.split("\n") + return text def get_closest_character(name): diff --git a/src/tests/test_character_info.py b/src/tests/test_character_info.py index 01f68d3..7c21f26 100644 --- a/src/tests/test_character_info.py +++ b/src/tests/test_character_info.py @@ -1,33 +1,58 @@ import unittest +from unittest.mock import patch, Mock from src.image.character_info import ( get_all_characters, get_closest_character, get_closest_characters ) class TestCharacterFunctions(unittest.TestCase): - @classmethod - def setUpClass(cls): - cls.character_list = ["souryuu asuka langley", "warrior of light (ff14)"] + def __init__(self, methodName: str = "runTest") -> None: + super().__init__(methodName) + self.character_list = ["souryuu asuka langley", "warrior of light (ff14)"] + + @patch('requests.get') + def test_get_all_characters(self, mock_get): + mock_response = Mock() + response_body = "1girl, souryuu asuka langley, neon genesis evangelion\n1girl, warrior of light \\(ff14\\), final fantasy\n1girl, akiyama mio, k-on!\n1girl, tifa lockhart, final fantasy\n1girl, 2b \\(nier:automata\\), nier \\(series\\)\n1girl, nakano azusa, k-on!\n1girl, rem \\(re:zero\\), re:zero kara hajimeru isekai seikatsu\n1girl, hirasawa yui, k-on!\n1girl, gotoh hitori, bocchi the rock!\n1girl, ayanami rei, neon genesis evangelion\n1boy, male focus, joseph joestar, jojo no kimyou na bouken\n1girl, matoi ryuuko, kill la kill\n1girl, yor briar, spy x family\n1girl, tainaka ritsu, k-on!\n" + mock_response.text = response_body + mock_get.return_value = mock_response - def test_get_all_characters(self): characters = get_all_characters() self.assertIsInstance(characters, list) self.assertTrue(all(isinstance(c, str) for c in characters)) - - def test_get_closest_character(self): + + @patch('requests.get') + def test_get_closest_character(self, mock_get): + mock_response = Mock() + response_body = "1girl, souryuu asuka langley, neon genesis evangelion\n1girl, warrior of light \\(ff14\\), final fantasy\n1girl, akiyama mio, k-on!\n1girl, tifa lockhart, final fantasy\n1girl, 2b \\(nier:automata\\), nier \\(series\\)\n1girl, nakano azusa, k-on!\n1girl, rem \\(re:zero\\), re:zero kara hajimeru isekai seikatsu\n1girl, hirasawa yui, k-on!\n1girl, gotoh hitori, bocchi the rock!\n1girl, ayanami rei, neon genesis evangelion\n1boy, male focus, joseph joestar, jojo no kimyou na bouken\n1girl, matoi ryuuko, kill la kill\n1girl, yor briar, spy x family\n1girl, tainaka ritsu, k-on!\n" + mock_response.text = response_body + mock_get.return_value = mock_response + closest_name = get_closest_character("Asuka Langley") self.assertEqual(closest_name, "1girl, souryuu asuka langley, neon genesis evangelion") - def test_get_closest_characters(self): + @patch('requests.get') + def test_get_closest_characters(self, mock_get): + mock_response = Mock() + response_body = "1boy, male focus, uzumaki naruto, naruto \\(series\\)\n1boy, male focus, uzumaki boruto, naruto \\(series\\)\n1girl, uzumaki himawari, naruto \\(series\\)\n1girl, carrot \\(one piece\\), one piece\n1girl, uzumaki kushina, naruto \\(series\\)\n" + mock_response.text = response_body + mock_get.return_value = mock_response + closest_names = get_closest_characters("Naruto Uzumaki", 3) self.assertEqual(closest_names, ['1boy, male focus, uzumaki naruto, naruto \\(series\\)', '1boy, male focus, uzumaki boruto, naruto \\(series\\)', '1girl, uzumaki himawari, naruto \\(series\\)']) - def test_get_closest_character_not_found(self): + @patch('requests.get') + def test_get_closest_character_not_found(self, mock_get): + mock_response = Mock() + response_body = "1boy, male focus, uzumaki naruto, naruto \\(series\\)\n1boy, male focus, uzumaki boruto, naruto \\(series\\)\n1girl, uzumaki himawari, naruto \\(series\\)\n1girl, carrot \\(one piece\\), one piece\n1girl, uzumaki kushina, naruto \\(series\\)\n" + mock_response.text = response_body + mock_get.return_value = mock_response + closest_name = get_closest_character("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") self.assertIsNone(closest_name) diff --git a/src/tests/test_game_info.py b/src/tests/test_game_info.py index 4eb7ce7..e3f47f0 100644 --- a/src/tests/test_game_info.py +++ b/src/tests/test_game_info.py @@ -1,7 +1,6 @@ import time import unittest from unittest.mock import patch, Mock -from requests.exceptions import HTTPError from src.image.game_info import ( GameInfo, get_year_recency, get_summary_keywords, is_relevant_adjective From 2864b02246b2843a054b945ed0aa00aeeeb0a87a Mon Sep 17 00:00:00 2001 From: Matzey Date: Sun, 21 Apr 2024 20:48:26 +0200 Subject: [PATCH 05/11] removed enviroment variables --- .github/workflows/tests.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f01d0c4..d95cf6a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -27,9 +27,5 @@ jobs: pip install -r requirements.txt - name: Run unit tests - env: - NLTK_DATA: ${{ secrets.NLTK_DATA }} - TWITCH_CLIENT_ID: ${{ secrets.TWITCH_CLIENT_ID }} - TWITCH_CLIENT_SECRET: ${{ secrets.TWITCH_CLIENT_SECRET }} run: | python -m unittest discover -s src/tests -p 'test_*.py' From 2cec7910b22f6926bd3c377a52dc6607915acec2 Mon Sep 17 00:00:00 2001 From: Matzey Date: Sun, 21 Apr 2024 23:07:30 +0200 Subject: [PATCH 06/11] restored GUI and css to former state --- resources/form.scss | 12 ------------ src/main.py | 19 ++++++------------- 2 files changed, 6 insertions(+), 25 deletions(-) diff --git a/resources/form.scss b/resources/form.scss index a6e3a98..0a6145d 100644 --- a/resources/form.scss +++ b/resources/form.scss @@ -42,16 +42,4 @@ $font-size: 16px; color: $main-color; background-color: $main-color; } -} - -.QComboBox { - color: $secondary-accent-color; - border: none; - border-bottom: 2px solid $accent-color; - padding-bottom: 2px; - background: $main-color; -} - -QComboBox QAbstractItemView { - background-color: $secondary-color; } \ No newline at end of file diff --git a/src/main.py b/src/main.py index 7878f4c..4690b9a 100644 --- a/src/main.py +++ b/src/main.py @@ -6,8 +6,8 @@ from PySide6.QtWidgets import ( # pylint: disable=E0611 QApplication, QMainWindow, QLabel, - QComboBox, QLineEdit, QPushButton, - QVBoxLayout, QWidget, QHBoxLayout + QLineEdit, QPushButton, QVBoxLayout, + QWidget, QHBoxLayout ) from PySide6.QtGui import QPixmap, QImage # pylint: disable=E0611 from PySide6.QtCore import Qt # pylint: disable=E0611 @@ -112,8 +112,8 @@ def __init__(self): "game_name": QLineEdit(), "facial_expression": QLineEdit("smile"), "looking_at": QLineEdit("viewer"), - "indoors": QComboBox(), - "daytime": QComboBox(), + "indoors": QLineEdit("indoors"), + "daytime": QLineEdit("night"), "additional_tags": QLineEdit() } self.inputs_labels = { @@ -139,9 +139,6 @@ def __init__(self): "prev_button": QPushButton("<"), "next_button": QPushButton(">"), } - self.inputs["indoors"].addItems(["indoors", "outdoors"]) - self.inputs["daytime"].addItems(["day", "night"]) - self.setup_ui() self.show_input_fields() @@ -198,12 +195,8 @@ def generate_image(self): return self.input_controls["generate_button"].setDisabled(True) - input_values = {} - for key, widget in self.inputs.items(): - if type(widget) == type(QComboBox()): - input_values[key] = widget.currentText().lower().replace(',', ' ').lstrip().rstrip() - else: - input_values[key] = widget.text().lower().replace(',', ' ').lstrip().rstrip() + input_values = {key: widget.text().lower().replace(',', ' ').lstrip().rstrip() + for key, widget in self.inputs.items()} threading.Thread(target=self.image_generator.process_image, args=(input_values, self)).start() From f75459594a71beba8727fedc0b0e9fc318a9a342 Mon Sep 17 00:00:00 2001 From: Matzey Date: Mon, 22 Apr 2024 10:32:38 +0200 Subject: [PATCH 07/11] improved on pylama complaints --- src/image/game_info.py | 1 - src/tests/test_character_info.py | 46 +++++++++++++++++++++++++++----- src/tests/test_game_info.py | 26 ++++++++++++------ 3 files changed, 57 insertions(+), 16 deletions(-) diff --git a/src/image/game_info.py b/src/image/game_info.py index ce3e4bd..be1787d 100644 --- a/src/image/game_info.py +++ b/src/image/game_info.py @@ -85,7 +85,6 @@ def authenticate(self): self.authentication_time = time.time() return - def get_game_info(self, name): """ Fetch game information from the IGDB API. diff --git a/src/tests/test_character_info.py b/src/tests/test_character_info.py index 7c21f26..5f3ecc3 100644 --- a/src/tests/test_character_info.py +++ b/src/tests/test_character_info.py @@ -13,7 +13,20 @@ def __init__(self, methodName: str = "runTest") -> None: @patch('requests.get') def test_get_all_characters(self, mock_get): mock_response = Mock() - response_body = "1girl, souryuu asuka langley, neon genesis evangelion\n1girl, warrior of light \\(ff14\\), final fantasy\n1girl, akiyama mio, k-on!\n1girl, tifa lockhart, final fantasy\n1girl, 2b \\(nier:automata\\), nier \\(series\\)\n1girl, nakano azusa, k-on!\n1girl, rem \\(re:zero\\), re:zero kara hajimeru isekai seikatsu\n1girl, hirasawa yui, k-on!\n1girl, gotoh hitori, bocchi the rock!\n1girl, ayanami rei, neon genesis evangelion\n1boy, male focus, joseph joestar, jojo no kimyou na bouken\n1girl, matoi ryuuko, kill la kill\n1girl, yor briar, spy x family\n1girl, tainaka ritsu, k-on!\n" + response_body = ("1girl, souryuu asuka langley, neon genesis evangelion\n" + "1girl, warrior of light \\(ff14\\), final fantasy\n" + "1girl, akiyama mio, k-on!\n" + "1girl, tifa lockhart, final fantasy\n" + "1girl, 2b \\(nier:automata\\), nier \\(series\\)\n" + "1girl, nakano azusa, k-on!\n" + "1girl, rem \\(re:zero\\), re:zero kara hajimeru isekai seikatsu\n" + "1girl, hirasawa yui, k-on!\n" + "1girl, gotoh hitori, bocchi the rock!\n" + "1girl, ayanami rei, neon genesis evangelion\n" + "1boy, male focus, joseph joestar, jojo no kimyou na bouken\n" + "1girl, matoi ryuuko, kill la kill\n" + "1girl, yor briar, spy x family\n" + "1girl, tainaka ritsu, k-on!\n") mock_response.text = response_body mock_get.return_value = mock_response @@ -21,14 +34,26 @@ def test_get_all_characters(self, mock_get): self.assertIsInstance(characters, list) self.assertTrue(all(isinstance(c, str) for c in characters)) - + @patch('requests.get') def test_get_closest_character(self, mock_get): mock_response = Mock() - response_body = "1girl, souryuu asuka langley, neon genesis evangelion\n1girl, warrior of light \\(ff14\\), final fantasy\n1girl, akiyama mio, k-on!\n1girl, tifa lockhart, final fantasy\n1girl, 2b \\(nier:automata\\), nier \\(series\\)\n1girl, nakano azusa, k-on!\n1girl, rem \\(re:zero\\), re:zero kara hajimeru isekai seikatsu\n1girl, hirasawa yui, k-on!\n1girl, gotoh hitori, bocchi the rock!\n1girl, ayanami rei, neon genesis evangelion\n1boy, male focus, joseph joestar, jojo no kimyou na bouken\n1girl, matoi ryuuko, kill la kill\n1girl, yor briar, spy x family\n1girl, tainaka ritsu, k-on!\n" + response_body = ("1girl, souryuu asuka langley, neon genesis evangelion\n" + "1girl, warrior of light \\(ff14\\), final fantasy\n" + "1girl, akiyama mio, k-on!\n" + "1girl, tifa lockhart, final fantasy\n" + "1girl, 2b \\(nier:automata\\), nier \\(series\\)\n" + "1girl, nakano azusa, k-on!\n" + "1girl, rem \\(re:zero\\), re:zero kara hajimeru isekai seikatsu\n" + "1girl, hirasawa yui, k-on!\n" + "1girl, gotoh hitori, bocchi the rock!\n" + "1girl, ayanami rei, neon genesis evangelion\n" + "1boy, male focus, joseph joestar, jojo no kimyou na bouken\n" + "1girl, matoi ryuuko, kill la kill\n" + "1girl, yor briar, spy x family\n" + "1girl, tainaka ritsu, k-on!\n") mock_response.text = response_body mock_get.return_value = mock_response - closest_name = get_closest_character("Asuka Langley") self.assertEqual(closest_name, "1girl, souryuu asuka langley, neon genesis evangelion") @@ -36,7 +61,11 @@ def test_get_closest_character(self, mock_get): @patch('requests.get') def test_get_closest_characters(self, mock_get): mock_response = Mock() - response_body = "1boy, male focus, uzumaki naruto, naruto \\(series\\)\n1boy, male focus, uzumaki boruto, naruto \\(series\\)\n1girl, uzumaki himawari, naruto \\(series\\)\n1girl, carrot \\(one piece\\), one piece\n1girl, uzumaki kushina, naruto \\(series\\)\n" + response_body = ("1boy, male focus, uzumaki naruto, naruto \\(series\\)\n" + "1boy, male focus, uzumaki boruto, naruto \\(series\\)\n" + "1girl, uzumaki himawari, naruto \\(series\\)\n" + "1girl, carrot \\(one piece\\), one piece\n" + "1girl, uzumaki kushina, naruto \\(series\\)\n") mock_response.text = response_body mock_get.return_value = mock_response @@ -49,10 +78,13 @@ def test_get_closest_characters(self, mock_get): @patch('requests.get') def test_get_closest_character_not_found(self, mock_get): mock_response = Mock() - response_body = "1boy, male focus, uzumaki naruto, naruto \\(series\\)\n1boy, male focus, uzumaki boruto, naruto \\(series\\)\n1girl, uzumaki himawari, naruto \\(series\\)\n1girl, carrot \\(one piece\\), one piece\n1girl, uzumaki kushina, naruto \\(series\\)\n" + response_body = ("1boy, male focus, uzumaki naruto, naruto \\(series\\)\n" + "1boy, male focus, uzumaki boruto, naruto \\(series\\)\n" + "1girl, uzumaki himawari, naruto \\(series\\)\n" + "1girl, carrot \\(one piece\\), one piece\n" + "1girl, uzumaki kushina, naruto \\(series\\)\n") mock_response.text = response_body mock_get.return_value = mock_response - closest_name = get_closest_character("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") self.assertIsNone(closest_name) diff --git a/src/tests/test_game_info.py b/src/tests/test_game_info.py index e3f47f0..9ea4648 100644 --- a/src/tests/test_game_info.py +++ b/src/tests/test_game_info.py @@ -15,7 +15,7 @@ def __init__(self, methodName: str = "runTest") -> None: @patch('requests.post') def test_authenticate(self, mock_post): """ - Test Twitch API Authentication + Test Twitch API Authentication """ mock_response = Mock() response_body = { @@ -31,7 +31,7 @@ def test_authenticate(self, mock_post): self.assertIsNotNone(self.game_info.token) self.assertTrue(time.time() - response_body["expires_in"] < self.game_info.authentication_time) - + @patch("requests.post") @patch("src.image.game_info.GameInfo.authenticate", Mock()) def test_get_game_info(self, mock_post_info): @@ -44,12 +44,20 @@ def test_get_game_info(self, mock_post_info): 'first_release_date': 1424217600, 'genres': [4], 'name': 'Tekken 7', - 'summary': 'Experience the epic conclusion of the Mishima clan and unravel the reasons behind each step of their ceaseless fight. Powered by Unreal Engine 4, Tekken 7 features stunning story-driven cinematic battles and intense duels that can be enjoyed with friends and rivals alike through innovative fight mechanics.' + 'summary': ('Experience the epic conclusion of the Mishima clan and unravel ' + 'the reasons behind each step of their ceaseless fight. ' + 'Powered by Unreal Engine 4, Tekken 7 features stunning ' + 'story-driven cinematic battles and intense duels that ' + 'can be enjoyed with friends and rivals alike through ' + 'innovative fight mechanics.') }, {}] mock_response.json.return_value = response_body mock_post_info.return_value = mock_response - - self.game_info.token = {"access_token": "someAccessToken", "expires_in": 9112004, "token_type": "bearer"} + self.game_info.token = { + "access_token": "someAccessToken", + "expires_in": 9112004, + "token_type": "bearer" + } info = self.game_info.get_game_info("Tekken 7") self.assertEqual(response_body[0], info) @@ -67,8 +75,11 @@ def test_get_genres(self, mock_post): }] mock_response.json.return_value = response_body mock_post.return_value = mock_response - - self.game_info.token = {"access_token": "someAccessToken", "expires_in": 9112004, "token_type": "bearer"} + self.game_info.token = { + "access_token": "someAccessToken", + "expires_in": 9112004, + "token_type": "bearer" + } self.game_info.get_genres([4]) self.assertEqual(response_body[0]["name"], 'Fighting') @@ -84,7 +95,6 @@ def test_get_game_keywords(self, mock_get): } mock_response.json.return_value = response_body mock_get.return_value = mock_response - keywords = self.game_info.get_game_keywords('Tekken 7') self.assertIsNotNone(keywords) From 16cb452d3229d421271d4c424e0fc3cd8ebd9651 Mon Sep 17 00:00:00 2001 From: Matzey Date: Mon, 22 Apr 2024 10:56:28 +0200 Subject: [PATCH 08/11] Update test_game_info.py --- src/tests/test_game_info.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tests/test_game_info.py b/src/tests/test_game_info.py index 9ea4648..35642e8 100644 --- a/src/tests/test_game_info.py +++ b/src/tests/test_game_info.py @@ -85,6 +85,7 @@ def test_get_genres(self, mock_post): self.assertEqual(response_body[0]["name"], 'Fighting') @patch("requests.get") + @patch("src.image.game_info.GameInfo.authenticate", Mock()) def test_get_game_keywords(self, mock_get): """ Test IGDB Response on https://api.igdb.com/v4/genres @@ -95,6 +96,11 @@ def test_get_game_keywords(self, mock_get): } mock_response.json.return_value = response_body mock_get.return_value = mock_response + self.game_info.token = { + "access_token": "someAccessToken", + "expires_in": 9112004, + "token_type": "bearer" + } keywords = self.game_info.get_game_keywords('Tekken 7') self.assertIsNotNone(keywords) From cf2b6f90fa0efd219c1829602d33de1766de0dd0 Mon Sep 17 00:00:00 2001 From: Matzey Date: Mon, 22 Apr 2024 11:43:49 +0200 Subject: [PATCH 09/11] Update test_game_info.py --- src/tests/test_game_info.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/tests/test_game_info.py b/src/tests/test_game_info.py index 35642e8..75f4b42 100644 --- a/src/tests/test_game_info.py +++ b/src/tests/test_game_info.py @@ -85,7 +85,18 @@ def test_get_genres(self, mock_post): self.assertEqual(response_body[0]["name"], 'Fighting') @patch("requests.get") - @patch("src.image.game_info.GameInfo.authenticate", Mock()) + @patch("src.image.game_info.GameInfo.get_game_info", + Mock(return_value={ + 'id': 7498, + 'first_release_date': 1424217600, + 'genres': [4], + 'name': 'Tekken 7', + 'summary': ('Experience the epic conclusion of the Mishima clan and unravel ' + 'the reasons behind each step of their ceaseless fight. ' + 'Powered by Unreal Engine 4, Tekken 7 features stunning ' + 'story-driven cinematic battles and intense duels that ' + 'can be enjoyed with friends and rivals alike through ' + 'innovative fight mechanics.')})) def test_get_game_keywords(self, mock_get): """ Test IGDB Response on https://api.igdb.com/v4/genres From 099bdf1c40697bcfef2ad4cc4ac0bd87929ab379 Mon Sep 17 00:00:00 2001 From: K0ntr4 Date: Mon, 22 Apr 2024 11:58:14 +0200 Subject: [PATCH 10/11] improved reusability for mocking for get_game_keywords improved reusability for mocking for get_game_keywords --- src/tests/test_game_info.py | 50 +++++++++++++------------------------ 1 file changed, 18 insertions(+), 32 deletions(-) diff --git a/src/tests/test_game_info.py b/src/tests/test_game_info.py index 75f4b42..086fcf0 100644 --- a/src/tests/test_game_info.py +++ b/src/tests/test_game_info.py @@ -6,6 +6,19 @@ get_summary_keywords, is_relevant_adjective ) +TEKKEN_GAME_INFO = { + 'id': 7498, + 'first_release_date': 1424217600, + 'genres': [4], + 'name': 'Tekken 7', + 'summary': ('Experience the epic conclusion of the Mishima clan and unravel ' + 'the reasons behind each step of their ceaseless fight. ' + 'Powered by Unreal Engine 4, Tekken 7 features stunning ' + 'story-driven cinematic battles and intense duels that ' + 'can be enjoyed with friends and rivals alike through ' + 'innovative fight mechanics.') + } + class TestGameInfo(unittest.TestCase): def __init__(self, methodName: str = "runTest") -> None: @@ -39,18 +52,7 @@ def test_get_game_info(self, mock_post_info): Test IGDB Response on https://api.igdb.com/v4/games """ mock_response = Mock() - response_body = [{ - 'id': 7498, - 'first_release_date': 1424217600, - 'genres': [4], - 'name': 'Tekken 7', - 'summary': ('Experience the epic conclusion of the Mishima clan and unravel ' - 'the reasons behind each step of their ceaseless fight. ' - 'Powered by Unreal Engine 4, Tekken 7 features stunning ' - 'story-driven cinematic battles and intense duels that ' - 'can be enjoyed with friends and rivals alike through ' - 'innovative fight mechanics.') - }, {}] + response_body = [TEKKEN_GAME_INFO, {}] mock_response.json.return_value = response_body mock_post_info.return_value = mock_response self.game_info.token = { @@ -84,29 +86,13 @@ def test_get_genres(self, mock_post): self.assertEqual(response_body[0]["name"], 'Fighting') - @patch("requests.get") - @patch("src.image.game_info.GameInfo.get_game_info", - Mock(return_value={ - 'id': 7498, - 'first_release_date': 1424217600, - 'genres': [4], - 'name': 'Tekken 7', - 'summary': ('Experience the epic conclusion of the Mishima clan and unravel ' - 'the reasons behind each step of their ceaseless fight. ' - 'Powered by Unreal Engine 4, Tekken 7 features stunning ' - 'story-driven cinematic battles and intense duels that ' - 'can be enjoyed with friends and rivals alike through ' - 'innovative fight mechanics.')})) - def test_get_game_keywords(self, mock_get): + @patch("src.image.game_info.GameInfo.get_game_info", Mock(return_value=TEKKEN_GAME_INFO)) + @patch("src.image.game_info.GameInfo.get_genres", Mock(return_value=['Fighting'])) + @patch("src.image.game_info.GameInfo.authenticate", Mock()) + def test_get_game_keywords(self): """ Test IGDB Response on https://api.igdb.com/v4/genres """ - mock_response = Mock() - response_body = { - "mid": ["clan", "Experience", "epic", "conclusion", "reasons", "Fighting"] - } - mock_response.json.return_value = response_body - mock_get.return_value = mock_response self.game_info.token = { "access_token": "someAccessToken", "expires_in": 9112004, From ba99123c2709b8aeb0c4b0c682f38fe4726fd82a Mon Sep 17 00:00:00 2001 From: K0ntr4 Date: Mon, 22 Apr 2024 12:00:11 +0200 Subject: [PATCH 11/11] improved coding style improved coding style --- src/tests/test_game_info.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/tests/test_game_info.py b/src/tests/test_game_info.py index 086fcf0..6a6f430 100644 --- a/src/tests/test_game_info.py +++ b/src/tests/test_game_info.py @@ -7,17 +7,17 @@ ) TEKKEN_GAME_INFO = { - 'id': 7498, - 'first_release_date': 1424217600, - 'genres': [4], - 'name': 'Tekken 7', - 'summary': ('Experience the epic conclusion of the Mishima clan and unravel ' - 'the reasons behind each step of their ceaseless fight. ' - 'Powered by Unreal Engine 4, Tekken 7 features stunning ' - 'story-driven cinematic battles and intense duels that ' - 'can be enjoyed with friends and rivals alike through ' - 'innovative fight mechanics.') - } + 'id': 7498, + 'first_release_date': 1424217600, + 'genres': [4], + 'name': 'Tekken 7', + 'summary': ('Experience the epic conclusion of the Mishima clan and unravel ' + 'the reasons behind each step of their ceaseless fight. ' + 'Powered by Unreal Engine 4, Tekken 7 features stunning ' + 'story-driven cinematic battles and intense duels that ' + 'can be enjoyed with friends and rivals alike through ' + 'innovative fight mechanics.') +} class TestGameInfo(unittest.TestCase):