Skip to content

Commit d9c25a3

Browse files
authoredNov 12, 2022
Chore/flake8 error fix (#11)
* feat(board.html): add template for points display board * feat(server): add route for points display board * feat(board.html): complete template * test(test_points_board): start testing happy path * feat(board.html): add condition if no clubs in json * test(test_points_board): add sad path to test * test(units/): add test_unlimited_points.py * fix(server): add condition to limit purchase * fix(booking.html): add display of flash message * test(units/): test_unlimited_points.py passed * test(units/): change docstrings in test_unlimited_points.py * test(units/): done test_unlimited_points.py * fix(issue): [OpenClassrooms-Student-Center#2] * test(units/): add test_points_not_update.py with TDD approch added test and failed * fix(server): add substraction points after book places * test(units/): run test_points_not_update.py and passed * fix(issue): [OpenClassrooms-Student-Center#6] * test(units/): add test_book_under_12.py with TDD method: started with failed test * fix(server): add condition if book more 12 places * test(units/): complete test_book_under_12.py and run tests passed * fix(issue): [OpenClassrooms-Student-Center#4] * test(functional/): add & complete test_route.py * fix(404.html): add 404 handler and template * fix(500.html): add 500 handler and template * test(functional/): add & complete test_load_json.py * test(integration/): add & complete test of app * fix(server): issue book more than places available * test(integration/): cleanup test_app * test(coverage/): make changes to have 100% test coverage * test(requirements.txt): install Locust * test(performance/): configure locust * test(performance/): add README * refactor(app): flake8 html report 100% clean * refactor(app): remove unused fixtures
1 parent 2be9885 commit d9c25a3

12 files changed

+97
-94
lines changed
 

‎server.py

+22-15
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
import json
22
import datetime
3-
from flask import Flask,render_template,request,redirect,flash,url_for, abort
3+
from flask import Flask, render_template, request, redirect, flash, url_for
44

55

66
# ============================================ FLASK APP INITIALIZATION
77

88
app = Flask(__name__)
99
app.secret_key = 'something_special'
1010

11+
1112
def page_not_found(e):
1213
return render_template('404.html'), 404
1314

15+
1416
app.register_error_handler(404, page_not_found)
1517

1618

@@ -20,7 +22,7 @@ def page_not_found(e):
2022
PATH_JSON_CLUBS = 'clubs.json'
2123
PATH_JSON_COMPETITIONS = 'competitions.json'
2224

23-
# ============================================ LOAD JSON DATA
25+
# ============================================ LOAD JSON DATA
2426

2527

2628
def loadClubs():
@@ -30,7 +32,7 @@ def loadClubs():
3032
listOfClubs = json.load(c)['clubs']
3133
if listOfClubs and len(listOfClubs) > 0:
3234
return listOfClubs
33-
else :
35+
else:
3436
raise Exception("This file is empty, or key not found")
3537

3638
except Exception as error:
@@ -42,14 +44,16 @@ def loadCompetitions():
4244
if PATH_JSON_COMPETITIONS:
4345
with open(PATH_JSON_COMPETITIONS) as c:
4446
listOfCompetitions = json.load(c)['competitions']
47+
listOfCompetitions.sort(key=lambda x: x["date"], reverse=True)
4548
if listOfCompetitions and len(listOfCompetitions) > 0:
4649
return listOfCompetitions
47-
else :
50+
else:
4851
raise Exception("This file is empty, or key not found")
4952

5053
except Exception as error:
5154
return str(error)
5255

56+
5357
competitions = loadCompetitions()
5458
clubs = loadClubs()
5559
now = datetime.datetime.now()
@@ -86,7 +90,7 @@ def show_summary():
8690
"""
8791
try:
8892
club = [club for club in clubs if club['email'] == request.form['email']][0]
89-
93+
9094
if club:
9195
return render_template('welcome.html', club=club, competitions=competitions, current_date=current_date)
9296

@@ -99,7 +103,7 @@ def show_summary():
99103

100104

101105
@app.route('/book/<competition>/<club>')
102-
def book(competition,club):
106+
def book(competition, club):
103107
"""
104108
Displays :
105109
Competition's name and places available
@@ -108,7 +112,7 @@ def book(competition,club):
108112
try:
109113
foundClub = [c for c in clubs if c['name'] == club][0]
110114
foundCompetition = [c for c in competitions if c['name'] == competition][0]
111-
return render_template('booking.html',club=foundClub,competition=foundCompetition)
115+
return render_template('booking.html', club=foundClub, competition=foundCompetition)
112116

113117
except IndexError:
114118
flash("Sorry, this club or competition wasn't found !!")
@@ -123,7 +127,7 @@ def book(competition,club):
123127
}
124128

125129

126-
@app.route('/purchasePlaces',methods=['POST'])
130+
@app.route('/purchasePlaces', methods=['POST'])
127131
@app.errorhandler(400)
128132
def purchase_places():
129133
"""
@@ -146,13 +150,13 @@ def purchase_places():
146150
elif placesRequired > club_points:
147151
flash("Sorry, your club doesn't have enough points !")
148152
return render_template('booking.html', club=club, competition=competition, current_date=current_date), 400
149-
150-
elif placesRequired > MAX_PLACES :
153+
154+
elif placesRequired > MAX_PLACES:
151155
flash(f"Sorry, you can't book more than {MAX_PLACES} places !")
152156
return render_template('booking.html', club=club, competition=competition, current_date=current_date), 400
153-
154-
elif placesRequired + current_cart > MAX_PLACES :
155-
flash(f"""Sorry, you have already booked places, for this competition
157+
158+
elif placesRequired + current_cart > MAX_PLACES:
159+
flash(f"""Sorry, you have already booked places, for this competition
156160
and now you have exceeded the limit of {MAX_PLACES} places !""")
157161
return render_template('booking.html', club=club, competition=competition, current_date=current_date), 400
158162

@@ -163,13 +167,16 @@ def purchase_places():
163167
else:
164168
competition['numberOfPlaces'] = int(competition['numberOfPlaces'])-placesRequired
165169

166-
club['points'] = int(club['points'])- placesRequired
170+
club['points'] = int(club['points']) - placesRequired
167171

168172
cart[competition["name"]][club["name"]] += placesRequired
169173

170174
flash(f"Great you have booked {placesRequired} places! for {competition['name']}")
171175

172-
return render_template('welcome.html', club=club, competitions=competitions, current_date=current_date, add_to_cart=cart[competition["name"]][club["name"]])
176+
return render_template('welcome.html',
177+
club=club, competitions=competitions,
178+
current_date=current_date,
179+
add_to_cart=cart[competition["name"]][club["name"]])
173180

174181
# ================================================= ROUTE FOR BOARD DISPLAY
175182

‎tests/conftest.py

+31-42
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import pytest
2-
# from server import app
32
import server
43

5-
# ============================================= FIXTURES
4+
# ============================================= FIXTURES CLIENT TESTING
65

76

87
@pytest.fixture
@@ -11,6 +10,9 @@ def client():
1110
yield client
1211

1312

13+
# ================================================== FIXTURE FOR CLUBS TESTING
14+
15+
1416
@pytest.fixture
1517
def clubs_fixture():
1618
return [
@@ -32,35 +34,7 @@ def clubs_fixture():
3234
]
3335

3436

35-
@pytest.fixture
36-
def empty_clubs_fixture():
37-
return {
38-
"competitions": [
39-
],
40-
"clubs": [
41-
]
42-
}
43-
44-
45-
@pytest.fixture
46-
def unknown_club():
47-
return [
48-
{
49-
"name": "Fake club",
50-
"email": "sam@email.co",
51-
"points": "12"
52-
},
53-
{
54-
"name": "Unknown Club",
55-
"email": "jim@gmail.com",
56-
"points": "9"
57-
},
58-
{
59-
"name": "invisible Club",
60-
"email": "sarah@yahoo.co.uk",
61-
"points": "16"
62-
}
63-
]
37+
# ================================================== FIXTURE FOR COMPETITIONS TESTING
6438

6539

6640
@pytest.fixture
@@ -88,20 +62,30 @@ def competitions_fixture():
8862
}
8963
]
9064

65+
66+
# ================================================== FIXTURE TO AVOID BOOKING MORE THAN 12 PLACES
67+
68+
9169
@pytest.fixture
9270
def cart_fixture(competitions_fixture, clubs_fixture):
9371
return {
94-
competition["name"]: {club["name"]: 0 for club in clubs_fixture}
95-
for competition in competitions_fixture
96-
}
72+
competition["name"]: {club["name"]: 0 for club in clubs_fixture}
73+
for competition in competitions_fixture
74+
}
75+
76+
77+
# ================================================== FIXTURE TO AVOID REPETITIONS OF CALLING FIXTURE IN PARAMETERS
9778

9879

9980
@pytest.fixture
10081
def fixture(mocker, clubs_fixture, competitions_fixture, cart_fixture):
10182
return [mocker, clubs_fixture, competitions_fixture, cart_fixture]
10283

10384

104-
def get(fixture, case , places=0):
85+
# ================================================== FIXTURE TO AVOID REPETITIONS IN FUNCTIONS TESTING
86+
87+
88+
def get(fixture, case, places=0):
10589
fixture[0].patch.object(server, 'clubs', fixture[1])
10690
fixture[0].patch.object(server, 'competitions', fixture[2])
10791
fixture[0].patch.object(server, 'cart', fixture[3])
@@ -117,11 +101,11 @@ def get(fixture, case , places=0):
117101
elif case == "wrong_email":
118102
return {"email": "unknown_email@gmail.com"}
119103

120-
elif case == "club_competition":
104+
elif case == "valid_club_competition":
121105
data_book = {'competition': valid_competition, 'club': valid_club}
122106
return data_book
123107

124-
elif case == "club_unknown-competition":
108+
elif case == "club_unknown_competition":
125109
return {'competition': "Black Race", 'club': valid_club}
126110

127111
elif case == "club_competition_places":
@@ -144,22 +128,27 @@ def get(fixture, case , places=0):
144128
return data_purchase_places
145129

146130
elif case == "board":
147-
return fixture[1]
148-
131+
return fixture[1]
132+
149133
elif case == "empty_board":
150134
return fixture[0].patch.object(server, 'clubs', '')
151135

152136

153-
FAKE_PATH_JSON_CLUBS = 'fake_club.json'
154-
FAKE_PATH_JSON_COMPETITIONS = 'fake_comp.json'
137+
# ================================================== FIXTURE FOR JSON TESTING
155138

156139

157140
EMPTY_JSON_PATH = 'tests/functional/empty.json'
141+
FAKE_PATH_JSON_CLUBS = 'fake_club.json'
142+
FAKE_PATH_JSON_COMPETITIONS = 'fake_comp.json'
143+
158144

159145
def get_empty_json(mocker):
160146
return mocker.patch.object(
161147
server, 'PATH_JSON_CLUBS', EMPTY_JSON_PATH), mocker.patch.object(
162148
server, 'PATH_JSON_COMPETITIONS', EMPTY_JSON_PATH)
163149

150+
164151
def get_wrong_json_path(mocker):
165-
return mocker.patch.object(server, 'PATH_JSON_CLUBS', FAKE_PATH_JSON_CLUBS), mocker.patch.object(server, 'PATH_JSON_COMPETITIONS', FAKE_PATH_JSON_COMPETITIONS)
152+
return mocker.patch.object(server, 'PATH_JSON_CLUBS',
153+
FAKE_PATH_JSON_CLUBS), mocker.patch.object(
154+
server, 'PATH_JSON_COMPETITIONS', FAKE_PATH_JSON_COMPETITIONS)

‎tests/functional/test_load_json.py

+5-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pytest
2+
import server
23
from server import loadClubs, loadCompetitions
3-
from conftest import get_empty_json, get_wrong_json_path, get
4+
from conftest import get_empty_json, get_wrong_json_path
45

56

67
def test_valid_load_json():
@@ -22,7 +23,7 @@ def test_valid_load_json():
2223
assert len(competitions) > 0
2324

2425

25-
def test_with_empty_json(mocker, empty_clubs_fixture):
26+
def test_with_empty_json(mocker):
2627
"""
2728
BACK END TESTING :
2829
GIVEN empty json files as database for flask app
@@ -36,7 +37,7 @@ def test_with_empty_json(mocker, empty_clubs_fixture):
3637
assert loadCompetitions() == "This file is empty, or key not found"
3738

3839

39-
def test_with_wrong_json_path(client, mocker):
40+
def test_with_wrong_json_path(mocker):
4041
"""
4142
BACK END TESTING :
4243
GIVEN wrong path for json files as database for flask app
@@ -49,7 +50,7 @@ def test_with_wrong_json_path(client, mocker):
4950
assert loadClubs() == "[Errno 2] No such file or directory: 'fake_club.json'"
5051
assert loadCompetitions() == "[Errno 2] No such file or directory: 'fake_comp.json'"
5152

52-
import server
53+
5354
def test_index_with_empty_data(client, mocker):
5455
"""
5556
FRONT END TESTING :
@@ -66,6 +67,3 @@ def test_index_with_empty_data(client, mocker):
6667

6768
assert response.status_code == 500
6869
assert b'500 page' in response.data
69-
70-
# assert isinstance(empty_clubs, str)
71-
# assert isinstance(empty_competitions, str)

‎tests/functional/test_route.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*/logout'
1111
"""
1212

13+
1314
def test_uknown_route(client):
1415
assert client.get('/fakeRoute').status_code == 404
1516

@@ -41,7 +42,7 @@ def test_route_showSummary(client, fixture):
4142

4243
def test_route_book(client, fixture):
4344

44-
data = get(fixture, "club_competition")
45+
data = get(fixture, "valid_club_competition")
4546
response = client.get(f"/book/{data['competition']}/{data['club']}")
4647

4748
assert response.status_code == 200

‎tests/integration/test_app.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def test_app(client, fixture):
2525
response = client.post('/showSummary', data=email)
2626
assert response.status_code == 200
2727

28-
data = get(fixture, "club_competition")
28+
data = get(fixture, "valid_club_competition")
2929
response = client.get(f"/book/{data['competition']}/{data['club']}")
3030
assert response.status_code == 200
3131

0 commit comments

Comments
 (0)