Migrating from Legacy Systems

Comparaison des frameworks de test

Comparez le framework TofuPilot, OpenHTF, pytest, OpenTAP et NI TestStand pour le test de production : code réel, matrice de fonctionnalités et coûts.

JJulien Buteau
intermediate14 min de lecture14 mars 2026
Validez un test avant de déployer.
Test existant
Connecter les résultats
Comparer un test
Déployer

Cinq frameworks dominent l'automatisation des tests de production : le framework TofuPilot, OpenHTF, pytest, OpenTAP et NI TestStand. Chacun fait des compromis différents entre structure, flexibilité, coût et écosystème. Ce guide les compare avec du code réel, des métriques concrètes et des critères de décision pour vous aider à choisir le bon.

Vue d'ensemble des frameworks

FrameworkLangageLicenceOrigineFocus
Framework TofuPilotPython (moteur Rust)MIT (gratuit)TofuPilotTest de production avec exécution parallèle
OpenHTFPythonApache 2.0 (gratuit)GoogleTest de fabrication/production
pytestPythonMIT (gratuit)CommunautéTest logiciel, adapté au hardware
OpenTAPC# / PythonMPL 2.0 (gratuit)KeysightAutomatisation de test avec instruments
NI TestStandLabVIEW / C / PythonCommercial (4 310 $/poste)NI (Emerson)Test de fabrication entreprise

Matrice de comparaison des fonctionnalités

FonctionnalitéFramework TofuPilotOpenHTFpytestOpenTAPTestStand
Mesures structuréesIntégré (validators YAML)Intégré (nom, valeur, limites, unités)Manuel (assert uniquement)Via pluginsIntégré
Saisie du numéro de sérieIntégréeInvite intégréeManuelPluginIntégré
Interface opérateurDéclarative, depuis la procédureInterface web intégréeAucuneIntégrée (éditeur GUI)Intégrée (Sequence Editor)
Séquencement des testsProcédure YAMLOrdre des phasesOrdre des fonctions (plugins)Ordre des étapes (GUI)Fichiers de séquence (GUI)
Phases parallèlesNatives (moteur Rust)NonVia xdistNativesNatives
Bancs multi-slotsNatifLimitéManuelNatifNatif
Agrégations de waveformsIntégrées (moyenne, min, max, écart-type)NonManuelPluginManuel
Validators par axeIntégrésNonManuelNonNon
Pilotes d'instrumentsPlugs (classes Python simples)Plugs (Python)Fixtures (Python)Plugins (C#/Python)Pilotes NI (LabVIEW)
Déploiement sur stationsPush Git, rollback instantanéÀ votre chargeÀ votre chargeManuelManuel
Gestion hors ligneFile d'attente et syncÀ votre chargeÀ votre chargeManuelDépend de la base
Contrôle de versionGit (YAML + Python)Git (fichiers Python)Git (fichiers Python)Git (XML + code)Difficile (fichiers binaires .seq)
Intégration CI/CDNative (Python)Native (Python)Native (Python)PossibleDifficile
Multi-plateformeLinux, macOS, WindowsLinux, macOS, WindowsLinux, macOS, WindowsLinux, WindowsWindows uniquement
CommunautéRécente, plus petitePetite (~640 stars)Massive (11K+ stars)Petite (~200 stars)Grande (forums NI)
Courbe d'apprentissageFaible (YAML + Python simple)MoyenneFaibleMoyenneÉlevée
Coût annuel (5 postes)0 $0 $0 $0 $~21 550 $

Le même test dans chaque framework

Un test fonctionnel simple : mesurer une tension de rail 3,3 V, vérifier qu'elle est comprise entre 3,2 V et 3,4 V.

Framework TofuPilot

Le YAML de procédure déclare la séquence et les limites. Les phases sont des fonctions Python simples sans décorateur, et les plugs des classes Python simples.

procedure.yaml
24 lines
name: PCBA Functional Testversion: 1.0.0unit:  serial_number:    default_value: "PCBA000001"  part_number:    default_value: "PCBA-100"plugs:  - name: dut    python: plugs.dut:Dutmain:  - name: Power Rail Test    python: phases.power_rail    measurements:      - name: Rail 3V3        unit: V        validators:          - operator: ">="            expected_value: 3.2          - operator: "<="            expected_value: 3.4
phases/power_rail.py
def power_rail(measurements, dut):    measurements.rail_3v3 = dut.read_voltage()
plugs/dut.py
class Dut:    def read_voltage(self) -> float:        return 3.31  # Remplacer par une lecture instrument

Lancez-le depuis le dossier de la procédure avec tofupilot run.

Points forts : Les limites vivent dans le YAML comme des données, donc le plan de test est lisible et diffable séparément de la logique. Les phases et les slots de banc s'exécutent en parallèle sur un moteur Rust pendant que votre code reste du Python simple. L'interface opérateur est générée depuis la procédure sans travail frontend. Les procédures se déploient sur les stations via un push Git, avec rollback instantané, et les runs se mettent en file d'attente quand le réseau tombe.

Point faible : Plus récent qu'OpenHTF, donc communauté plus petite et moins d'exemples publics.

OpenHTF

comparison/openhtf_example.py
29 lines
import openhtf as htffrom openhtf.util import unitsclass DutPlug(htf.plugs.BasePlug):    def setUp(self):        self.voltage = 3.31  # Remplacer par la lecture de l'instrument    def tearDown(self):        pass@htf.measures(    htf.Measurement("rail_3v3")    .in_range(3.2, 3.4)    .with_units(units.VOLT),)@htf.plug(dut=DutPlug)def test_power(test, dut):    test.measurements.rail_3v3 = dut.voltagedef main():    test = htf.Test(test_power, procedure_id="FCT-001", part_number="PCBA-100")    test.execute(test_start=lambda: input("Numéro de série : "))if __name__ == "__main__":    main()

Points forts : Les mesures sont des données structurées (nom, valeur, limites, unités). Des années d'usage en production à grande échelle. L'invite de numéro de série est intégrée. S'exécute nativement sur le CLI TofuPilot sans code supplémentaire.

Point faible : Les phases s'exécutent en séquence sur une seule unité. Les phases parallèles et les bancs multi-slots s'orchestrent en dehors du framework.

pytest

comparison/pytest_example.py
import pytest@pytest.fixturedef dut():    connection = {"voltage": 3.31}  # Remplacer par une vraie connexion    yield connectiondef test_power_rail(dut):    voltage = dut["voltage"]    assert 3.2 <= voltage <= 3.4, f"Rail 3,3 V : {voltage} V"

Points forts : Familier pour tout développeur Python. Énorme écosystème de plugins. Système de fixtures flexible. Excellent pour la R&D et la validation.

Point faible : Les mesures sont implicites (instructions assert). La valeur mesurée vit dans un assert puis disparaît, donc pas de données structurées pour l'analytique sans code supplémentaire.

OpenTAP

comparison/opentap_example.cs
21 lines
// Étape de test OpenTAP en C#using OpenTap;[Display("Power Rail Test", Group: "FCT")]public class PowerRailStep : TestStep{    [Display("Lower Limit")]    public double LowerLimit { get; set; } = 3.2;    [Display("Upper Limit")]    public double UpperLimit { get; set; } = 3.4;    public override void Run()    {        double voltage = 3.31; // Remplacer par la lecture de l'instrument        Results.Publish("rail_3v3", new { Voltage = voltage });        if (voltage < LowerLimit || voltage > UpperLimit)            UpgradeVerdict(Verdict.Fail);    }}

Points forts : Éditeur d'étapes en GUI pour les non-programmeurs. Forte intégration avec les instruments Keysight. Architecture de plugins pour les plans de test.

Point faible : Langage principal en C# (le plugin Python existe mais est secondaire). Communauté plus restreinte.

NI TestStand

TestStand utilise un éditeur de séquences visuel. Le test équivalent est un fichier de séquence (.seq) avec une étape « Numeric Limit Test » configurée via l'interface : valeur de test = lecture de tension, limite basse = 3,2, limite haute = 3,4.

Points forts : Mature, qualité entreprise. Intégration poussée avec le hardware NI. Génération de rapports, journalisation en base de données, exécution parallèle intégrées.

Point faible : 4 310 $/poste/an. Windows uniquement. Les fichiers de séquence binaires ne se versionnent pas bien. Dépendance à l'écosystème NI.

Analyse des coûts

Framework TofuPilotOpenHTFpytestOpenTAPTestStand
Licence (5 postes)0 $0 $0 $0 $21 550 $/an
Licence (20 postes)0 $0 $0 $0 $86 200 $/an
Déploiement runtimeGratuitGratuitGratuitGratuitLicences runtime supplémentaires
FormationAuto-formation (docs)Auto-formation (docs)Auto-formation (docs)Auto-formation (docs)Formations NI (2 000 $+)
Verrouillage fournisseurAucun (MIT, open source)AucunAucunFaible (proche Keysight)Élevé (écosystème NI)
SupportCommunauté + TofuPilotCommunauté (GitHub)Communauté (massive)Communauté + KeysightContrat de support NI

Quand utiliser chaque framework

ScénarioMeilleur choixPourquoi
Test de production, ligne limitée par le débitFramework TofuPilotPhases parallèles et bancs multi-slots réduisent le temps de cycle
Test de production, opérateurs guidésFramework TofuPilotInterface opérateur déclarative, sans travail frontend
Validation de waveforms ou de sweepsFramework TofuPilotAgrégations et validators par axe vérifient la forme de la courbe
Nouvelles stations, plusieurs sitesFramework TofuPilotDéploiement sur push Git, rollback instantané, file d'attente hors ligne
Suites OpenHTF déjà en productionOpenHTFTourne nativement sur le CLI TofuPilot ; le coût de migration n'en vaut pas la peine
Paradigme Python pur, sans couche YAMLOpenHTFTout en décorateurs Python
Validation R&D, CI firmwarepytestFlexible, itération rapide, natif CI/CD, énorme écosystème
Instruments multi-fournisseurs, entrepriseOpenTAPArchitecture de plugins, éditeur GUI, intégration Keysight
Hardware NI existant, grande entrepriseTestStandIntégration NI poussée, support entreprise, infrastructure existante
Mixte (R&D + production)pytest + Framework TofuPilotpytest pour la validation, Framework pour la production

Parcours de migration

De TestStand vers le framework TofuPilot

Concept TestStandÉquivalent framework TofuPilot
Fichier de séquence (.seq)procedure.yaml
Types d'étapesFonctions de phase dans phases/
Numeric Limit Testmeasurements avec validators en YAML
String Value Testvalidators avec operator: "=="
Module d'étape (code)Classe de plug dans plugs/
Process modelIntégré au CLI
Génération de rapportsTableau de bord TofuPilot
Numéro de série UUTunit.serial_number dans la procédure
Exécution de séquences en parallèleexecution.slots

D'OpenHTF vers le framework TofuPilot

Concept OpenHTFÉquivalent framework TofuPilot
Fonction de phase avec @htf.measuresFonction simple, mesures déclarées en YAML
.in_range(3.2, 3.4)validators avec >= et <=
Sous-classe de BasePlugClasse Python simple
@htf.plug(dut=DutPlug)Plug injecté par nom de paramètre
test.measurements.x = vmeasurements.x = v
htf.Test(phase1, phase2)Liste main: dans la procédure

De pytest vers le framework TofuPilot

Concept pytestÉquivalent framework TofuPilot
Fonction de testFonction de phase
FixturePlug
Instruction assertvalidators dans le YAML de procédure
conftest.pyDossier plugs/
XML JUnitTableau de bord TofuPilot

Intégration TofuPilot

Les cinq frameworks fonctionnent avec TofuPilot :

FrameworkMéthode d'intégrationEffort
Framework TofuPilotNative (tofupilot run --upload)Aucun
OpenHTFNative sur le CLI TofuPilotAucun
pytestSDK Python (TofuPilotClient)~10 lignes par test
OpenTAPAPI REST ou SDK PythonMoyen
TestStandAPI RESTMoyen

Le framework TofuPilot et OpenHTF tournent tous deux nativement sur le CLI, qui streame phases, mesures, logs, pièces jointes et interface opérateur vers le dashboard sans code supplémentaire d'un côté comme de l'autre.

Arbre de décision

  1. Avez-vous une infrastructure TestStand existante ? Oui, et elle fonctionne bien : restez sur TestStand. Oui, mais vous souhaitez migrer : passez au framework TofuPilot.
  2. Utilisez-vous déjà OpenHTF en production ? Oui : gardez-le. Il tourne nativement sur le CLI TofuPilot, et le coût de migration n'en vaut pas la peine sauf si vous avez besoin de slots parallèles.
  3. Construisez-vous des tests de production sur de nouvelles stations ? Oui : le framework TofuPilot. Exécution parallèle, interface opérateur déclarative et déploiement sur push sont intégrés.
  4. Faites-vous de la R&D ou de la validation firmware ? Oui : pytest. Plus flexible, meilleur pour le CI/CD.
  5. Avez-vous besoin d'une interface graphique pour les non-programmeurs ? Oui : OpenTAP. Éditeur d'étapes visuel.
  6. Pas sûr ? Commencez par le framework TofuPilot. tofupilot run ./procedure.yaml exécute une procédure sur votre machine sans compte.

Pour une comparaison plus poussée des deux options Python dédiées, voir Framework TofuPilot vs OpenHTF.

Plus de guides

Mettez ce guide en pratique