Getting Started

Créer votre premier test matériel

Créez et exécutez un test matériel en Python en 15 minutes avec OpenHTF et TofuPilot, avec des mesures, des limites et un enregistrement automatique des.

JJulien Buteau
beginner12 min de lecture14 mars 2026

Vous pouvez exécuter un test matériel en Python en 15 minutes. Ce guide vous accompagne dans l'écriture d'un test fonctionnel avec OpenHTF et TofuPilot qui mesure des tensions, vérifie des limites et enregistre les résultats automatiquement. Pas de LabVIEW, pas de TestStand, pas de frais de licence.

Prérequis

  • Python 3.9+
  • pip (gestionnaire de paquets Python)

Étape 1 : Installer les dépendances

install.sh
pip install openhtf tofupilot

OpenHTF est le framework de test matériel open source de Google. TofuPilot le connecte à un tableau de bord cloud pour l'analytique, la traçabilité et le suivi du rendement.

Étape 2 : Écrire votre première phase de test

Une phase de test est une fonction Python qui prend des mesures. OpenHTF gère la structure : vous déclarez ce que vous mesurez, définissez les limites et écrivez la logique.

first_test.py
import openhtf as htf
from openhtf.util import units

@htf.measures(
    htf.Measurement("voltage_3v3")
    .in_range(3.2, 3.4)
    .with_units(units.VOLT)
    .doc("Tension du rail 3.3V"),
)
@htf.PhaseOptions(timeout_s=10)
def test_voltage(test):
    test.measurements.voltage_3v3 = 3.31  # Remplacer par une vraie lecture d'instrument

Le décorateur @htf.measures définit ce que cette phase enregistre. .in_range(3.2, 3.4) définit les limites de réussite/échec. .with_units() ajoute les unités pour l'analytique. La phase réussit si la valeur est dans la plage.

Étape 3 : Ajouter plusieurs mesures

Une seule phase peut mesurer plusieurs choses. C'est utile pour tester tous les rails d'alimentation en une seule étape.

multi_measurement.py
import openhtf as htf
from openhtf.util import units

@htf.measures(
    htf.Measurement("voltage_3v3")
    .in_range(3.2, 3.4)
    .with_units(units.VOLT)
    .doc("Rail 3.3V"),
    htf.Measurement("voltage_5v0")
    .in_range(4.8, 5.2)
    .with_units(units.VOLT)
    .doc("Rail 5.0V"),
    htf.Measurement("board_current")
    .in_range(0.05, 0.25)
    .with_units(units.AMPERE)
    .doc("Courant total consommé par la carte"),
)
def test_power_rails(test):
    test.measurements.voltage_3v3 = 3.31
    test.measurements.voltage_5v0 = 5.02
    test.measurements.board_current = 0.12

Étape 4 : Utiliser un Plug pour le contrôle d'instruments

Les Plugs gèrent les connexions aux instruments. OpenHTF appelle setUp() avant les tests et tearDown() après, pour que vos instruments se connectent et se déconnectent automatiquement. Les Plugs sont injectés dans les phases via le décorateur @htf.plug().

plug_example.py
import openhtf as htf
from openhtf.plugs import BasePlug
from openhtf.util import units


class MultimeterPlug(BasePlug):
    \"\"\"Gère le cycle de vie de la connexion au multimètre.\"\"\"

    def setUp(self):
        # Remplacer par une vraie connexion à l'instrument
        self._readings = iter([3.31, 5.02, 0.12])

    def read_dc_voltage(self) -> float:
        return next(self._readings)

    def read_dc_current(self) -> float:
        return next(self._readings)

    def tearDown(self):
        pass  # Remplacer par la déconnexion de l'instrument


@htf.measures(
    htf.Measurement("rail_3v3")
    .in_range(3.2, 3.4)
    .with_units(units.VOLT),
)
@htf.plug(dmm=MultimeterPlug)
def test_with_instrument(test, dmm):
    test.measurements.rail_3v3 = dmm.read_dc_voltage()

Le décorateur @htf.plug(dmm=MultimeterPlug) indique à OpenHTF de créer une instance de MultimeterPlug et de la passer comme argument dmm. N'utilisez pas les annotations de type pour l'injection de plug (ex. dmm: MultimeterPlug). Le décorateur @htf.plug() est obligatoire.

Étape 5 : Ajouter différents types de mesures

OpenHTF prend en charge les plages numériques, les correspondances exactes et les vérifications booléennes.

measurement_types.py
import openhtf as htf
from openhtf.util import units

# Booléen : réussit si True
@htf.measures(
    htf.Measurement("led_on").equals(True).doc("La LED d'alimentation est allumée"),
)
def test_led(test):
    test.measurements.led_on = True

# Chaîne : réussit si correspondance exacte
@htf.measures(
    htf.Measurement("firmware_version").equals("2.1.0").doc("Firmware attendu"),
)
def test_firmware(test):
    test.measurements.firmware_version = "2.1.0"

# Plage numérique : réussit si dans les limites
@htf.measures(
    htf.Measurement("temperature")
    .in_range(20, 30)
    .with_units(units.DEGREE_CELSIUS)
    .doc("Température de la carte"),
)
def test_temperature(test):
    test.measurements.temperature = 24.5
ValidateurCas d'utilisationExemple
.in_range(low, high)Numérique dans les limitesTension, courant, résistance
.equals(value)Correspondance exacteVersion firmware, indicateurs booléens
.with_units(unit)Attacher une unité pour l'analytiqueunits.VOLT, units.AMPERE
.doc(text)Description pour les rapportsAffiché dans le tableau de bord TofuPilot

Étape 6 : Assembler et exécuter le test

Connectez les phases dans un test, ajoutez TofuPilot pour l'enregistrement cloud, et lancez.

full_test.py
import openhtf as htf
from openhtf.plugs import BasePlug
from openhtf.util import units
from tofupilot.openhtf import TofuPilot


class MultimeterPlug(BasePlug):
    def setUp(self):
        self._readings = iter([3.31, 5.02, 0.12])

    def read_dc_voltage(self) -> float:
        return next(self._readings)

    def read_dc_current(self) -> float:
        return next(self._readings)

    def tearDown(self):
        pass


@htf.measures(
    htf.Measurement("voltage_3v3")
    .in_range(3.2, 3.4)
    .with_units(units.VOLT)
    .doc("Rail 3.3V"),
    htf.Measurement("voltage_5v0")
    .in_range(4.8, 5.2)
    .with_units(units.VOLT)
    .doc("Rail 5.0V"),
    htf.Measurement("board_current")
    .in_range(0.05, 0.25)
    .with_units(units.AMPERE)
    .doc("Courant consommé par la carte"),
)
@htf.plug(dmm=MultimeterPlug)
def test_power(test, dmm):
    test.measurements.voltage_3v3 = dmm.read_dc_voltage()
    test.measurements.voltage_5v0 = dmm.read_dc_voltage()
    test.measurements.board_current = dmm.read_dc_current()


@htf.measures(
    htf.Measurement("led_on").equals(True),
)
def test_led(test):
    test.measurements.led_on = True


@htf.measures(
    htf.Measurement("firmware_version").equals("2.1.0"),
)
def test_firmware(test):
    test.measurements.firmware_version = "2.1.0"


def main():
    test = htf.Test(
        test_power,
        test_led,
        test_firmware,
        procedure_id="FCT-001",
        part_number="PCBA-100",
    )
    with TofuPilot(test):
        test.execute(test_start=lambda: input("Scanner le numéro de série : "))


if __name__ == "__main__":
    main()

Lorsque vous exécutez ce script, OpenHTF demande un numéro de série, exécute chaque phase dans l'ordre, vérifie les mesures par rapport aux limites, et TofuPilot télécharge les résultats. Vous obtenez FPY, Cpk et graphiques de contrôle dans le tableau de bord sans aucun code supplémentaire.

Ce qui se passe en coulisses

ÉtapeQui le faitCe qui se passe
Saisie du numéro de sérieOpenHTFL'opérateur scanne ou saisit le numéro de série du DUT
Exécution des phasesOpenHTFExécute test_power, test_led, test_firmware dans l'ordre
Validation des mesuresOpenHTFVérifie chaque valeur par rapport aux limites déclarées
Téléchargement des résultatsTofuPilotEnvoie mesures, limites, unités, résultat dans le cloud
AnalytiqueTofuPilotFPY, Cpk, graphiques de contrôle, Pareto des défaillances mis à jour automatiquement

Plus de guides

Mettez ce guide en pratique