KLEB38 commited on
Commit
6758ac3
·
1 Parent(s): d3a6aa2

feat: add functional tests

Browse files
Files changed (2) hide show
  1. tests/.coverage +0 -0
  2. tests/test_functional.py +235 -0
tests/.coverage ADDED
Binary file (53.2 kB). View file
 
tests/test_functional.py CHANGED
@@ -0,0 +1,235 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi.testclient import TestClient
2
+ from app.main import app
3
+ import logging
4
+
5
+ client = TestClient(app)
6
+
7
+ def test_root():
8
+ response = client.get("/")
9
+ assert response.status_code == 200
10
+ assert response.json() == {"message":"Welcome to the FUTURISYS HR predictor API"}
11
+
12
+ def test_predict_valid():
13
+ payload = {
14
+ "Genre": "M",
15
+ "Statut Marital": "Marié(e)",
16
+ "Département": "Consulting",
17
+ "Poste": "Consultant",
18
+ "Domaine d'étude": "Infra & Cloud",
19
+ "Fréquence de déplacement": "Occasionnel",
20
+ "Heures supplémentaires": "Non",
21
+ "Âge": 32,
22
+ "Revenu mensuel": 4883,
23
+ "Nombre d'expériences précédentes": 1,
24
+ "Années d'expérience totale": 10,
25
+ "Années dans l'entreprise": 10,
26
+ "Années dans le poste actuel": 4,
27
+ "Nombre de formations suivies": 3,
28
+ "Distance domicile-travail": 7,
29
+ "Niveau d'éducation": 2,
30
+ "Années depuis la dernière promotion": 1,
31
+ "Années sous responsable actuel": 1,
32
+ "Satisfaction environnement": 4,
33
+ "Note évaluation précédente": 3,
34
+ "Satisfaction nature du travail": 3,
35
+ "Satisfaction équipe": 1,
36
+ "Satisfaction équilibre pro/perso": 3,
37
+ "Note évaluation actuelle": 3,
38
+ "Augmentation salaire précédente": "18%"
39
+ }
40
+
41
+ response = client.post("/predict", json=payload)
42
+ data = response.json()
43
+
44
+ assert response.status_code == 200
45
+ assert data["statut_employe"] == "The staff has a LOW probability of resigning"
46
+ assert data["probability_score"] == 0.28
47
+ assert data["model_threshold"] == 0.37
48
+
49
+ # Top 5 SHAP factors
50
+ factors = data["top_5_factors"]
51
+ assert list(factors.keys()) == [
52
+ "revenu_mensuel",
53
+ "annees_dans_l_entreprise",
54
+ "statut_marital_Célibataire",
55
+ "distance_domicile_travail",
56
+ "overall_satisfaction"
57
+ ]
58
+
59
+ # Interpretations
60
+ assert factors["revenu_mensuel"]["interpretation"] == "Primary driver — decreases resignation risk"
61
+ assert factors["annees_dans_l_entreprise"]["interpretation"] == "Strong factor — decreases resignation risk"
62
+ assert factors["statut_marital_Célibataire"]["interpretation"] == "Moderate factor — decreases resignation risk"
63
+ assert factors["distance_domicile_travail"]["interpretation"] == "Contributing factor — decreases resignation risk"
64
+ assert factors["overall_satisfaction"]["interpretation"] == "Notable factor — decreases resignation risk"
65
+
66
+ # Feature values
67
+ assert factors["revenu_mensuel"]["feature_value"] == 4883.0
68
+ assert factors["annees_dans_l_entreprise"]["feature_value"] == 10.0
69
+ assert factors["statut_marital_Célibataire"]["feature_value"] == "encoded"
70
+
71
+ assert factors["distance_domicile_travail"]["feature_value"] == 7.0
72
+ assert factors["overall_satisfaction"]["feature_value"] == 2.75
73
+
74
+
75
+ class Test_Predict_422:
76
+
77
+ def test_predict_422_wrong_input(self):
78
+ payload = {
79
+ "Genre": "X", # INSERTION OF WRONG INPUT F OR M
80
+ "Statut Marital": "Marié(e)",
81
+ "Département": "Consulting",
82
+ "Poste": "Consultant",
83
+ "Domaine d'étude": "Infra & Cloud",
84
+ "Fréquence de déplacement": "Occasionnel",
85
+ "Heures supplémentaires": "Non",
86
+ "Âge": 32,
87
+ "Revenu mensuel": 4883,
88
+ "Nombre d'expériences précédentes": 1,
89
+ "Années d'expérience totale": 10,
90
+ "Années dans l'entreprise": 10,
91
+ "Années dans le poste actuel": 4,
92
+ "Nombre de formations suivies": 3,
93
+ "Distance domicile-travail": 7,
94
+ "Niveau d'éducation": 2,
95
+ "Années depuis la dernière promotion": 1,
96
+ "Années sous responsable actuel": 1,
97
+ "Satisfaction environnement": 4,
98
+ "Note évaluation précédente": 3,
99
+ "Satisfaction nature du travail": 3,
100
+ "Satisfaction équipe": 1,
101
+ "Satisfaction équilibre pro/perso": 3,
102
+ "Note évaluation actuelle": 3,
103
+ "Augmentation salaire précédente": "18%"
104
+ }
105
+ response = client.post("/predict", json=payload)
106
+ assert response.status_code == 422
107
+
108
+
109
+ def test_predict_422_wrong_type_str(self):
110
+ payload = {
111
+ "Genre": "M",
112
+ "Statut Marital": "Marié(e)",
113
+ "Département": "Consulting",
114
+ "Poste": "Consultant",
115
+ "Domaine d'étude": "Infra & Cloud",
116
+ "Fréquence de déplacement": "Occasionnel",
117
+ "Heures supplémentaires": "Non",
118
+ "Âge": "trente", #EXPECTED INT
119
+ "Revenu mensuel": 4883,
120
+ "Nombre d'expériences précédentes": 1,
121
+ "Années d'expérience totale": 10,
122
+ "Années dans l'entreprise": 10,
123
+ "Années dans le poste actuel": 4,
124
+ "Nombre de formations suivies": 3,
125
+ "Distance domicile-travail": 7,
126
+ "Niveau d'éducation": 2,
127
+ "Années depuis la dernière promotion": 1,
128
+ "Années sous responsable actuel": 1,
129
+ "Satisfaction environnement": 4,
130
+ "Note évaluation précédente": 3,
131
+ "Satisfaction nature du travail": 3,
132
+ "Satisfaction équipe": 1,
133
+ "Satisfaction équilibre pro/perso": 3,
134
+ "Note évaluation actuelle": 3,
135
+ "Augmentation salaire précédente": "18%"
136
+ }
137
+ response = client.post("/predict", json=payload)
138
+ assert response.status_code == 422
139
+
140
+ def test_predict_422_wrong_type_int(self):
141
+ payload = {
142
+ "Genre": "M",
143
+ "Statut Marital": "Marié(e)",
144
+ "Département": "Consulting",
145
+ "Poste": "Consultant",
146
+ "Domaine d'étude": "Infra & Cloud",
147
+ "Fréquence de déplacement": "Occasionnel",
148
+ "Heures supplémentaires": "Non",
149
+ "Âge": 32,
150
+ "Revenu mensuel": 4883.12,#WRONG TYPE, should be int
151
+ "Nombre d'expériences précédentes": 1,
152
+ "Années d'expérience totale": 10,
153
+ "Années dans l'entreprise": 10,
154
+ "Années dans le poste actuel": 4,
155
+ "Nombre de formations suivies": 3,
156
+ "Distance domicile-travail": 7,
157
+ "Niveau d'éducation": 2,
158
+ "Années depuis la dernière promotion": 1,
159
+ "Années sous responsable actuel": 1,
160
+ "Satisfaction environnement": 4,
161
+ "Note évaluation précédente": 3,
162
+ "Satisfaction nature du travail": 3,
163
+ "Satisfaction équipe": 1,
164
+ "Satisfaction équilibre pro/perso": 3,
165
+ "Note évaluation actuelle": 3,
166
+ "Augmentation salaire précédente": "18%"
167
+ }
168
+ response = client.post("/predict", json=payload)
169
+ assert response.status_code == 422
170
+
171
+ def test_predict_422_incomplete_json(self):
172
+ payload = {
173
+ "Genre": "M",
174
+ "Statut Marital": "Marié(e)",
175
+ "Département": "Consulting",
176
+ "Poste": "Consultant",
177
+ "Domaine d'étude": "Infra & Cloud",
178
+ "Fréquence de déplacement": "Occasionnel",
179
+ "Heures supplémentaires": "Non",
180
+ "Âge": 32,
181
+ "Revenu mensuel": 4883,
182
+ "Nombre d'expériences précédentes": 1,
183
+ "Années d'expérience totale": 10,
184
+ "Années dans l'entreprise": 10,
185
+ "Années dans le poste actuel": 4,
186
+ "Nombre de formations suivies": 3,
187
+ "Niveau d'éducation": 2, #MISSING "Distance domicile-travail"
188
+ "Années depuis la dernière promotion": 1,
189
+ "Années sous responsable actuel": 1,
190
+ "Satisfaction environnement": 4,
191
+ "Note évaluation précédente": 3,
192
+ "Satisfaction nature du travail": 3,
193
+ "Satisfaction équipe": 1,
194
+ "Satisfaction équilibre pro/perso": 3,
195
+ "Note évaluation actuelle": 3,
196
+ "Augmentation salaire précédente": "18%"
197
+ }
198
+ response = client.post("/predict", json=payload)
199
+ assert response.status_code == 422
200
+
201
+ def test_logging(caplog):
202
+ payload = {
203
+ "Genre": "M",
204
+ "Statut Marital": "Marié(e)",
205
+ "Département": "Logistique", #check wrong department
206
+ "Poste": "Consultant",
207
+ "Domaine d'étude": "Infra & Cloud",
208
+ "Fréquence de déplacement": "Occasionnel",
209
+ "Heures supplémentaires": "Non",
210
+ "Âge": 32,
211
+ "Revenu mensuel": 4883,
212
+ "Nombre d'expériences précédentes": 1,
213
+ "Années d'expérience totale": 10,
214
+ "Années dans l'entreprise": 10,
215
+ "Années dans le poste actuel": 4,
216
+ "Nombre de formations suivies": 3,
217
+ "Distance domicile-travail": 7,
218
+ "Niveau d'éducation": 2,
219
+ "Années depuis la dernière promotion": 1,
220
+ "Années sous responsable actuel": 1,
221
+ "Satisfaction environnement": 4,
222
+ "Note évaluation précédente": 3,
223
+ "Satisfaction nature du travail": 3,
224
+ "Satisfaction équipe": 1,
225
+ "Satisfaction équilibre pro/perso": 3,
226
+ "Note évaluation actuelle": 3,
227
+ "Augmentation salaire précédente": "18%"
228
+ }
229
+
230
+ with caplog.at_level(logging.WARNING):
231
+ response = client.post("/predict", json=payload)
232
+
233
+ assert response.status_code == 200 # l'API répond quand même
234
+ assert "Unknown value 'Logistique' for column 'departement'" in caplog.text
235
+