-
Notifications
You must be signed in to change notification settings - Fork 55
Expand file tree
/
Copy pathtest_games.py
More file actions
197 lines (163 loc) · 7 KB
/
test_games.py
File metadata and controls
197 lines (163 loc) · 7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
import unittest
import json
from typing import Dict, Any
from flask import Flask, Response
from models import Game, Publisher, Category, db
from routes.games import games_bp
class TestGamesRoutes(unittest.TestCase):
# Test data as complete objects
TEST_DATA: Dict[str, Any] = {
"publishers": [
{"name": "DevGames Inc"},
{"name": "Scrum Masters"}
],
"categories": [
{"name": "Strategy"},
{"name": "Card Game"}
],
"games": [
{
"title": "Pipeline Panic",
"description": "Build your DevOps pipeline before chaos ensues",
"publisher_index": 0,
"category_index": 0,
"star_rating": 4.5
},
{
"title": "Agile Adventures",
"description": "Navigate your team through sprints and releases",
"publisher_index": 1,
"category_index": 1,
"star_rating": 4.2
}
]
}
# API paths
GAMES_API_PATH: str = '/api/games'
def setUp(self) -> None:
"""Set up test database and seed data"""
# Create a fresh Flask app for testing
self.app = Flask(__name__)
self.app.config['TESTING'] = True
self.app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
self.app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# Register the games blueprint
self.app.register_blueprint(games_bp)
# Initialize the test client
self.client = self.app.test_client()
# Initialize in-memory database for testing
db.init_app(self.app)
# Create tables and seed data
with self.app.app_context():
db.create_all()
self._seed_test_data()
def tearDown(self) -> None:
"""Clean up test database and ensure proper connection closure"""
with self.app.app_context():
db.session.remove()
db.drop_all()
db.engine.dispose()
def _seed_test_data(self) -> None:
"""Helper method to seed test data"""
# Create test publishers
publishers = [
Publisher(**publisher_data) for publisher_data in self.TEST_DATA["publishers"]
]
db.session.add_all(publishers)
# Create test categories
categories = [
Category(**category_data) for category_data in self.TEST_DATA["categories"]
]
db.session.add_all(categories)
# Commit to get IDs
db.session.commit()
# Create test games
games = []
for game_data in self.TEST_DATA["games"]:
game_dict = game_data.copy()
publisher_index = game_dict.pop("publisher_index")
category_index = game_dict.pop("category_index")
games.append(Game(
**game_dict,
publisher=publishers[publisher_index],
category=categories[category_index]
))
db.session.add_all(games)
db.session.commit()
def _get_response_data(self, response: Response) -> Any:
"""Helper method to parse response data"""
return json.loads(response.data)
def test_get_games_success(self) -> None:
"""Test successful retrieval of multiple games"""
# Act
response = self.client.get(self.GAMES_API_PATH)
data = self._get_response_data(response)
# Assert
self.assertEqual(response.status_code, 200)
self.assertEqual(len(data), len(self.TEST_DATA["games"]))
# Verify all games using loop instead of manual testing
for i, game_data in enumerate(data):
test_game = self.TEST_DATA["games"][i]
test_publisher = self.TEST_DATA["publishers"][test_game["publisher_index"]]
test_category = self.TEST_DATA["categories"][test_game["category_index"]]
self.assertEqual(game_data['title'], test_game["title"])
self.assertEqual(game_data['publisher']['name'], test_publisher["name"])
self.assertEqual(game_data['category']['name'], test_category["name"])
self.assertEqual(game_data['starRating'], test_game["star_rating"])
def test_get_games_structure(self) -> None:
"""Test the response structure for games"""
# Act
response = self.client.get(self.GAMES_API_PATH)
data = self._get_response_data(response)
# Assert
self.assertEqual(response.status_code, 200)
self.assertIsInstance(data, list)
self.assertEqual(len(data), len(self.TEST_DATA["games"]))
required_fields = ['id', 'title', 'description', 'publisher', 'category', 'starRating']
for field in required_fields:
self.assertIn(field, data[0])
def test_get_game_by_id_success(self) -> None:
"""Test successful retrieval of a single game by ID"""
# Get the first game's ID from the list endpoint
response = self.client.get(self.GAMES_API_PATH)
games = self._get_response_data(response)
game_id = games[0]['id']
# Act
response = self.client.get(f'{self.GAMES_API_PATH}/{game_id}')
data = self._get_response_data(response)
# Assert
first_game = self.TEST_DATA["games"][0]
first_publisher = self.TEST_DATA["publishers"][first_game["publisher_index"]]
self.assertEqual(response.status_code, 200)
self.assertEqual(data['title'], first_game["title"])
self.assertEqual(data['publisher']['name'], first_publisher["name"])
def test_get_game_by_id_not_found(self) -> None:
"""Test retrieval of a non-existent game by ID"""
# Act
response = self.client.get(f'{self.GAMES_API_PATH}/999')
data = self._get_response_data(response)
# Assert
self.assertEqual(response.status_code, 404)
self.assertEqual(data['error'], "Game not found")
def test_get_games_empty_database(self) -> None:
"""Test retrieval of games when database is empty"""
# Clear all games from the database
with self.app.app_context():
db.session.query(Game).delete()
db.session.commit()
# Act
response = self.client.get(self.GAMES_API_PATH)
data = self._get_response_data(response)
# Assert
self.assertEqual(response.status_code, 200)
self.assertIsInstance(data, list)
self.assertEqual(len(data), 0)
def test_get_game_by_invalid_id_type(self) -> None:
"""Test retrieval of a game with invalid ID type"""
# Act
response = self.client.get(f'{self.GAMES_API_PATH}/invalid-id')
# Assert
# Flask should return 404 for routes that don't match the <int:id> pattern
self.assertEqual(response.status_code, 404)
if __name__ == '__main__':
unittest.main()