Comment migrer de LabVIEW TestExec vers Python avec TofuPilot
LabVIEW TestExec a rempli son rôle. Mais les coûts de licence ne cessent d'augmenter, trouver des développeurs LabVIEW devient de plus en plus difficile, et votre pipeline CI/CD ne parle pas le langage G. Python vous donne le langage, OpenHTF vous donne le framework de test, et TofuPilot vous donne la plateforme de données.
Voici comment effectuer la transition sans perdre votre couverture de test.
Pourquoi les équipes migrent
| Point de friction | LabVIEW TestExec | Python + TofuPilot |
|---|---|---|
| Licences | Par poste, renouvellement annuel | Gratuit et open source |
| Vivier de développeurs | En diminution, spécialisé | Large, en croissance |
| Contrôle de version | VIs binaires, conflits de fusion | Fichiers texte, Git standard |
| Intégration CI/CD | Adaptateurs personnalisés nécessaires | Support natif pytest/OpenHTF |
| Pilotes d'instruments | Écosystème NI uniquement | PyVISA, tout instrument SCPI |
| Stockage des données | Fichiers TDM/TDMS locaux | Base de données cloud avec API |
Prérequis
- Python 3.8+ installé
pip install openhtf tofupilot pyvisa- Accès à vos séquences et spécifications de test LabVIEW existantes
- Documentation des instruments (références de commandes SCPI)
Étape 1 : Mapper votre architecture TestExec
LabVIEW TestExec et OpenHTF partagent des concepts similaires avec des noms différents :
| LabVIEW TestExec | OpenHTF + TofuPilot | Notes |
|---|---|---|
| Séquence de test | htf.Test() | Conteneur de test de niveau supérieur |
| Étape de test | Fonction de phase | Fonction Python décorée |
| Limite | Validateur htf.Measurement | .in_range(), .at_most(), etc. |
| Résultat d'étape | Valeur de mesure | Stockée avec le statut réussite/échec |
| Fichier de séquence (.seq) | Script Python (.py) | Texte sous contrôle de version |
| Interface opérateur | Interface station TofuPilot | Web, pas de runtime LabVIEW nécessaire |
| Rapport | Tableau de bord TofuPilot | Automatique, en temps réel |
| Variable globale de station | Config au niveau module ou variable d'env | Patterns Python standards |
Étape 2 : Convertir les étapes de test en phases Python
Une étape LabVIEW TestExec typique qui lit une tension devient une phase Python :
Avant (pseudo-code LabVIEW TestExec) :
Step: "Read 5V Rail"
Type: Numeric Limit Test
Instrument: DMM_1 (NI PXI-4072)
Command: Measure DC Voltage
Low Limit: 4.95
High Limit: 5.05
Units: V
Après (Python avec OpenHTF) :
import openhtf as htf
from openhtf.util import units
import pyvisa
@htf.measures(
htf.Measurement("voltage_5v_rail")
.with_units(units.VOLT)
.in_range(4.95, 5.05)
.doc("Tension de sortie du rail 5V"),
)
def read_5v_rail(test, dmm):
"""Lire et valider la tension du rail 5V."""
voltage = float(dmm.query("MEAS:VOLT:DC?"))
test.measurements.voltage_5v_rail = voltageLe pattern est toujours le même :
- Définir les mesures avec des limites (remplace les colonnes de limites)
- Écrire le contrôle d'instrument dans le corps de la phase (remplace le VI)
- Assigner les valeurs mesurées (remplace le résultat de l'étape)
Étape 3 : Gérer les connexions d'instruments
LabVIEW TestExec utilise l'architecture de pilotes d'instruments NI. Python utilise PyVISA, qui fonctionne avec NI, Keysight, Rigol et tout instrument compatible SCPI.
import pyvisa
def connect_instruments():
"""Remplacer les variables globales de station TestExec par des connexions PyVISA."""
rm = pyvisa.ResourceManager()
instruments = {
"dmm": rm.open_resource("TCPIP::192.168.1.10::INSTR"),
"psu": rm.open_resource("TCPIP::192.168.1.11::INSTR"),
"scope": rm.open_resource("USB0::0x0957::0x1796::INSTR"),
}
# Configurer les instruments
instruments["dmm"].timeout = 5000
instruments["psu"].write("*RST")
return instrumentsSi vous utilisez des instruments NI PXI, le backend NI-VISA fonctionne avec PyVISA. Vos instruments GPIB, USB et TCP/IP fonctionnent sans aucun logiciel NI.
Étape 4 : Convertir le contrôle de flux de séquence
LabVIEW TestExec dispose d'un contrôle de flux intégré (préconditions, post-actions, branchements). Dans OpenHTF, vous utilisez du Python standard :
Exécution conditionnelle :
import openhtf as htf
@htf.measures(
htf.Measurement("board_variant")
.with_allowed_values("A", "B", "C"),
)
def detect_variant(test):
"""Lire la variante de carte depuis l'EEPROM ou le pont diviseur résistif."""
variant = read_board_variant()
test.measurements.board_variant = variant
test.state["variant"] = variant
@htf.measures(
htf.Measurement("bluetooth_rssi")
.with_units(units.DECIBEL)
.at_least(-70),
)
def bluetooth_test(test):
"""S'exécute uniquement sur la variante B (cartes équipées Bluetooth)."""
if test.state.get("variant") != "B":
return # Ignorer pour les variantes sans BT
rssi = scan_bluetooth()
test.measurements.bluetooth_rssi = rssiSetup et teardown :
import openhtf as htf
@htf.PhaseOptions(timeout_s=10)
def setup_fixture(test, fixture_controller):
"""Remplace le groupe d'étapes Setup de TestExec."""
fixture_controller.clamp()
fixture_controller.connect_probes()
@htf.PhaseOptions(run_if=lambda: True) # S'exécute toujours
def teardown_fixture(test, fixture_controller):
"""Remplace le groupe d'étapes Cleanup de TestExec. S'exécute même en cas d'échec."""
fixture_controller.release()
fixture_controller.disconnect_probes()Étape 5 : Mettre en place la collecte de données
LabVIEW TestExec stocke les résultats dans des fichiers locaux (TDM, TDMS, XML). TofuPilot stocke tout dans le cloud avec une traçabilité complète.
import openhtf as htf
from tofupilot import TofuPilotClient
def main():
instruments = connect_instruments()
test = htf.Test(
setup_fixture,
detect_variant,
read_5v_rail,
bluetooth_test,
teardown_fixture,
phase_kwargs={
"dmm": instruments["dmm"],
"psu": instruments["psu"],
},
)
test.add_output_callbacks(
TofuPilotClient().as_openhtf_callback(
procedure_id="pcba-fct-v3",
procedure_name="PCBA FCT (migré depuis TestExec)",
)
)
test.execute(test_start=htf.PhaseDescriptor.wrap(
lambda test: setattr(test, "dut_id", input("Scanner le numéro de série : "))
))
if __name__ == "__main__":
main()Stratégie de migration
Ne réécrivez pas tout d'un coup. Migrez station par station :
- Choisissez une station de test avec la séquence la plus simple
- Documentez la spécification de test existante (étapes, limites, instruments, flux)
- Écrivez l'équivalent Python en suivant les patterns ci-dessus
- Exécutez les deux systèmes en parallèle pour un lot de production
- Comparez les résultats pour vérifier l'équivalence
- Basculez quand les résultats correspondent
- Passez à la station suivante
Conservez vos séquences LabVIEW TestExec comme documentation de référence. Les scripts Python les remplacent, mais avoir la spécification originale aide pendant la validation.
Pièges courants
| Problème | Solution |
|---|---|
| Les pilotes NI nécessitent le runtime LabVIEW | PyVISA avec le backend NI-VISA fonctionne sans LabVIEW |
| Groupes d'étapes parallèles TestExec | Utilisez le threading ou asyncio Python |
| Callbacks TestExec (en cas d'échec, en cas de réussite) | Options de phase OpenHTF et callbacks de sortie |
| Suivi du modèle/numéro de série de la station | Propriétés de configuration de station TofuPilot |
| Génération de rapports TestExec | TofuPilot génère les rapports automatiquement |
| Boutons de l'interface opérateur | Interface station web de TofuPilot ou Tkinter personnalisé |
Le plus difficile n'est pas le code. C'est valider que les nouveaux tests détectent les mêmes défaillances que les anciens. Exécutez les deux systèmes en parallèle jusqu'à ce que vous soyez confiant.