Évaluation de la Tête de Défaut et Tests de Fumée
Le test de fumée de la tête de défaut valide que le pipeline de détection des défauts structurels de TarmacView — backbone DINOv3 + tête MLP à 5 étiquettes pour...
Un test de fumée est une vérification rapide de bout en bout permettant de s’assurer qu’une chaîne de traitement logicielle s’exécute sans planter sur des données représentatives, produisant les résultats attendus. Les scripts de test smoke_*.py de TarmacView valident chaque phase de la chaîne de traitement (analyse, évaluation, fissuration, défaut, relevé, visualisation). Couvre la conception des tests de fumée, ce que les tests de fumée vérifient par rapport aux tests complets, et leur rôle dans l’IC/CD.
{{
Un test de fumée est une procédure de vérification automatisée légère qui exécute une chaîne de traitement logicielle de bout en bout sur des données d’entrée représentatives ou minimales afin de confirmer que la chaîne s’exécute jusqu’à son terme sans planter et produit des fichiers de sortie avec la structure attendue. Le test effectue une évaluation binaire réussite/échec — si une étape lève une exception non gérée, ne produit aucune sortie ou génère une sortie dépourvue de colonnes critiques, le test échoue et le build est immédiatement rejeté.
Le terme provient du génie matériel où la métaphore est littérale. Lorsque les ingénieurs allumaient pour la première fois un circuit nouvellement assemblé, ils observaient si de la fumée s’échappait des composants grillés. Si de la fumée apparaissait, la carte présentait une défaillance catastrophique et tout test ultérieur s’arrêtait. La carte défectueuse était soit réparée, soit jetée avant que quiconque n’investisse du temps dans des diagnostics détaillés. Le test de fumée logiciel applique le même principe : exécuter le code et vérifier la présence de « fumée » — plantages, exceptions non capturées, sorties manquantes — avant d’investir du temps dans une validation détaillée.
Dans le contexte des chaînes de traitement logicielles d’inspection, un test de fumée valide que chaque étape de la chaîne de traitement peut s’exécuter sur des données représentatives. Pour TarmacView, cela signifie alimenter une petite image de piste ou de chaussée à travers l’ensemble de la chaîne — de l’acquisition d’image à la détection de fissures, la classification des défauts, l’évaluation de surface, le relevé cartographique et la visualisation — et vérifier que chaque étape produit une sortie sans erreur. Cela est particulièrement critique pour les logiciels aéronautiques où les défaillances de la chaîne de traitement peuvent retarder les évaluations d’infrastructures aéroportuaires qui ont un impact direct sur la sécurité des vols.
Le terme test de vérification de build (BVT) est souvent utilisé de manière interchangeable avec test de fumée, Microsoft étant l’adopteur le plus connu de cette terminologie. Les processus de développement internes de Microsoft — en particulier pour Windows et Office — ont institutionnalisé le test de fumée comme une barrière qualité obligatoire dans les années 1990. Le livre Code Complete de Steve McConnell identifie le « build quotidien et test de fumée » comme la meilleure pratique industrielle la plus élevée pour la maturité de l’intégration continue. Le cadre SRE (Site Reliability Engineering) de Google positionne les tests de fumée sous les « tests système » — le type le plus simple utilisé spécifiquement pour court-circuiter les pipelines de test coûteux.
L’objectif du test de fumée est triple :
Les tests de fumée occupent le premier niveau de la pyramide de test, s’exécutant avant les tests unitaires, les tests d’intégration et les suites de régression de bout en bout. Ils sont conçus pour être réalisés en moins de 60 secondes pour une chaîne de traitement d’inspection typique, ce qui les rend adaptés à une exécution sur chaque commit de code dans l’IC/CD. Dans les organisations logicielles à maturité élevée, les tests de fumée s’exécutent sur chaque push vers n’importe quelle branche, pas seulement la branche principale, offrant ainsi la détection la plus précoce possible des échecs d’intégration.
Le concept de test de fumée précède le génie logiciel de plusieurs décennies. La première utilisation documentée de l’expression apparaît dans les tests de plomberie et de poêles au XIXe siècle. Les fabricants de poêles allumaient un feu à l’intérieur d’un poêle nouvellement assemblé, fermaient tous les registres et observaient d’où la fumée s’échappait — si la fumée sortait par des endroits non prévus, le poêle présentait des défauts de construction. Cette même logique « appliquer une puissance minimale et observer ce qui casse » a migré vers les tests électroniques au milieu du XXe siècle, puis enfin vers le génie logiciel dans les années 1980 et 1990.
Microsoft est largement crédité d’avoir introduit le test de fumée dans la pratique courante du génie logiciel. À la fin des années 1990, les divisions Windows et Office de Microsoft ont adopté ce qu’elles appelaient le Build Verification Testing (BVT) comme processus de barrière obligatoire. Chaque build nocturne devait passer une suite de BVT avant d’être diffusé aux testeurs internes. Si le BVT échouait, le build était « cassé » et le développeur responsable était contacté, quel que soit le moment de la journée. Cette culture de responsabilité immédiate pour la qualité du build est devenue fondamentale pour la culture d’ingénierie de Microsoft et a été largement documentée dans la documentation MSDN et les livres de Microsoft Press.
La taxonomie de Crosslake Technologies (dérivée directement de la pratique de Microsoft) établit une distinction entre les tests de fumée et les BVT. Les tests de fumée sont décrits comme « superficiels — garantir que les fonctionnalités de base fonctionnent », s’exécutant en minutes et concentrés sur les fonctions critiques. Les BVT sont décrits comme « un sur-ensemble des tests de fumée » qui sont « légèrement plus approfondis » mais s’exécutent toujours en minutes, pas en heures. Les deux remplissent la même fonction de barrière, mais les BVT incluent un ensemble plus large de scénarios de chemin critique.
Google a adopté le test de fumée à travers ses pratiques SRE (Site Reliability Engineering). Le Google Testing Blog considère le test de fumée comme une pratique connue et supposée, se concentrant davantage sur la façon de pondérer les résultats des tests de fumée parallèlement à d’autres types de tests. La culture d’ingénierie de Google met l’accent sur la précision des tests unitaires et la notation de confiance pondérée pour les vérifications larges de type test de fumée, considérant les tests de fumée comme complémentaires plutôt que comme remplacement des tests unitaires rigoureux.
Dans le domaine des logiciels aéronautiques, le test de fumée correspond à la phase de Test d’Intégration Matériel/Logiciel décrite dans la section DO-178C 6.4.3. Bien que la DO-178C ne mentionne pas explicitement le « test de fumée », la norme exige que le système intégré « démarre et que les fonctions de base fonctionnent » avant de procéder à des tests plus approfondis. Cela est fonctionnellement identique à un test de fumée. Pour les logiciels d’inspection aéroportuaire fonctionnant sous l’Annexe 14 de l’OACI — qui régit la conception et l’exploitation des aérodromes — les tests de fumée fournissent l’assurance de fiabilité logicielle nécessaire pour soutenir les évaluations de l’indice de condition des chaussées (PCI) qui alimentent les systèmes de gestion de la sécurité aéroportuaire.
Comprendre où se situent les tests de fumée dans la taxonomie plus large des tests est essentiel pour élaborer une stratégie d’assurance qualité équilibrée. Les quatre principaux niveaux de test jouent des rôles complémentaires mais distincts, ciblant différents modes de défaillance à différentes étapes du cycle de vie de la chaîne de traitement.
| Dimension | Test de Fumée | Test Unitaire | Test d’Intégration | Test Système |
|---|---|---|---|---|
| Périmètre | Chaîne complète de bout en bout | Fonction ou méthode unique | Deux composants ou plus en interaction | Système complet dans un environnement de type production |
| Données | Échantillon minimal représentatif | Entrées simulées ou factices | Données réelles mais limitées | Données à l’échelle de production |
| Temps d’exécution | Secondes à moins d'1 minute | Millisecondes | Minutes à heures | Heures à jours |
| Ce qu’il détecte | Plantages, sorties manquantes, échecs d’import | Erreurs logiques dans une fonction | Décalages d’interface, erreurs de protocole | Exactitude de bout en bout, performance |
| Dépendances | Réelles (non simulées) | Simulées ou factices | Sous-ensemble réel | Pile de production complète |
| Fréquence | Chaque commit dans l’IC | Chaque commit dans l’IC | Par build ou nuit | Par version |
| Impact d’un échec | Arrête la chaîne de traitement | Isolé à une seule fonction | Bloque la branche d’intégration | Bloque la version |
Les tests unitaires valident que des fonctions individuelles produisent des sorties correctes pour des entrées données. Ils simulent toutes les dépendances externes — bases de données, systèmes de fichiers, services réseau, accélérateurs matériels. Un test unitaire pour une fonction de détection de fissures pourrait vérifier qu’elle identifie correctement des fissures dans un tableau synthétique de 10x10 pixels avec des positions de fissures connues. Les tests unitaires sont étroits et profonds : ils vérifient la logique d’une seule fonction de manière exhaustive, couvrant les cas limites, les conditions aux limites et les chemins d’erreur. Cependant, les tests unitaires ne peuvent pas détecter les échecs d’intégration car les dépendances sont simulées — le test n’exerce jamais la chaîne d’import réelle, le chargement de la configuration ou le flux de données inter-modules.
Les tests d’intégration valident que deux composants ou plus fonctionnent correctement ensemble. Ils utilisent des instances de dépendances réelles mais contrôlées. Un test d’intégration pour TarmacView pourrait vérifier que l’étape d’acquisition d’image transmet correctement les données au modèle de détection de fissures dans le format tensoriel attendu avec le bon ordre des canaux et les bons paramètres de normalisation. Les tests d’intégration sont plus étroits que les tests de fumée dans le périmètre de la chaîne mais plus profonds dans la validation des interactions : ils se concentrent sur des limites de composants spécifiques plutôt que sur la chaîne complète.
Les tests de fumée valident que la chaîne de traitement entière s’exécute sans planter. Ils exécutent chaque étape en séquence avec des données réelles, bien que petites. Les tests de fumée sont larges et superficiels — ils couvrent la chaîne complète mais vérifient seulement que l’exécution se termine et que les sorties existent, pas que les résultats numériques sont corrects. Un calcul de longueur de fissure qui retourne 47,2 pixels au lieu des 42,1 pixels corrects réussit un test de fumée tant que la colonne length_px existe et contient une valeur à virgule flottante.
Les tests système (également appelés tests de bout en bout) exécutent le système complet avec des données à l’échelle de production dans un environnement de type production. Ils vérifient que le système répond à ses exigences fonctionnelles et non fonctionnelles, y compris l’exactitude, la performance et la fiabilité. Les tests système sont les plus coûteux à exécuter et à maintenir, et ils ne s’exécutent que sur les candidates à la version, pas sur chaque commit.
Dans la pyramide de test, les tests de fumée forment la couche de base — ils s’exécutent en premier, le plus rapidement et le plus fréquemment. Si un test de fumée échoue, les tests unitaires et d’intégration sur ce build sont généralement ignorés ou marqués comme préventivement non fiables. Cela économise des ressources de calcul et du temps de développement en échouant rapidement lorsque l’exécution fondamentale de la chaîne de traitement est cassée.
La conception efficace d’un test de fumée repose sur le concept d’entrée minimale représentative — le plus petit ensemble de données qui exerce chaque étape de la chaîne de traitement sans déclencher de cas limites dépendants des données. C’est la décision de conception la plus importante dans la construction d’une suite de tests de fumée.
Principe 1 : Minimal mais non trivial. L’entrée doit être suffisamment grande pour traverser chaque étape de la chaîne sans emprunter des chemins de code qui contournent la logique de traitement réelle. Une image d’un seul pixel est triviale — elle traverserait le chargement d’image, mais les algorithmes de traitement emprunteraient des chemins de code dégénérés qui ne s’exécutent jamais sur des données réelles. Une image de 256x256 pixels d’une véritable chaussée de piste est minimale mais représentative : elle exerce les algorithmes de traitement par tuiles, les routines de normalisation des couleurs et les chemins d’inférence du modèle sans nécessiter un temps de calcul excessif.
Principe 2 : Représentative des données de production. L’entrée doit avoir le même format de fichier, la même profondeur de couleur, la même structure de métadonnées et les mêmes propriétés statistiques que les données de production. Si les données de production proviennent d’un appareil photo aérien Phase One iXM-RS150F capturant des fichiers TIFF 16 bits avec des métadonnées EXIF GPS intégrées, l’entrée du test de fumée doit correspondre à ces caractéristiques. L’utilisation de données synthétiques qui diffèrent des données de production contredit l’objectif du test de fumée car les défaillances de la chaîne de traitement proviennent souvent de propriétés inattendues des données réelles — balises EXIF manquantes, profils colorimétriques inattendus, chaînes de projection GeoTIFF non standard.
Principe 3 : Fixe et versionnée. Les entrées des tests de fumée doivent être placées sous contrôle de version avec le code sous forme de fichiers binaires ou gérées via Git LFS (Large File Storage). Elles ne doivent jamais changer sans révision explicite via des pull requests. Une entrée changeante rend impossible la distinction entre les régressions de la chaîne de traitement et les modifications des données de test — un test de fumée qui réussit aujourd’hui et échoue demain pourrait indiquer soit une régression de code, soit une entrée de test modifiée. Le contrôle de version des entrées élimine cette ambiguïté.
Principe 4 : Rapide à traiter. Le temps d’exécution total de la suite de tests de fumée ne doit pas dépasser 60 secondes pour une chaîne de traitement typique et 3 minutes pour les chaînes complexes à plusieurs étapes comme les logiciels d’inspection. Cette contrainte détermine la taille des entrées. Pour les chaînes de traitement basées sur l’image, une seule image de 512x512 pixels est généralement suffisante. Pour les chaînes vidéo, une seule image ou un clip de 2 secondes. Pour les chaînes LiDAR, un segment de ligne de vol unique couvrant 100 mètres de chaussée.
Principe 5 : Contient des caractéristiques connues. L’entrée du test doit contenir les caractéristiques que chaque étape de la chaîne est conçue pour détecter. Un test de fumée pour la détection de fissures est inutile si l’image d’entrée ne contient aucune fissure — la chaîne pourrait ignorer silencieusement la détection de fissures et quand même réussir. Les entrées de test doivent être sélectionnées pour contenir au moins une instance de chaque caractéristique détectable avec une vérité terrain connue pouvant être référencée lors de l’analyse des défaillances.
Pour la chaîne de traitement d’inspection de TarmacView, l’entrée du test de fumée est une seule bande orthophotographique RVB de 1024x768 pixels d’une chaussée aéroportuaire capturée à une distance au sol (GSD) de 1 mm. L’image contient au moins une fissure visible, un défaut de surface (par exemple désagrégation ou écaillage) et des marquages de chaussée clairs. Cette image unique :
Le temps de traitement attendu pour cette image unique à travers la chaîne complète est inférieur à 30 secondes sur le matériel CI, laissant une marge pour les autres tests de fumée de la suite. L’image de test est stockée dans le dépôt sous tests/data/smoke/ et est versionnée via Git LFS.
La chaîne de traitement d’inspection de TarmacView est validée par une suite de scripts de test de fumée dédiés, chacun couvrant une phase spécifique de la chaîne. Ces scripts se trouvent dans le répertoire scripts/ suivant la convention de nommage smoke_<phase>.py. Chaque script est conçu pour pouvoir être exécuté à la fois indépendamment (pour le débogage en développement) et dans le cadre de la suite CI (pour la barrière automatisée).
{{
Ce script valide la phase d’analyse d’image. Il lit une seule bande orthophotographique représentative, exécute la chaîne d’analyse complète via le module de traitement d’image et vérifie :
Le script accepte un argument --input pointant vers l’image de test et un argument --output-dir spécifiant où la chaîne doit écrire les résultats. Si la chaîne plante pendant une étape de traitement, l’exception est capturée et le test retourne un rapport d’échec structuré.
Ce script valide la phase d’évaluation de l’état des chaussées. Il prend la sortie de la phase d’analyse (ou un fichier d’analyse pré-généré stocké dans le contrôle de version), exécute l’algorithme d’évaluation de l’état et vérifie :
pavement_id condition_index severity extent date_assessedL’algorithme d’évaluation de TarmacView suit la norme ASTM D5340 pour le calcul du PCI aéroportuaire, adapté pour l’inspection automatisée basée sur l’image. Le test de fumée ne vérifie pas que les valeurs PCI sont numériquement correctes — il vérifie seulement que le calcul s’exécute, produit des résultats au format attendu et les écrit sur le disque.
Ce script valide la phase de détection de fissures. Il exécute le modèle de détection de fissures sur une image de test connue pour contenir des fissures et vérifie :
crack_id length_px width_px orientation confidence classificationLe modèle de détection de fissures utilisé par TarmacView est une architecture U-Net avec un backbone ResNet-50 entraîné sur des images de chaussée étiquetées provenant de plusieurs aéroports. L’image d’entrée du test de fumée a été spécifiquement sélectionnée dans l’ensemble de validation, ce qui signifie qu’elle contient des fissures que le modèle a vues pendant l’entraînement mais pas pendant l’évaluation sur l’ensemble de test.
Ce script valide la phase de classification des défauts de surface. Il exécute le classifieur de défauts sur une image de test contenant des défauts connus (désagrégation, écaillage, réparation, altération météorologique) et vérifie :
defect_id defect_type area_px severity confidence timestampLe classifieur de défauts utilise une architecture Mask R-CNN qui produit des masques de segmentation d’instance pour chaque défaut détecté. Le test de fumée vérifie que le masque de sortie a les bonnes dimensions et que le fichier d’inventaire contient les colonnes de schéma attendues. Il ne vérifie pas que les classifications des défauts sont correctes — cela nécessite une suite de validation séparée avec des données de vérité terrain étiquetées.
Ce script valide la phase de relevé cartographique. Il prend les données de fissures et de défauts produites par les étapes en amont, exécute le module de relevé cartographique géospatial et vérifie :
Le module de relevé cartographique utilise les métadonnées de géoréférencement de l’orthophoto pour effectuer une transformation projective des coordonnées pixels vers les coordonnées géographiques. Le test de fumée vérifie que cette transformation produit des coordonnées géographiques valides dans la boîte englobante attendue pour l’image de test. Une photo de l’emplacement de l’image de test prise à l’aéroport fournit une référence croisée visuelle pour l’analyse des défaillances.
Ce script valide la phase de visualisation et de tête de segmentation — la dernière étape de la chaîne qui produit une sortie lisible par l’homme. Il prend les sorties traitées de la chaîne, exécute le moteur de rendu de visualisation et vérifie :
La phase de visualisation est souvent le premier endroit où les erreurs cumulatives de la chaîne deviennent visibles. Une étape de détection de fissures qui produit un masque dans le mauvais espace de coordonnées générera une visualisation où les superpositions de fissures sont décalées par rapport à l’image de base. Le test de fumée détecte cela indirectement si le rendu plante, mais c’est le test de régression d’inspection visuelle — pas le test de fumée — qui détecte les régressions de qualité visuelle.
Ces tests de fumée sont conçus pour s’exécuter en séquence mais peuvent également s’exécuter indépendamment si les sorties en amont sont mises en cache. La suite complète se termine en moins de 3 minutes sur le matériel CI. Chaque test produit un rapport JSON structuré avec les champs suivants :
| Champ | Type | Description |
|---|---|---|
test_name | string | Nom unique du test (par ex. « smoke_crack ») |
passed | boolean | Indique si le test a réussi (true) ou échoué (false) |
duration_ms | integer | Temps d’exécution réel en millisecondes |
output_files | array of strings | Chemins vers les fichiers de sortie créés pendant le test |
failure_reason | string or null | Raison de l’échec lisible par un humain si le test a échoué |
input_path | string | Chemin vers les données d’entrée utilisées pour le test |
pipeline_version | string | SHA du commit Git ou étiquette de version du code de la chaîne de traitement |
L’exécuteur de test agrège les rapports JSON individuels en un résumé de suite qui est affiché sur le tableau de bord CI et éventuellement envoyé par Slack ou email pour notification en temps réel.
Les tests de fumée sont délibérément limités dans ce qu’ils affirment. Ils vérifient trois catégories de conditions et rien de plus. Cette portée restreinte est intentionnelle — elle maintient les tests rapides, déterministes et faciles à maintenir.
L’affirmation la plus fondamentale : le code s’exécute-t-il sans lever d’exception non gérée ? Cela couvre :
Une chaîne qui plante au démarrage ou en cours d’exécution échoue immédiatement au test de fumée. La raison de l’échec est capturée à partir de la trace de l’exception, fournissant aux développeurs un pointeur direct vers l’emplacement du code de la défaillance.
Après l’exécution, le test de fumée vérifie que les fichiers de sortie existent aux chemins attendus. Cela couvre :
Une chaîne qui prétend se terminer mais ne produit aucun fichier de sortie échoue au test de fumée. Cela détecte les échecs silencieux où la chaîne se termine proprement mais saute des opérations d’écriture critiques en raison de chemins de sortie mal configurés ou d’une logique conditionnelle qui s’évalue à faux de manière inattendue.
Pour toute sortie tabulaire (CSV, Parquet, collection d’entités GeoJSON), le test de fumée vérifie que les colonnes attendues existent par leur nom. Il s’agit d’un contrôle d’intégrité structurelle — le schéma des colonnes doit correspondre à ce que les consommateurs en aval attendent.
| Type de Sortie | Colonnes Requises |
|---|---|
| Inventaire des fissures | crack_id length_px width_px orientation confidence classification |
| Inventaire des défauts | defect_id defect_type area_px severity confidence timestamp |
| Évaluation de l’état | pavement_id condition_index severity extent date_assessed method |
| Relevé cartographique | feature_id latitude longitude geometry_type crs_epsg accuracy_m |
Le test utilise une vérification d’existence de colonnes (pas un contrôle de type, pas un contrôle de plage de valeurs). C’est intentionnel — l’existence des colonnes est la garantie d’intégrité structurelle minimale. Les contrôles de type et de plage appartiennent aux tests d’intégration et de validation où le coût de leur exécution est justifié par la profondeur des informations qu’ils fournissent.
La quatrième catégorie de vérification effectuée par les tests de fumée — souvent négligée — est la compatibilité des formats de données. Le test de fumée vérifie que les fichiers de sortie peuvent être relus par les consommateurs en aval attendus. Pour TarmacView, cela signifie :
Cela détecte les incompatibilités de version de format — par exemple si la bibliothèque Parquet est mise à niveau et modifie son encodage, ou si la spécification GeoJSON évolue et que la sortie de la chaîne n’est plus conforme.
Il est tout aussi important de comprendre ce que les tests de fumée excluent délibérément. Une méconnaissance de cela conduit à une confiance erronée dans l’exactitude de la chaîne de traitement — un test de fumée réussi ne signifie pas que la chaîne est correcte, seulement qu’elle n’est pas catastrophiquement cassée.
Les tests de fumée ne vérifient pas que les valeurs calculées sont correctes. Un calcul de longueur de fissure qui retourne 47,2 pixels au lieu des 42,1 pixels corrects réussit un test de fumée tant que la colonne length_px existe et contient un nombre à virgule flottante. La validation de l’exactitude appartient aux tests unitaires où la valeur correcte est codée en dur, et aux tests d’intégration où les résultats sont comparés aux mesures manuelles effectuées par des inspecteurs certifiés.
Pour les chaînes de traitement d’inspection aéronautique fonctionnant sous l’Annexe 14 de l’OACI, l’exactitude numérique est critique car les évaluations de l’état des chaussées informent directement la priorisation de la maintenance et l’allocation budgétaire. Une chaîne qui réussit les tests de fumée mais produit des scores PCI inexacts pourrait conduire à des décisions de maintenance incorrectes. C’est pourquoi les tests de fumée ne sont que la première barrière — ils doivent être suivis de tests de validation axés sur l’exactitude.
Les tests de fumée utilisent des entrées représentatives mais non adverses. Ils ne testent pas :
La gestion des cas limites est validée par des tests de cas limites dédiés qui ciblent spécifiquement chaque condition aux limites. Ces tests sont plus coûteux à exécuter et sont généralement effectués de nuit plutôt qu’à chaque commit.
Les tests de fumée vérifient que la chaîne de traitement se termine, pas qu’elle se termine dans un budget de performance. Une chaîne qui prend 10 secondes par image dans les tests de fumée mais qui est censée traiter 100 images par seconde en production réussit les tests de fumée sans problème. La validation des performances nécessite des tests de benchmark dédiés avec des données à l’échelle de production et des assertions temporelles.
Pour les chaînes de traitement d’inspection aéroportuaire, la performance est critique car les aéroports traitent des centaines d’images de chaussée par relevé. Une régression de performance d’un facteur 10 pourrait encore réussir les tests de fumée sur une seule image, mais rendrait les relevés complets irréalisables. Les benchmarks de performance avec des seuils temporels sont l’outil approprié pour détecter de telles régressions.
Les tests de fumée ne couvrent que le chemin d’exécution principal. Les fonctionnalités ne faisant pas partie du chemin critique — formats de sortie alternatifs, journalisation optionnelle, télémétrie, pistes d’audit, fonctionnalités d’exportation expérimentales — ne sont pas couvertes. Les régressions dans ces domaines doivent être détectées par des suites de tests de régression qui ciblent spécifiquement les fonctionnalités non critiques.
Les tests de fumée ne vérifient pas que les valeurs des données sont cohérentes en interne. Par exemple, un test de fumée vérifie que la colonne crack_id existe, mais ne vérifie pas que toutes les valeurs de crack_id sont uniques, non nulles ou dans des plages attendues. La validation de la qualité des données nécessite des tests de qualité des données dédiés utilisant des frameworks comme Great Expectations ou Pandera qui définissent des contrats de données et valident les ensembles de données par rapport à ceux-ci.
Les tests de fumée apportent une valeur maximale lorsqu’ils sont intégrés dans le pipeline d’intégration continue et de déploiement continu (IC/CD). Leur placement dans le flux de travail du pipeline détermine leur efficacité en tant que barrière qualité.
{{
Dans un flux de travail IC/CD typique, les tests de fumée s’exécutent à l’étape de vérification du build immédiatement après la compilation et avant toute autre suite de tests :
Commit de code → Build → Lint → Tests Unitaires → Tests de Fumée → Tests d'Intégration → Tests de Validation → Déploiement
L’ordre exact dépend de la stratégie de test du projet. Certaines organisations exécutent les tests unitaires avant les tests de fumée, arguant que les tests unitaires sont plus rapides et détectent les erreurs logiques. D’autres exécutent les tests de fumée en premier, arguant qu’une chaîne qui plante sur une exécution de base doit être rejetée sans perdre de temps sur les tests unitaires. Le pipeline TarmacView exécute les tests unitaires et les tests de fumée en parallèle après un build réussi, car ils couvrent des modes de défaillance indépendants et n’ont pas d’interdépendances.
Ce placement garantit que si le build produit une chaîne qui plante sur une exécution de base, aucune infrastructure de test supplémentaire n’est consommée. La boucle de rétroaction se mesure en minutes plutôt qu’en heures. Un développeur qui pousse un commit cassant la chaîne d’import reçoit une notification d’échec CI en 2 à 3 minutes plutôt que d’attendre 4 heures que la suite de tests d’intégration échoue.
Le pipeline IC/CD utilise une barrière stricte : si un test de fumée échoue, le pipeline s’arrête et ne passe pas aux étapes suivantes. Le build est marqué comme échoué et les développeurs sont notifiés avec le rapport d’échec du test de fumée. Aucune dérogation manuelle n’est autorisée dans la configuration par défaut — une suite de tests de fumée réussie est une condition nécessaire pour le déploiement.
Cette logique de barrière empêche les scénarios suivants :
La barrière est implémentée dans la configuration de la plateforme CI. Pour CircleCI, cela signifie configurer les dépendances du workflow de sorte que le travail smoke-test s’exécute avant integration-test et deploy. Pour GitHub Actions, cela signifie utiliser le mot-clé needs: pour imposer l’ordre des travaux.
Les tests de fumée au sein de la suite peuvent s’exécuter en parallèle s’ils testent des étapes indépendantes de la chaîne. La suite de tests de fumée de TarmacView utilise le parallélisme lorsque c’est possible :
smoke_crack.py et smoke_defect.py n’ont pas d’interdépendances et peuvent s’exécuter simultanément, réduisant le temps total de la suite de 40%smoke_analyze.py doit se terminer avant smoke_assess.py car l’évaluation consomme la sortie de l’analysesmoke_survey.py dépend des sorties des fissures et des défautssmoke_seg_head.py dépend de toutes les sorties en amontLa stratégie d’exécution parallèle est configurée dans le YAML du pipeline CI en utilisant le parallélisme au niveau des travaux. Chaque travail s’exécute dans son propre conteneur avec des dépendances isolées, empêchant la contention de ressources.
L’intégration IC/CD inclut des rapports automatisés avec plusieurs canaux :
# .circleci/config.yml
version: 2.1
jobs:
smoke-test:
docker:
- image: tarmacview/pipeline:ci
parallelism: 3
steps:
- checkout
- run: pip install -r requirements.txt
- run: python scripts/smoke_analyze.py --input tests/data/smoke_image.tif --output-dir /tmp/smoke-output
- run:
name: "Tests de fumée parallèles"
command: |
python scripts/smoke_crack.py --input tests/data/smoke_image.tif --output-dir /tmp/smoke-output &
python scripts/smoke_defect.py --input tests/data/smoke_image.tif --output-dir /tmp/smoke-output &
wait
- run: python scripts/smoke_assess.py --input /tmp/smoke-output/cracks.parquet --output-dir /tmp/smoke-output
- run: python scripts/smoke_survey.py --input /tmp/smoke-output --output-dir /tmp/smoke-output
- run: python scripts/smoke_seg_head.py --input /tmp/smoke-output --output-dir /tmp/smoke-output
- store_artifacts:
path: /tmp/smoke-output
workflows:
version: 2
build-and-test:
jobs:
- build
- unit-tests:
requires: [build]
- smoke-test:
requires: [build]
- integration-tests:
requires: [smoke-test]
- deploy:
requires: [integration-tests]
Écrire des tests de fumée efficaces demande de la discipline. Le test doit être rapide, fiable et concentré uniquement sur ce qu’il est conçu pour détecter. Chaque test de fumée suit le même schéma fondamental : exécuter l’étape de la chaîne, vérifier l’existence de la sortie, valider l’exactitude minimale du schéma, rapporter le résultat réussi/échec en JSON structuré.
# smoke_crack.py — simplified pattern
import sys
import json
import time
from pathlib import Path
import pandas as pd
def test_smoke_crack(input_path: str, output_dir: str) -> dict:
result = {
"test_name": "smoke_crack",
"passed": False,
"duration_ms": 0,
"output_files": [],
"failure_reason": None,
"input_path": input_path,
"pipeline_version": "unknown"
}
start = time.time()
try:
# Step 1: Get pipeline version
from tarmacview import __version__
result["pipeline_version"] = __version__
# Step 2: Run the pipeline stage with real imports
from tarmacview.pipeline.crack import detect_cracks
output = detect_cracks(input_path, output_dir)
# Step 3: Verify output file exists and is non-empty
output_path = Path(output["crack_mask_path"])
assert output_path.exists(), f"Output file not found: {output_path}"
assert output_path.stat().st_size > 0, f"Output file is empty: {output_path}"
result["output_files"].append(str(output_path))
# Step 4: Verify key columns in tabular output
if output.get("crack_inventory_path"):
inv_path = Path(output["crack_inventory_path"])
assert inv_path.exists(), f"Inventory file not found: {inv_path}"
df = pd.read_parquet(inv_path)
required_columns = [
"crack_id", "length_px", "width_px",
"orientation", "confidence", "classification"
]
for col in required_columns:
assert col in df.columns, f"Missing required column: {col}"
result["output_files"].append(str(inv_path))
# Step 5: Verify output mask dimensions match input
from PIL import Image
input_img = Image.open(input_path)
mask_img = Image.open(output_path)
assert input_img.size == mask_img.size, \
f"Mask dimensions {mask_img.size} do not match input {input_img.size}"
result["passed"] = True
except Exception as e:
result["failure_reason"] = f"{type(e).__name__}: {str(e)}"
result["passed"] = False
result["duration_ms"] = int((time.time() - start) * 1000)
return result
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--input", required=True)
parser.add_argument("--output-dir", default="/tmp/smoke-output")
args = parser.parse_args()
result = test_smoke_crack(args.input, args.output_dir)
print(json.dumps(result, indent=2))
sys.exit(0 if result["passed"] else 1)
Une assertion par catégorie. Affirmer que l’exécution se termine. Affirmer que la sortie existe. Affirmer que les colonnes existent. Ne pas affirmer les plages numériques, les tailles de fichiers exactes ou les métriques de qualité des données. Chaque assertion supplémentaire augmente le coût de maintenance du test et réduit sa fiabilité.
Utiliser des imports réels. Ne pas simuler les modules de la chaîne de traitement. Le test de fumée doit exercer la chaîne d’import réelle pour détecter les erreurs d’import et les dépendances manquantes. Un test de fumée qui utilise unittest.mock pour supprimer les erreurs d’import va à l’encontre de son propre objectif.
Configuration et nettoyage minimaux. Le test ne doit nécessiter aucune configuration de base de données, aucun démarrage de service, aucune configuration externe au-delà du fichier d’entrée du test. Si une configuration est nécessaire, elle doit faire partie de la définition du travail CI, pas du script de test. Chaque test de fumée doit pouvoir être exécuté sur l’ordinateur portable d’un développeur avec une seule commande.
Déterministe. La même entrée doit toujours produire le même résultat réussi/échec. Les germes aléatoires doivent être fixés dans la configuration de la chaîne de traitement. Les fichiers d’entrée des tests doivent être sous contrôle de version. Les tests de fumée non déterministes sont pires qu’inutiles — ils érodent la confiance dans l’ensemble de l’infrastructure de test.
Sortie structurée autonome. Le test doit imprimer une sortie JSON structurée à la fin, facilitant l’analyse des résultats par les systèmes CI sans analyse de logs personnalisée. Le schéma JSON doit être cohérent pour tous les tests de fumée de la suite.
Rapide. Chaque test doit se terminer en moins de 60 secondes sur le matériel CI. Si un test dépasse systématiquement cette limite, optimisez le test avant de l’ajouter à la suite. Un test de fumée qui prend 5 minutes sera ignoré par les développeurs exécutant les tests localement.
except Exception générique peut manquer les échecs d’import. Laissez certaines exceptions se propager ou, au minimum, enregistrez les erreurs d’import séparément.--output-dir pour permettre des environnements d’exécution flexibles.Lorsqu’un test de fumée échoue, le flux de travail de développement doit passer du « développement » au « diagnostic et correction ». Une interprétation efficace des échecs suit une approche structurée qui fait correspondre les symptômes d’échec aux causes profondes probables.
| Symptôme d’Échec | Cause Racine Probable | Action Immédiate |
|---|---|---|
| ImportError | Dépendance manquante, module renommé, module supprimé, conflit de version | Vérifier requirements.txt et les changements d’import récents dans le diff du commit |
| ModuleNotFoundError | Paquet non installé ou pas dans le chemin Python | Vérifier que l’environnement correspond au fichier de verrouillage, vérifier les imports conditionnels |
| FileNotFoundError | Chemin de sortie modifié, problème de permission d’écriture, répertoire manquant | Vérifier la configuration du chemin de sortie dans les commits récents, vérifier la logique de création de répertoire |
| PermissionError | Permissions du système de fichiers insuffisantes dans le conteneur CI | Vérifier les permissions du Dockerfile et l’utilisateur d’exécution CI |
| Fichier de sortie vide | L’étape s’est terminée mais a ignoré la logique de traitement en raison d’un conditionnel qui s’est évalué de manière inattendue | Ajouter du débogage par journalisation pour tracer le chemin d’exécution, vérifier les retours prématurés |
| Colonne manquante | Changement de schéma dans une étape en amont, colonne renommée, colonne supprimée, incompatibilité de type | Comparer les schémas de colonnes entre les étapes de la chaîne, vérifier les PR récents touchant les définitions de schéma |
| Segfault ou OOM | Fuite mémoire, allocation mémoire illimitée, plantage d’extension native | Profiler avec une entrée réduite, vérifier les boucles infinies, vérifier la gestion de la mémoire CUDA |
| Délai d’attente | Boucle infinie, E/S bloquante, interblocage, API externe lente | Ajouter une enveloppe de délai d’attente, vérifier les problèmes de sécurité des threads, vérifier la connectivité réseau |
| AssertionError sur les dimensions | Opération de redimensionnement supprimée, taille d’entrée du modèle modifiée, conversion de type de données ayant changé la forme | Vérifier les paramètres de traitement d’image, vérifier les spécifications d’entrée du modèle |
| Erreur CUDA | Incompatibilité du pilote GPU, conflit de version CUDA, mémoire GPU insuffisante | Vérifier la version du kit d’outils CUDA, vérifier les pilotes GPU de l’image Docker |
Lorsqu’un test de fumée échoue dans le CI, le flux de travail de réponse recommandé est :
Consulter le rapport d’échec. La sortie JSON structurée du test de fumée inclut le champ failure_reason qui contient le type d’exception et le message. C’est le chemin le plus rapide pour comprendre ce qui a cassé.
Identifier si l’échec est une régression de code ou un problème d’infrastructure. Un ModuleNotFoundError sur un paquet qui était installé hier suggère une régression. Un Timeout qui apparaît sur tous les builds simultanément suggère un problème d’infrastructure (panne réseau, dégradation de l’exécuteur CI).
Revenir en arrière si la cause racine n’est pas évidente dans les 15 minutes. La suite de tests de fumée est rapide précisément pour permettre une reversion rapide. Un build qui échoue aux tests de fumée doit être immédiatement annulé pour débloquer le pipeline CI pour les autres développeurs.
Enquêter avec l’entrée de test. Exécuter le test de fumée défaillant localement avec la même entrée de test sous contrôle de version. Reproduire l’échec localement élimine les variables spécifiques au CI (différences de conteneurs, limites de ressources, problèmes de parallélisme).
Corriger et ajouter un test unitaire. Une fois la cause racine identifiée, corrigez le code et ajoutez un test unitaire au niveau approprié qui aurait détecté l’échec. Cela empêche la même classe de régression de se reproduire.
Vérifier que la correction passe les tests de fumée. Exécuter la suite complète de tests de fumée localement avant de pousser la correction. Cela garantit que la correction n’introduit pas de nouveaux échecs dans d’autres étapes de la chaîne.
Les tests de fumée peuvent produire des faux positifs — le test échoue mais la chaîne de traitement est en réalité fonctionnelle. Les causes courantes incluent :
Les tests de fumée instables érodent la confiance dans l’infrastructure de test. Les développeurs qui voient des tests de fumée échouer aléatoirement commenceront à ignorer les échecs. La solution est de déstabiliser agressivement : identifier la cause racine de l’instabilité et renforcer le test. Si un test ne peut pas être rendu fiable avec un effort raisonnable, il doit être déplacé vers une suite de test de moindre priorité ou remplacé par une conception plus robuste.
Pour les logiciels aéronautiques, y compris les chaînes de traitement d’inspection aéroportuaire, les tests de fumée ont une importance supplémentaire en raison de la nature critique pour la sécurité du domaine. Selon la DO-178C (Considérations sur les logiciels pour les systèmes et équipements aéroportés — Certification), la vérification logicielle suit un processus rigoureux basé sur les exigences. Bien que la DO-178C ne mentionne pas explicitement le « test de fumée », le concept de Test d’Intégration Matériel/Logiciel défini dans la section 6.4.3 exige que le système intégré « démarre et que les fonctions de base fonctionnent » — l’équivalent fonctionnel d’un test de fumée.
Selon l’Annexe 14 de l’OACI Volume I — Conception et exploitation des aérodromes — l’état des chaussées aéroportuaires affecte directement la sécurité des aéronefs. Une défaillance de chaussée sur une piste peut causer des dommages à l’aéronef ou une perte de contrôle au décollage et à l’atterrissage. Les logiciels utilisés pour l’inspection automatisée des chaussées doivent donc répondre à des normes de fiabilité à la hauteur des implications sécuritaires de leurs résultats. Les tests de fumée constituent la première ligne de défense contre les erreurs logicielles qui pourraient compromettre les évaluations de l’état des chaussées.
Pour TarmacView, les tests de fumée font partie d’un cadre d’assurance qualité logicielle plus large qui comprend :
Cette approche multicouche garantit que les tests de fumée servent de première barrière sans être la seule barrière. Un test de fumée réussi signifie que la chaîne de traitement est structurellement solide. Mais ce sont les tests d’intégration, les tests de validation et les benchmarks de performance qui fournissent la confiance nécessaire pour utiliser les résultats de TarmacView pour de vraies décisions de maintenance aéroportuaire.
Le test de fumée est une pratique fondamentale de qualité logicielle qui offre une valeur disproportionnée par rapport à son coût de mise en œuvre. Pour les chaînes de traitement logicielles d’inspection comme TarmacView, les tests de fumée détectent les échecs d’intégration — imports cassés, fichiers manquants, incompatibilités de schéma — en secondes plutôt qu’en heures. Ils servent de première barrière dans l’IC/CD, rejetant les builds instables avant qu’ils ne consomment l’infrastructure de test. La suite de tests de fumée de TarmacView couvre chaque phase de la chaîne de traitement, de l’acquisition d’image à la détection de fissures, la classification des défauts, l’évaluation de surface, le relevé cartographique et la visualisation, chaque test vérifiant que l’étape s’exécute, produit une sortie et maintient les schémas de colonnes attendus.
La clé d’un test de fumée efficace est de comprendre sa portée limitée. Les tests de fumée vérifient que la chaîne de traitement s’exécute et produit une sortie. Ils ne vérifient pas l’exactitude, la performance, la gestion des cas limites ou la qualité des données. Ceux-ci sont validés par d’autres types de tests dans le cadre plus large de l’assurance qualité. Lorsque les tests de fumée sont conçus avec cette discipline — entrées minimales représentatives, temps d’exécution rapides, couverture large mais superficielle — ils fournissent la détection rapide et fiable des défaillances qui rend les pipelines IC/CD efficaces pour les logiciels aéronautiques critiques pour la sécurité.
TarmacView utilise des tests de fumée automatisés pour valider chaque étape de sa chaîne de traitement d'inspection. Contactez-nous pour découvrir comment nous maintenons la qualité logicielle pour l'analyse d'infrastructures aéroportuaires critiques.
Le test de fumée de la tête de défaut valide que le pipeline de détection des défauts structurels de TarmacView — backbone DINOv3 + tête MLP à 5 étiquettes pour...
Explorez les concepts avancés des tests de performance logicielle et de l’assurance qualité (QA), incluant processus, méthodologies, outils, métriques et applic...
Une procédure de test est une méthode documentée, étape par étape, permettant de vérifier systématiquement la conformité, la justesse et la performance des syst...