"""Tests d'intégration : vrai modèle CRNN, vraies images — pas de mock. Plus lents que les tests unitaires (chargement du modèle ~30-90s sur CPU) : à lancer séparément avec `pytest tests/test_integration.py -v`, pas dans la boucle de développement rapide. """ import os import unittest import numpy as np from PIL import Image from app.recognizer import load_model, get_device, recognize_screen from app.postprocess import process as postprocess_results from app.quality import estimate_image_quality from app.rules import evaluate as evaluate_rules from app.preprocessing import detect_screen_region REPO_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) # Photo resserrée sur l'écran (pas besoin de détection d'écran) — voir # l'annotation ajoutée cette session : prix=10000, volume=14.28, prix_litre=700 SAMPLE_IMAGE = os.path.join( REPO_ROOT, "Images datasetdiversifié", "Images nettes", "20260622_121734_009.jpg" ) def _imread(path): img = Image.open(path).convert("RGB") arr = np.array(img) return arr[:, :, ::-1].copy() # RGB -> BGR pour rester cohérent avec cv2 @unittest.skipUnless(os.path.exists(SAMPLE_IMAGE), "image d'exemple absente de ce clone") class TestRealModelIntegration(unittest.TestCase): @classmethod def setUpClass(cls): cls.device = get_device() cls.model = load_model(device=cls.device) def test_recognizes_known_screen(self): img = _imread(SAMPLE_IMAGE) crop, (x, y, w, h) = detect_screen_region(img) img_to_process = crop if w < img.shape[1] * 0.95 else img recognized = recognize_screen(self.model, img_to_process, self.device) self.assertGreaterEqual(len(recognized), 1, "le CRNN n'a rien renvoyé") parsed = postprocess_results(recognized, fuel_price=700) quality = estimate_image_quality(img_to_process, ocr_results=recognized) gate = evaluate_rules(parsed, quality, fuel_price=700) print("\nrecognized:", recognized) print("parsed:", parsed) print("gate:", gate) # On ne verrouille pas une exactitude parfaite (précision du modèle # documentée dans docs/LIMITATIONS.md) : on vérifie que le pipeline # tourne bout-en-bout et renvoie une structure exploitable. self.assertIn(gate["success"], (True, False)) self.assertIsInstance(gate["confidence_score"], float) if __name__ == "__main__": unittest.main()