Quatre frameworks dominent l'automatisation des tests de fabrication : 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
| Framework | Langage | Licence | Origine | Focus |
|---|---|---|---|---|
| OpenHTF | Python | Apache 2.0 (gratuit) | Test de fabrication/production | |
| pytest | Python | MIT (gratuit) | Communauté | Test logiciel, adapté au hardware |
| OpenTAP | C# / Python | MPL 2.0 (gratuit) | Keysight | Automatisation de test avec instruments |
| NI TestStand | LabVIEW / C / Python | Commercial (4 310 $/poste) | NI (Emerson) | Test de fabrication entreprise |
Matrice de comparaison des fonctionnalités
| Fonctionnalité | OpenHTF | pytest | OpenTAP | TestStand |
|---|---|---|---|---|
| Mesures structurées | Intégré (nom, valeur, limites, unités) | Manuel (assert uniquement) | Via plugins | Intégré |
| Saisie du numéro de série | Invite intégrée | Manuel | Plugin | Intégré |
| Interface opérateur | Interface web intégrée | Aucune | Intégrée (éditeur GUI) | Intégrée (Sequence Editor) |
| Séquencement des tests | Ordre des phases | Ordre des fonctions (plugins) | Ordre des étapes (GUI) | Fichiers de séquence (GUI) |
| DUT parallèles | Limité | Natif (pytest-xdist) | Natif | Natif |
| Pilotes d'instruments | Plugs (Python) | Fixtures (Python) | Plugins (C#/Python) | Pilotes NI (LabVIEW) |
| Format de rapport | Protobuf | JUnit XML | XML/JSON | XML/base de données |
| Contrôle de version | Git (fichiers Python) | Git (fichiers Python) | Git (XML + code) | Difficile (fichiers binaires .seq) |
| Intégration CI/CD | Native (Python) | Native (Python) | Possible | Difficile |
| Multi-plateforme | Linux, macOS, Windows | Linux, macOS, Windows | Linux, Windows | Windows uniquement |
| Communauté | Petite (~640 stars) | Massive (11K+ stars) | Petite (~200 stars) | Grande (forums NI) |
| Courbe d'apprentissage | Moyenne | Faible | Moyenne | Élevée |
| Coût annuel (5 postes) | 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.
OpenHTF
import openhtf as htf
from openhtf.util import units
from tofupilot.openhtf import TofuPilot
class 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.voltage
def main():
test = htf.Test(test_power, procedure_id="FCT-001", part_number="PCBA-100")
with TofuPilot(test):
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). Une seule ligne pour l'intégration TofuPilot. L'opérateur reçoit automatiquement une invite de numéro de série.
pytest
import pytest
from tofupilot import TofuPilotClient
@pytest.fixture
def dut():
connection = {"voltage": 3.31} # Remplacer par une vraie connexion
yield connection
def 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). Pas de données structurées pour l'analytique sans code supplémentaire.
OpenTAP
// É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
| OpenHTF | pytest | OpenTAP | TestStand | |
|---|---|---|---|---|
| Licence (5 postes) | 0 $ | 0 $ | 0 $ | 21 550 $/an |
| Licence (20 postes) | 0 $ | 0 $ | 0 $ | 86 200 $/an |
| Déploiement runtime | Gratuit | Gratuit | Gratuit | Licences runtime supplémentaires |
| Formation | Auto-formation (docs) | Auto-formation (docs) | Auto-formation (docs) | Formations NI (2 000 $+) |
| Verrouillage fournisseur | Aucun | Aucun | Faible (proche Keysight) | Élevé (écosystème NI) |
| Support | Communauté (GitHub) | Communauté (massive) | Communauté + Keysight | Contrat de support NI |
Quand utiliser chaque framework
| Scénario | Meilleur choix | Pourquoi |
|---|---|---|
| FCT en production, équipe Python | OpenHTF | Conçu pour le test de fabrication, mesures structurées, interface opérateur |
| Validation R&D, CI firmware | pytest | Flexible, itération rapide, natif CI/CD, énorme écosystème |
| Instruments multi-fournisseurs, entreprise | OpenTAP | Architecture de plugins, éditeur GUI, intégration Keysight |
| Hardware NI existant, grande entreprise | TestStand | Intégration NI poussée, support entreprise, infrastructure existante |
| Petite équipe, budget limité | OpenHTF ou pytest | Aucun coût de licence, écosystème Python |
| Mixte (R&D + production) | pytest + OpenHTF | pytest pour la validation, OpenHTF pour la production |
Parcours de migration
De TestStand vers OpenHTF
| Concept TestStand | Équivalent OpenHTF |
|---|---|
| Fichier de séquence (.seq) | Script de test Python |
| Types d'étapes | Fonctions de phase |
| Numeric Limit Test | @htf.measures avec .in_range() |
| String Value Test | @htf.measures avec .equals() |
| Module d'étape (code) | Classe Plug |
| Process model | Intégration TofuPilot |
| Génération de rapports | Tableau de bord TofuPilot |
| Numéro de série UUT | test.execute(test_start=lambda: input("Numéro de série : ")) |
De pytest vers OpenHTF
| Concept pytest | Équivalent OpenHTF |
|---|---|
| Fonction de test | Fonction de phase |
| Fixture | Plug |
| Instruction assert | @htf.measures avec des validateurs |
| conftest.py | Classes Plug dans un module partagé |
| JUnit XML | Sortie Protobuf + TofuPilot |
Intégration TofuPilot
Les quatre frameworks fonctionnent avec TofuPilot :
| Framework | Méthode d'intégration | Effort |
|---|---|---|
| OpenHTF | Native (with TofuPilot(test)) | 1 ligne |
| pytest | SDK Python (TofuPilotClient) | ~10 lignes par test |
| OpenTAP | API REST ou SDK Python | Moyen |
| TestStand | API REST | Moyen |
Arbre de décision
- Avez-vous une infrastructure TestStand existante ? Oui, et elle fonctionne bien : restez sur TestStand. Oui, mais vous souhaitez migrer : passez à OpenHTF.
- Construisez-vous des tests de production ? Oui : OpenHTF. Il a été conçu pour cela.
- Faites-vous de la R&D ou de la validation firmware ? Oui : pytest. Plus flexible, meilleur pour le CI/CD.
- Avez-vous besoin d'une interface graphique pour les non-programmeurs ? Oui : OpenTAP. Éditeur d'étapes visuel.
- Pas sûr ? Commencez par pytest. C'est le plus facile à apprendre et vous pouvez toujours ajouter OpenHTF pour la production par la suite.