Test Types & Methods

Suivre les données de réparation

Découvrez comment structurer les tests OpenHTF pour que les boucles de réparation, les actions de reprise et les retests soient tous liés au même numéro.

JJulien Buteau
intermediate8 min de lecture14 mars 2026

Les tests de production détectent les défauts, mais la vraie valeur vient de la boucle fermée : diagnostiquer les défaillances, réparer les unités et les retester. Chaque retest est lié au numéro de série original, ce qui vous donne un historique complet du parcours de chaque unité dans votre processus de réparation.

La boucle de réparation

Un flux de réparation typique suit ce cycle : une unité échoue à un test, un technicien diagnostique la cause racine, effectue une réparation, et l'unité repasse par les tests. Sans données structurées, cet historique se perd dans des tableurs ou des journaux papier.

La solution consiste à tout indexer sur le numéro de série. Chaque exécution de test sur le même DUT apparaît automatiquement dans son historique d'unité. Aucune configuration spéciale n'est nécessaire. Utilisez simplement le même numéro de série lors du retest.

Structurer votre test initial

Commencez par un test OpenHTF standard qui mesure votre DUT et envoie les résultats.

functional_test.py
30 lines
import openhtf as htffrom openhtf.util import unitsfrom tofupilot.openhtf import upload@htf.measures(    htf.Measurement("output_voltage")    .in_range(minimum=4.8, maximum=5.2)    .with_units(units.VOLT),    htf.Measurement("current_draw")    .in_range(minimum=0.095, maximum=0.105)    .with_units(units.AMPERE),)def functional_check(test):    test.measurements.output_voltage = 5.05    test.measurements.current_draw = 0.1012def main():    test = htf.Test(        functional_check,        procedure_id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",  # UUID de procédure du dashboard        part_number="PCBA-100",    )    test.add_output_callbacks(upload())    test.execute(lambda: "SN-20260312-001")if __name__ == "__main__":    main()

Quand ce test échoue, l'unité entre dans votre file d'attente de réparation.

Enregistrer les actions de réparation comme mesures

Après qu'un technicien a diagnostiqué et réparé l'unité, capturez ce contexte dans le retest. Une phase dédiée enregistre ce qui a été trouvé et ce qui a été fait.

retest_after_repair.py
44 lines
import openhtf as htffrom openhtf.util import unitsfrom tofupilot.openhtf import upload@htf.measures(    htf.Measurement("repair_code"),    htf.Measurement("failure_category"),    htf.Measurement("repair_action"),)def record_repair_info(test):    # Ces valeurs proviennent de la saisie du technicien de réparation    test.measurements.repair_code = "RC-042"    test.measurements.failure_category = "solder_bridge"    test.measurements.repair_action = "reworked_U3_solder_joints"@htf.measures(    htf.Measurement("output_voltage")    .in_range(minimum=4.8, maximum=5.2)    .with_units(units.VOLT),    htf.Measurement("current_draw")    .in_range(minimum=0.095, maximum=0.105)    .with_units(units.AMPERE),)def functional_recheck(test):    test.measurements.output_voltage = 5.01    test.measurements.current_draw = 0.1003def main():    test = htf.Test(        record_repair_info,        functional_recheck,        procedure_id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",        part_number="PCBA-100",    )    test.add_output_callbacks(upload())    # Le même numéro de série lie ce retest à la défaillance originale    test.execute(lambda: "SN-20260312-001")if __name__ == "__main__":    main()

La phase record_repair_info stocke le diagnostic et l'action de réparation aux côtés des mesures du retest, liés à la même unité.

En pratique, le technicien saisit ces valeurs plutôt que de les coder en dur. Demandez-les avec openhtf.plugs.user_input pour que l'opérateur choisisse dans votre liste de catégories au lieu de saisir du texte libre : c'est ce qui garde les données agrégeables par la suite.

Utiliser des catégories de défaillance cohérentes

Définissez un ensemble standard de catégories de défaillance et de codes de réparation au sein de votre équipe. Un nommage cohérent permet de filtrer et d'agréger les données de réparation ultérieurement.

Catégories de défaillance courantes pour les tests PCBA :

CatégorieDescription
solder_bridgeConnexion de soudure involontaire entre les pads
cold_jointMouillage de soudure insuffisant
missing_componentComposant non placé lors de l'assemblage
wrong_valueValeur de composant incorrecte
damaged_componentComposant endommagé lors de la manipulation ou de la refusion
pcb_defectProblème au niveau de la carte (fissure de piste, défaillance de via)

Stockez-les comme mesures de type chaîne pour qu'elles restent recherchables.

Une liste courte vaut mieux qu'une liste exhaustive. Les catégories que personne ne sait distinguer sont remplies au hasard, et le Pareto qui en découle est alors pire que pas de graphique du tout.

Suivre les cycles de réparation multiples

Certaines unités nécessitent plus d'une tentative de réparation. Chaque retest crée une nouvelle exécution sur le même numéro de série, et l'historique de l'unité montre la chaîne complète : échec initial, première tentative, deuxième tentative et passage final.

second_repair_retest.py
44 lines
import openhtf as htffrom openhtf.util import unitsfrom tofupilot.openhtf import upload@htf.measures(    htf.Measurement("repair_code"),    htf.Measurement("failure_category"),    htf.Measurement("repair_action"),    htf.Measurement("repair_cycle"),)def record_repair_info(test):    test.measurements.repair_code = "RC-043"    test.measurements.failure_category = "cold_joint"    test.measurements.repair_action = "reflowed_C12_pads"    test.measurements.repair_cycle = 2@htf.measures(    htf.Measurement("output_voltage")    .in_range(minimum=4.8, maximum=5.2)    .with_units(units.VOLT),    htf.Measurement("current_draw")    .in_range(minimum=0.095, maximum=0.105)    .with_units(units.AMPERE),)def functional_recheck(test):    test.measurements.output_voltage = 4.98    test.measurements.current_draw = 0.0998def main():    test = htf.Test(        record_repair_info,        functional_recheck,        procedure_id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",        part_number="PCBA-100",    )    test.add_output_callbacks(upload())    test.execute(lambda: "SN-20260312-001")if __name__ == "__main__":    main()

Ajouter une mesure repair_cycle facilite le comptage du nombre de tentatives par unité. Fixez un seuil au-delà duquel une unité n'est plus réparée mais mise au rebut : une carte à sa quatrième reprise a généralement absorbé plus de temps technicien qu'elle ne vaut, et les refusions répétées abîment le stratifié.

Analyser les tendances de réparation

Une fois les données de réparation collectées, vous pouvez répondre aux questions qui comptent sans écrire de scripts d'analyse.

L'historique de l'unité affiche chaque exécution de test pour un numéro de série par ordre chronologique. Vous voyez exactement quand une unité a échoué, ce qui a été réparé et si le retest a réussi.

Les diagrammes de Pareto des défaillances classent vos catégories par fréquence. Si solder_bridge domine, c'est un signal pour investiguer votre profil de refusion ou la conception du pochoir.

Les tendances de rendement au premier passage reflètent l'efficacité de vos réparations dans le temps. Un rendement en hausse après des modifications de processus confirme que la correction fonctionne. Une unité qui échoue constamment au même test après plusieurs réparations peut pointer vers un problème de conception plus profond.

Surveillez l'écart entre rendement au premier passage et rendement final. Un écart qui se creuse signifie que le process se dégrade pendant que la reprise l'absorbe, ce qui paraît correct sur un graphique de rendement final jusqu'au jour où la capacité de reprise sature.

Séparer les procédures entre test initial et retest

Pour la traçabilité, envisagez des procédures distinctes pour les tests initiaux et les retests. Les exécutions sont regroupées par procédure, donc cette séparation rend le reporting plus propre.

Chaque procédure a son propre UUID dans le dashboard : pointer un script vers la procédure de retest revient à changer procedure_id.

retest_procedure.py
38 lines
import openhtf as htffrom openhtf.util import unitsfrom tofupilot.openhtf import uploadRETEST_PROCEDURE_ID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"  # « PCBA Functional Test - Retest »@htf.measures(    htf.Measurement("repair_code"),    htf.Measurement("repair_action"),)def record_repair_info(test):    test.measurements.repair_code = "RC-042"    test.measurements.repair_action = "reworked_U3_solder_joints"@htf.measures(    htf.Measurement("output_voltage")    .in_range(minimum=4.8, maximum=5.2)    .with_units(units.VOLT),)def functional_recheck(test):    test.measurements.output_voltage = 5.02def main():    test = htf.Test(        record_repair_info,        functional_recheck,        procedure_id=RETEST_PROCEDURE_ID,        part_number="PCBA-100",    )    test.add_output_callbacks(upload())    test.execute(lambda: "SN-20260312-001")if __name__ == "__main__":    main()

Vous pouvez ainsi comparer le rendement entre tests initiaux et retests indépendamment, tandis que l'historique de l'unité lie toujours tout sous un seul numéro de série.

Le compromis : séparer les procédures signifie que le rendement au premier passage de la procédure initiale ne compte plus les unités qui ont fini par passer au retest. C'est généralement ce que vous voulez, mais précisez de quel chiffre vous parlez quand vous le communiquez.

Plus de guides

Mettez ce guide en pratique