| | from fastapi.testclient import TestClient |
| | from app.main import app |
| | import logging |
| |
|
| | client = TestClient(app) |
| |
|
| | def test_root(): |
| | response = client.get("/") |
| | assert response.status_code == 200 |
| | assert response.json() == {"message":"Welcome to the FUTURISYS HR predictor API"} |
| |
|
| | def test_predict_valid(): |
| | payload = { |
| | "Genre": "M", |
| | "Statut Marital": "Marié(e)", |
| | "Département": "Consulting", |
| | "Poste": "Consultant", |
| | "Domaine d'étude": "Infra & Cloud", |
| | "Fréquence de déplacement": "Occasionnel", |
| | "Heures supplémentaires": "Non", |
| | "Âge": 32, |
| | "Revenu mensuel": 4883, |
| | "Nombre d'expériences précédentes": 1, |
| | "Années d'expérience totale": 10, |
| | "Années dans l'entreprise": 10, |
| | "Années dans le poste actuel": 4, |
| | "Nombre de formations suivies": 3, |
| | "Distance domicile-travail": 7, |
| | "Niveau d'éducation": 2, |
| | "Années depuis la dernière promotion": 1, |
| | "Années sous responsable actuel": 1, |
| | "Satisfaction environnement": 4, |
| | "Note évaluation précédente": 3, |
| | "Satisfaction nature du travail": 3, |
| | "Satisfaction équipe": 1, |
| | "Satisfaction équilibre pro/perso": 3, |
| | "Note évaluation actuelle": 3, |
| | "Augmentation salaire précédente": "18%" |
| | } |
| |
|
| | response = client.post("/predict", json=payload) |
| | data = response.json() |
| |
|
| | assert response.status_code == 200 |
| | assert data["statut_employe"] == "The staff has a LOW probability of resigning" |
| | assert data["probability_score"] == 0.28 |
| | assert data["model_threshold"] == 0.37 |
| |
|
| | |
| | factors = data["top_5_factors"] |
| | assert list(factors.keys()) == [ |
| | "revenu_mensuel", |
| | "annees_dans_l_entreprise", |
| | "statut_marital_Célibataire", |
| | "distance_domicile_travail", |
| | "overall_satisfaction" |
| | ] |
| |
|
| | |
| | assert factors["revenu_mensuel"]["interpretation"] == "Primary driver — decreases resignation risk" |
| | assert factors["annees_dans_l_entreprise"]["interpretation"] == "Strong factor — decreases resignation risk" |
| | assert factors["statut_marital_Célibataire"]["interpretation"] == "Moderate factor — decreases resignation risk" |
| | assert factors["distance_domicile_travail"]["interpretation"] == "Contributing factor — decreases resignation risk" |
| | assert factors["overall_satisfaction"]["interpretation"] == "Notable factor — decreases resignation risk" |
| |
|
| | |
| | assert factors["revenu_mensuel"]["feature_value"] == 4883.0 |
| | assert factors["annees_dans_l_entreprise"]["feature_value"] == 10.0 |
| | assert factors["statut_marital_Célibataire"]["feature_value"] == "encoded" |
| |
|
| | assert factors["distance_domicile_travail"]["feature_value"] == 7.0 |
| | assert factors["overall_satisfaction"]["feature_value"] == 2.75 |
| |
|
| |
|
| | class Test_Predict_422: |
| |
|
| | def test_predict_422_wrong_input(self): |
| | payload = { |
| | "Genre": "X", |
| | "Statut Marital": "Marié(e)", |
| | "Département": "Consulting", |
| | "Poste": "Consultant", |
| | "Domaine d'étude": "Infra & Cloud", |
| | "Fréquence de déplacement": "Occasionnel", |
| | "Heures supplémentaires": "Non", |
| | "Âge": 32, |
| | "Revenu mensuel": 4883, |
| | "Nombre d'expériences précédentes": 1, |
| | "Années d'expérience totale": 10, |
| | "Années dans l'entreprise": 10, |
| | "Années dans le poste actuel": 4, |
| | "Nombre de formations suivies": 3, |
| | "Distance domicile-travail": 7, |
| | "Niveau d'éducation": 2, |
| | "Années depuis la dernière promotion": 1, |
| | "Années sous responsable actuel": 1, |
| | "Satisfaction environnement": 4, |
| | "Note évaluation précédente": 3, |
| | "Satisfaction nature du travail": 3, |
| | "Satisfaction équipe": 1, |
| | "Satisfaction équilibre pro/perso": 3, |
| | "Note évaluation actuelle": 3, |
| | "Augmentation salaire précédente": "18%" |
| | } |
| | response = client.post("/predict", json=payload) |
| | assert response.status_code == 422 |
| |
|
| |
|
| | def test_predict_422_wrong_type_str(self): |
| | payload = { |
| | "Genre": "M", |
| | "Statut Marital": "Marié(e)", |
| | "Département": "Consulting", |
| | "Poste": "Consultant", |
| | "Domaine d'étude": "Infra & Cloud", |
| | "Fréquence de déplacement": "Occasionnel", |
| | "Heures supplémentaires": "Non", |
| | "Âge": "trente", |
| | "Revenu mensuel": 4883, |
| | "Nombre d'expériences précédentes": 1, |
| | "Années d'expérience totale": 10, |
| | "Années dans l'entreprise": 10, |
| | "Années dans le poste actuel": 4, |
| | "Nombre de formations suivies": 3, |
| | "Distance domicile-travail": 7, |
| | "Niveau d'éducation": 2, |
| | "Années depuis la dernière promotion": 1, |
| | "Années sous responsable actuel": 1, |
| | "Satisfaction environnement": 4, |
| | "Note évaluation précédente": 3, |
| | "Satisfaction nature du travail": 3, |
| | "Satisfaction équipe": 1, |
| | "Satisfaction équilibre pro/perso": 3, |
| | "Note évaluation actuelle": 3, |
| | "Augmentation salaire précédente": "18%" |
| | } |
| | response = client.post("/predict", json=payload) |
| | assert response.status_code == 422 |
| |
|
| | def test_predict_422_wrong_type_int(self): |
| | payload = { |
| | "Genre": "M", |
| | "Statut Marital": "Marié(e)", |
| | "Département": "Consulting", |
| | "Poste": "Consultant", |
| | "Domaine d'étude": "Infra & Cloud", |
| | "Fréquence de déplacement": "Occasionnel", |
| | "Heures supplémentaires": "Non", |
| | "Âge": 32, |
| | "Revenu mensuel": 4883.12, |
| | "Nombre d'expériences précédentes": 1, |
| | "Années d'expérience totale": 10, |
| | "Années dans l'entreprise": 10, |
| | "Années dans le poste actuel": 4, |
| | "Nombre de formations suivies": 3, |
| | "Distance domicile-travail": 7, |
| | "Niveau d'éducation": 2, |
| | "Années depuis la dernière promotion": 1, |
| | "Années sous responsable actuel": 1, |
| | "Satisfaction environnement": 4, |
| | "Note évaluation précédente": 3, |
| | "Satisfaction nature du travail": 3, |
| | "Satisfaction équipe": 1, |
| | "Satisfaction équilibre pro/perso": 3, |
| | "Note évaluation actuelle": 3, |
| | "Augmentation salaire précédente": "18%" |
| | } |
| | response = client.post("/predict", json=payload) |
| | assert response.status_code == 422 |
| |
|
| | def test_predict_422_incomplete_json(self): |
| | payload = { |
| | "Genre": "M", |
| | "Statut Marital": "Marié(e)", |
| | "Département": "Consulting", |
| | "Poste": "Consultant", |
| | "Domaine d'étude": "Infra & Cloud", |
| | "Fréquence de déplacement": "Occasionnel", |
| | "Heures supplémentaires": "Non", |
| | "Âge": 32, |
| | "Revenu mensuel": 4883, |
| | "Nombre d'expériences précédentes": 1, |
| | "Années d'expérience totale": 10, |
| | "Années dans l'entreprise": 10, |
| | "Années dans le poste actuel": 4, |
| | "Nombre de formations suivies": 3, |
| | "Niveau d'éducation": 2, |
| | "Années depuis la dernière promotion": 1, |
| | "Années sous responsable actuel": 1, |
| | "Satisfaction environnement": 4, |
| | "Note évaluation précédente": 3, |
| | "Satisfaction nature du travail": 3, |
| | "Satisfaction équipe": 1, |
| | "Satisfaction équilibre pro/perso": 3, |
| | "Note évaluation actuelle": 3, |
| | "Augmentation salaire précédente": "18%" |
| | } |
| | response = client.post("/predict", json=payload) |
| | assert response.status_code == 422 |
| |
|
| | def test_logging(caplog): |
| | payload = { |
| | "Genre": "M", |
| | "Statut Marital": "Marié(e)", |
| | "Département": "Logistique", |
| | "Poste": "Consultant", |
| | "Domaine d'étude": "Infra & Cloud", |
| | "Fréquence de déplacement": "Occasionnel", |
| | "Heures supplémentaires": "Non", |
| | "Âge": 32, |
| | "Revenu mensuel": 4883, |
| | "Nombre d'expériences précédentes": 1, |
| | "Années d'expérience totale": 10, |
| | "Années dans l'entreprise": 10, |
| | "Années dans le poste actuel": 4, |
| | "Nombre de formations suivies": 3, |
| | "Distance domicile-travail": 7, |
| | "Niveau d'éducation": 2, |
| | "Années depuis la dernière promotion": 1, |
| | "Années sous responsable actuel": 1, |
| | "Satisfaction environnement": 4, |
| | "Note évaluation précédente": 3, |
| | "Satisfaction nature du travail": 3, |
| | "Satisfaction équipe": 1, |
| | "Satisfaction équilibre pro/perso": 3, |
| | "Note évaluation actuelle": 3, |
| | "Augmentation salaire précédente": "18%" |
| | } |
| |
|
| | with caplog.at_level(logging.WARNING): |
| | response = client.post("/predict", json=payload) |
| |
|
| | assert response.status_code == 200 |
| | assert "Unknown value 'Logistique' for column 'departement'" in caplog.text |
| |
|
| | def test_predict_by_id_valid(): |
| |
|
| | response = client.get("/predict/1") |
| | data=response.json() |
| |
|
| | assert response.status_code==200 |
| | assert "statut_employe" in data |
| | assert "probability_score" in data |
| | assert "top_5_factors" in data |
| |
|
| | def test_predict_by_id_not_found(): |
| | response = client.get("/predict/99999") |
| | assert response.status_code == 404 |
| | assert response.json()["detail"] == "Employee ID not found in database" |
| |
|