PROJETAVIS / test_app.py
Oxyb's picture
Upload 5 files
5dfd370 verified
Raw
History Blame Contribute Delete
5.85 kB
"""
Tests locaux pour Avis'IA Resto.
Execution :
python test_app.py
Ces tests n'appellent pas l'API Mistral. Ils verifient que l'application peut etre
importee, que le CSV exemple est conforme, que les graphiques sont generes et que
le mode local produit une reponse exploitable sans cle API.
"""
from __future__ import annotations
import unittest
from pathlib import Path
import pandas as pd
import plotly.graph_objects as go
import app
class AvisIARestoTestCase(unittest.TestCase):
def setUp(self) -> None:
self.csv_path = Path(__file__).resolve().parent / "avis_restaurant_exemple.csv"
self.raw = app.load_reviews(self.csv_path)
self.prepared = app.prepare_reviews(self.raw)
def test_csv_file_exists(self) -> None:
self.assertTrue(self.csv_path.exists(), "Le CSV exemple doit exister dans le projet.")
def test_required_columns_are_present(self) -> None:
self.assertTrue(app.REQUIRED_COLUMNS.issubset(set(self.raw.columns)))
def test_example_dataset_shape(self) -> None:
self.assertEqual(len(self.prepared), 36)
self.assertEqual(self.prepared["restaurant"].nunique(), 3)
def test_sentiment_classification(self) -> None:
sentiments = set(self.prepared["sentiment"].unique())
self.assertTrue({"Positif", "Mitige", "Negatif"}.issubset(sentiments))
self.assertEqual(app.classify_sentiment(5), "Positif")
self.assertEqual(app.classify_sentiment(1), "Negatif")
self.assertEqual(app.classify_sentiment(3), "Mitige")
def test_theme_detection(self) -> None:
themes = app.detect_themes("Service lent, plat froid, addition trop chere.")
self.assertIn("Service", themes)
self.assertIn("Cuisine", themes)
self.assertIn("Prix", themes)
def test_fallback_response_without_api_key(self) -> None:
response = app.generate_review_response(
"Service lent et plat froid. Tres decu.",
1,
"Le Normand - Caen",
"Google",
use_ai=False,
)
self.assertGreater(len(response), 80)
self.assertIn("desoles", app.strip_accents(response))
self.assertIn("Le Normand - Caen", response)
def test_five_plotly_figures_are_created(self) -> None:
figures = app.build_figures(self.prepared)
self.assertEqual(len(figures), 5)
self.assertTrue(all(isinstance(fig, go.Figure) for fig in figures))
def test_dashboard_contract(self) -> None:
outputs = app.build_dashboard(self.csv_path, use_ai=False)
self.assertEqual(len(outputs), 7)
self.assertIsInstance(outputs[0], str)
self.assertTrue(all(isinstance(fig, go.Figure) for fig in outputs[1:6]))
self.assertIn("Bilan", outputs[6])
def test_quality_checks_are_all_green(self) -> None:
results = app.run_quality_checks()
self.assertEqual(len(results), 7)
failed = [check.name for check in results if not check.ok]
self.assertEqual(failed, [])
def test_gradio_demo_is_defined(self) -> None:
self.assertTrue(hasattr(app, "demo"))
def test_project_files_exist(self) -> None:
expected_files = [
"README.md",
"requirements.txt",
"avis_restaurant_exemple.csv",
"app.py",
"test_app.py",
]
root = Path(__file__).resolve().parent
missing = [name for name in expected_files if not (root / name).exists()]
self.assertEqual(missing, [])
def test_readme_huggingface_metadata(self) -> None:
readme = (Path(__file__).resolve().parent / "README.md").read_text(encoding="utf-8")
self.assertIn("sdk: gradio", readme)
self.assertIn("python_version: 3.11", readme)
self.assertIn("sdk_version: 5.49.1", readme)
self.assertIn("app_file: app.py", readme)
self.assertIn("MISTRAL_API_KEY", readme)
def test_readme_pins_huggingface_runtime(self) -> None:
readme = (Path(__file__).resolve().parent / "README.md").read_text(encoding="utf-8")
self.assertIn("python_version: 3.11", readme)
self.assertIn("sdk_version: 5.49.1", readme)
self.assertNotIn("sdk_version: 5.0.0", readme)
def test_requirements_include_runtime_dependencies(self) -> None:
requirements = (Path(__file__).resolve().parent / "requirements.txt").read_text(encoding="utf-8")
for dependency in ["gradio", "huggingface_hub", "mistralai", "pandas", "plotly", "audioop-lts"]:
self.assertIn(dependency, requirements)
def test_requirements_pin_known_compatible_versions(self) -> None:
requirements = (Path(__file__).resolve().parent / "requirements.txt").read_text(encoding="utf-8")
expected_pins = [
"gradio==5.49.1",
"huggingface_hub==0.35.3",
"mistralai==2.4.9",
"pandas==2.2.3",
"plotly==6.5.2",
"audioop-lts==0.2.2",
]
for pin in expected_pins:
self.assertIn(pin, requirements)
self.assertNotIn("gradio==5.0.0", requirements)
self.assertNotIn("gradio>=", requirements)
def test_mistral_import_supports_sdk_v1_and_v2_paths(self) -> None:
source = (Path(__file__).resolve().parent / "app.py").read_text(encoding="utf-8")
self.assertIn("from mistralai.client import Mistral", source)
self.assertIn("from mistralai import Mistral", source)
def test_runtime_fix_is_documented(self) -> None:
readme = (Path(__file__).resolve().parent / "README.md").read_text(encoding="utf-8")
self.assertIn("Correctifs de déploiement verrouillés", readme)
self.assertIn("huggingface_hub", readme)
self.assertIn("audioop-lts", readme)
if __name__ == "__main__":
unittest.main(verbosity=2)