Back to blog
Ali KamalyAli Kamaly
October 22, 2026
15 min read
Hardware Validation

Battery Test Automation in 2026 (Capacity, Discharge, IR on a Bench)

How to characterise a lithium-ion cell with a bench supply, an electronic load, and a DMM: CC-CV charge, capacity and discharge curves, the IEC 61960 DC pulse method for internal resistance, hardware and software abort limits, and when a dedicated battery cycler is the better buy.

Battery Test Automation in 2026 (Capacity, Discharge, IR on a Bench)

Battery test automation on a bench means scripting a programmable power supply, an electronic load, and a DMM or SMU to charge a cell in constant current then constant voltage, discharge it at a set current to its cut-off voltage, log the curve, compute capacity and internal resistance, and stop the moment any safety limit is crossed. Three instruments cover a single cell: the supply charges, the load discharges, and a 6½-digit DMM reads the cell voltage at its tabs. You can script that in Python with PyVISA, or describe it in a sentence to an AI agent such as TestFlow (testflowinc.com), which builds the same sequence and writes the report from the logged data.

This guide is for hardware, power, and validation engineers who need capacity, discharge curves, and internal resistance on a handful of cells before a dedicated cycler is justified. You get the bench, the wiring, the abort limits, real SCPI for a Keysight E36313A, EL34143A, and 34465A, the IEC 61960 DC pulse method in code, and an honest answer on when to buy a battery cycler instead.

The bench for battery characterisation

A single-cell characterisation bench needs four roles, and a Li-ion 18650 sits comfortably inside common bench instrument ratings. The examples below use a Molicel INR-18650-P28A because its datasheet states every number the test needs.

Datasheet item (Molicel P28A)Value
Capacity2,800 mAh typical, 2,600 mAh minimum
Nominal voltage3.6 V
ChargeCC-CV to 4.2 V, 50 mA cut-off at 23 °C, standard 2.8 A, maximum 6.0 A
Discharge cut-off2.5 V
Maximum discharge current35 A
Internal resistanceAC 1 kHz 20 mΩ maximum, DC (10 A, 1 s) 20 mΩ
Temperaturecharge 0 to 60 °C, discharge -40 to 60 °C

The instruments, with list prices from the vendors' sites as of October 2026:

RoleModelWhy it fitsList price
ChargerKeysight E36313A output 16 V, 10 A, remote senseUS$2,609
DischargerKeysight EL34143A150 V, 60 A, 350 W, built-in battery test subsystemUS$3,128
Cell voltageKeysight 34465A6½ digits, Kelvin leads at the tabsUS$2,075
Temperaturesecond 34465Athermocouple input (34465A and 34470A only)US$2,075

One SMU can replace the supply and load for low currents. The Keithley 2450 sources and sinks in four quadrants up to ±1.05 A at 20 V, and the Keithley 2460 reaches 7.35 A at 7.35 V, at list prices of US$8,630 and US$13,700 on tek.com as of October 2026. For a 2.8 Ah cell, a 1 A ceiling means a capacity run takes hours longer than with a separate load, so the supply-plus-load bench is the usual choice above about 1 A.

Wiring a cell so the numbers mean something

Battery measurements are millivolt measurements on milliohm paths, so the wiring decides the result. A 20 mΩ cell carrying 2.6 A drops 52 mV across its own resistance, and a holder or lead with the same resistance doubles the apparent drop.

Four rules for a single-cell fixture:

  1. 1

    Voltage leads at the cell tabs, separate from the current leads. IEC 61960-3 specifies exactly this for internal resistance: voltage sensed at the terminals, independent of the current-carrying contacts.

  2. 2

    A series diode between the supply and the cell. Keysight's E36300 user's guide warns that if over-voltage protection trips with a battery across the output, the battery's current sinks through the supply's internal circuitry and can damage it, and it says a diode must be connected in series.

  3. 3

    Supply remote sense at the cell, after the diode. VOLT:SENS:SOUR EXT, (@1) moves regulation to the cell terminals, so the diode's forward drop sits inside the loop. The E36300 data sheet lists 1 V as the maximum load-lead drop for remote sense, which a Schottky diode at these currents fits within.

  4. 4

    Load remote sense at the cell with VOLT:SENS:SOUR EXT, (@1) on the EL34143A, so its cut-off voltage is judged at the tabs rather than after the lead drop.

The supply and the load can stay wired to the cell together. The diode blocks the cell from the supply during discharge, and the EL34143A's input-off impedance of 824 kΩ (per the EL30000 data sheet) draws about 5 µA at 4.2 V while it waits. The VI curve sweep guide covers the same 4-wire principle for a resistive DUT.

Safety limits and abort conditions

A battery test needs limits that hold even if the PC crashes, so set hardware cut-offs in the instruments first and software checks second. The script is a monitor, not the last line of defence.

ConditionHardware layerSoftware abort (example limit)Source of the number
Over-voltage on chargeSupply OVP at 5.0 V on output 1Cell above 4.25 V on the DMMDatasheet charge voltage 4.2 V
Under-voltage on dischargeBATT:CUTO:VOLT 2.5 on the loadCell below 2.45 V on the DMMDatasheet cut-off 2.5 V
Over-temperaturenone on these instrumentsCell surface above 45 °CDatasheet maximum 60 °C, example margin
Charge runaway timenoneCharge longer than 4 h at 1.4 ADatasheet standard charge 1.5 h at 2.8 A
Discharge runaway timeBATT:CUTO:TIM on the loadDischarge longer than 7 h at 0.52 A2.8 Ah at 0.52 A is about 5.4 h
Lost communicationOVP and load cut-offs still activethe finally block turns everything offnone

Every software limit in that table is an example for this cell, not a measured result and not a universal value. Derive yours from the cell's datasheet and your lab's safety rules. Physical protection matters as much as code: a fuse in series with the cell sized for your maximum test current, and a fire-safe container for unattended runs.

The E36313A's OVP on output 1 is programmable from 0.5 V to 6.6 V with VOLT:PROT <v>, (@1), and it is always active rather than switchable. The EL34143A's battery subsystem stops the discharge itself when the cell voltage falls below BATT:CUTO:VOLT, a timer set by BATT:CUTO:TIM expires, or a capacity set by BATT:CUTO:CAP has been drawn, per the EL30000 programming guide. Use the battery subsystem's cut-off rather than the load's VOLT:INH:VON setting: in its LIVE mode Von turns the input back on when the voltage recovers, and a resting cell's voltage always recovers.

Capacity and discharge curve in Python

A capacity test is a charge, a rest, and a discharge, with the cell voltage, current, and temperature logged throughout. This script runs one cycle on the P28A at a 1.4 A charge and a 0.52 A discharge (0.2 It against the 2,600 mAh minimum capacity), integrates capacity, and writes the discharge curve to CSV.

"""One capacity cycle on a single Li-ion cell.

E36313A output 1 charges through a series diode with remote sense at the
cell; EL34143A discharges with remote sense at the cell; 34465A #1 reads
cell voltage at the tabs; 34465A #2 reads a type K thermocouple on the can.
"""
import csv
import time

import pyvisa

V_CHARGE, I_CHARGE, I_TERM = 4.20, 1.4, 0.050     # datasheet CC-CV, 50 mA cut
I_DISCHARGE, V_CUTOFF = 0.52, 2.50                # 0.2 It, datasheet cut-off
ABORT_V_HIGH, ABORT_V_LOW, ABORT_T = 4.25, 2.45, 45.0   # example limits
CHARGE_MAX_S, DISCHARGE_MAX_S, REST_S = 4 * 3600, 7 * 3600, 3600
LOG_EVERY_S = 10

rm = pyvisa.ResourceManager()
psu = rm.open_resource("TCPIP0::192.168.1.10::inst0::INSTR")
load = rm.open_resource("TCPIP0::192.168.1.11::inst0::INSTR")
dmm_v = rm.open_resource("TCPIP0::192.168.1.12::inst0::INSTR")
dmm_t = rm.open_resource("TCPIP0::192.168.1.13::inst0::INSTR")
for inst in (psu, load, dmm_v, dmm_t):
    inst.timeout = 10000
    inst.write("*RST")

dmm_v.write("CONF:VOLT:DC 10")
dmm_v.write("VOLT:DC:NPLC 10")
dmm_t.write("CONF:TEMP TC,K")
dmm_t.write("UNIT:TEMP C")

psu.write("VOLT:SENS:SOUR EXT, (@1)")
psu.write("VOLT:PROT 5.0, (@1)")
psu.write(f"CURR {I_CHARGE}, (@1)")
psu.write(f"VOLT {V_CHARGE}, (@1)")

load.write("FUNC CURR, (@1)")
load.write("VOLT:SENS:SOUR EXT, (@1)")
load.write("CURR:RANG 3, (@1)")
load.write(f"CURR {I_DISCHARGE}, (@1)")
load.write(f"BATT:CUTO:VOLT {V_CUTOFF}, (@1)")
load.write("BATT:CUTO:VOLT:STAT ON, (@1)")
load.write(f"BATT:CUTO:TIM {DISCHARGE_MAX_S}, (@1)")
load.write("BATT:CUTO:TIM:STAT ON, (@1)")


def sample():
    v = float(dmm_v.query("READ?"))
    t = float(dmm_t.query("READ?"))
    if v > ABORT_V_HIGH or v < ABORT_V_LOW or t > ABORT_T:
        raise RuntimeError(f"abort: cell {v:.3f} V, {t:.1f} C")
    return v, t


curve, ah = [], 0.0
try:
    # 1. CC-CV charge until the taper current falls below 50 mA.
    psu.write("OUTP ON, (@1)")
    start = time.monotonic()
    while True:
        time.sleep(LOG_EVERY_S)
        v, t = sample()
        i = float(psu.query("MEAS:CURR? (@1)"))
        if i < I_TERM:
            break
        if time.monotonic() - start > CHARGE_MAX_S:
            raise RuntimeError("abort: charge timeout")
    psu.write("OUTP OFF, (@1)")

    # 2. Rest so the cell voltage relaxes before discharge.
    time.sleep(REST_S)

    # 3. CC discharge; the load's battery cut-off ends it at 2.5 V.
    load.write("BATT ON, (@1)")
    load.write("INP ON, (@1)")
    start = last = time.monotonic()
    while True:
        time.sleep(LOG_EVERY_S)
        now = time.monotonic()
        i = float(load.query("MEAS:CURR? (@1)"))
        v, t = sample()
        ah += i * (now - last) / 3600
        last = now
        curve.append((round(now - start, 1), v, i, t, round(ah, 4)))
        if v <= V_CUTOFF or i < 0.1 * I_DISCHARGE:   # cut-off reached
            break
    load_ah = float(load.query("BATT:MEAS:CAP? (@1)"))
finally:
    load.write("INP OFF, (@1)")
    psu.write("OUTP OFF, (@1)")

with open("discharge.csv", "w", newline="") as f:
    w = csv.writer(f)
    w.writerow(["t_s", "cell_V", "load_A", "temp_C", "ah"])
    w.writerows(curve)

print(f"capacity: {ah * 1000:.0f} mAh integrated, {load_ah * 1000:.0f} mAh from the load")

Two capacity numbers come out, and they should agree within a few milliamp-hours: the script's own integration and the load's BATT:MEAS:CAP?. If they disagree, the logging interval is too coarse or a reading was missed. The charge termination is coarser: output 1 specifies current readback as 0.05% + 5 mA, so the 50 mA cut-off is judged to about ±10%, which shifts the end of charge by minutes, not by meaningful capacity. The datasheet's 2,600 mAh minimum is a reasonable example limit, but check the discharge current and temperature the datasheet rates capacity at before you grade against it, because capacity falls as current rises.

The sample() function runs on every log point in both phases, so a cell that heats or drifts out of its window ends the run within one interval. The multimeter automation guide covers the DMM side, including why CONF must come before any NPLC setting.

Internal resistance by the IEC 61960 DC pulse method

DC internal resistance on a bench follows IEC 61960-3, clause 7.7.3: discharge at a constant 0.2 It for 10 s ± 0.1 s and record U1, then immediately step to 1.0 It for 1 s ± 0.1 s and record U2. The resistance is R = (U1 − U2) / (I2 − I1). The wording is in the PS IEC 61960-3 national adoption, and Arbin's IEC 61960 procedure matches it. The standard preconditions the cell with a charge and 1 to 4 h of storage at 20 °C ± 5 °C.

It is the rated capacity divided by one hour. Against the P28A's 2,600 mAh minimum, I1 is 0.52 A and I2 is 2.6 A.

import time

import pyvisa

I1, I2 = 0.52, 2.6                     # 0.2 It and 1.0 It for 2.6 Ah

rm = pyvisa.ResourceManager()
load = rm.open_resource("TCPIP0::192.168.1.11::inst0::INSTR")
dmm = rm.open_resource("TCPIP0::192.168.1.12::inst0::INSTR")

dmm.write("*RST")
dmm.write("CONF:VOLT:DC 10")
dmm.write("VOLT:DC:NPLC 1")            # 20 ms integration keeps U1/U2 on time

load.write("*RST")
load.write("FUNC CURR, (@1)")
load.write("VOLT:SENS:SOUR EXT, (@1)")
load.write("CURR:RANG 3, (@1)")        # one range for both levels
load.write(f"CURR {I1}, (@1)")

try:
    load.write("INP ON, (@1)")
    t0 = time.monotonic()
    time.sleep(max(0.0, t0 + 9.97 - time.monotonic()))
    u1 = float(dmm.query("READ?"))
    i1 = float(load.query("MEAS:CURR? (@1)"))
    load.write(f"CURR {I2}, (@1)")     # same range, so the input stays on
    t1 = time.monotonic()
    time.sleep(max(0.0, t1 + 0.97 - time.monotonic()))
    u2 = float(dmm.query("READ?"))
    i2 = float(load.query("MEAS:CURR? (@1)"))
finally:
    load.write("INP OFF, (@1)")

r_dc = (u1 - u2) / (i2 - i1)
print(f"U1 {u1:.5f} V  U2 {u2:.5f} V  R_dc {r_dc * 1000:.2f} mOhm")

Both current levels sit inside the EL34143A's medium range, which the guide says to choose once, because a range change briefly drops the input and would break the pulse. Software timing with time.sleep holds well inside the standard's ± 0.1 s window on a desktop PC, but it is not deterministic; for tighter timing, use the load's own transient or LIST system.

Do not grade an IEC number against the P28A's "DC (10 A, 1 s) 20 mΩ" line. That datasheet figure uses a 10 A pulse, a different method, so treat it as context, not a limit. The AC method in clause 7.7.2 measures at 1.0 kHz ± 0.1 kHz with a current chosen to keep the peak voltage under 20 mV, and the standard notes that it measures impedance. A dedicated meter such as the Hioki BT3562A, which measures at 1 kHz, is listed at €3,098 excluding VAT on Hioki's EU shop as of October 2026.

Instruments with battery test built in

Some bench instruments package part of this sequence in firmware, which shortens the script without changing the method.

  • •Keysight EL34143A battery subsystem. BATT ON with voltage, capacity, and timer cut-offs, and BATT:MEAS:CAP? and BATT:MEAS:TIM? for results. It handles the discharge and its end condition; charging and limits on temperature stay with you.
  • •Keithley 2281S-20-6. A 20 V, 6 A, 120 W supply that sinks up to 1 A. Its data sheet describes a battery test function with charge current from 0 to 6 A and a maximum discharge current of 1 A, which computes capacity in Ah and equivalent series resistance and generates a battery model. Tektronix lists it at US$5,010 on the 2281S product page as of October 2026. The 1 A discharge ceiling makes it a model-building tool more than a capacity tester for large cells.
  • •Chroma 63600 loads. The 63600 data sheet describes a timing function from 2 ms to 100,000 s with final-voltage and timeout settings for battery discharge testing.

Four ways to automate battery testing in 2026

The options split by scale: bench characterisation of a few cells, or production and long-term cycling of many.

1. Python and PyVISA (free, you write it)

PyVISA is MIT licensed, and version 1.16.2 shipped on February 27, 2026. Every script on this page runs on it. You own the sequencing, the abort logic, the logging, and the report, and you also own the job of making sure a crashed script leaves the cell in a safe state. The PyVISA tutorial covers setup, and the data logger without LabVIEW guide covers long logging runs.

2. TestFlow

TestFlow (testflowinc.com) is an AI agent for electronics testing: you describe the test, the agent builds the workflow and Python, runs it on your bench, and writes the report from measured results. Free to start, then $39 or $149 a month per seat as of October 2026. Bench runs need the Windows desktop app. Not a production battery cycler, and not BMS HIL.

The capacity cycle above, described in one sentence:

> "Charge the cell on E36313A output 1 at 1.4 A to 4.2 V until the current drops below 50 mA, rest one hour, discharge on the EL34143A at 0.52 A to 2.5 V, log cell voltage and thermocouple temperature from the two 34465As every 10 s, abort above 4.25 V or 45 °C, and report capacity against 2,600 mAh."

The agent builds a reviewable workflow of steps (configure, charge, rest, discharge, log, compute) plus the generated Python with the SCPI for those models, and the Windows desktop app runs it on the real instruments. The report charts the discharge curve with a PASS or FAIL per reading, built from the run's results; the agent writes limits, never measurements, and will not widen a limit to make a cell pass (trust guide). The generated Python exports as a standalone package you own (generated code guide).

TestFlow fits cell and small-pack characterisation on instruments you already have. It does not replace a multi-channel cycler for weeks of unattended cycling, it does not do deterministic real-time timing, and it is not a hardware-in-the-loop system for BMS validation; the HIL testing software comparison covers that category. It drives SCPI bench instruments, not DAQ cards. See pricing and the instrument catalog.

Best for
Teams that want automation without writing VIs or drivers
Cost
Free to start. Engineer $39 a month, Lab $149 a month
Tradeoff
Runs on your bench through the Windows desktop app
TestFlow: the agent's chat, the workflow it built, and the script for a load-transient test

3. The instruments' built-in battery functions

The EL34143A battery subsystem and the Keithley 2281S battery test function, described above, run part of the sequence with no PC at all. You give up the charge-discharge sequencing across instruments, the temperature abort, and the report.

4. A dedicated battery cycler

A battery cycler is the right purchase when the test is many cells, many cycles, or pack-level power. The vendors below publish no prices; every one sells by quote as of October 2026.

VendorExample lineScale (from the vendor's page)
ArbinLBTS-Cell, RBT-Cell, RBT-Pack4 to 256 channels per cell system, packs to 1,500 V; MITS Pro software
MaccorSeries 40001 to 96 channels, up to 1,400 A and 14,400 W
BioLogicBCS-900 series8 channels per module, ±150 mA to ±15 A (BCS-915), EIS option
Chroma17011 cells, 17020 and 17040 packs17020 regenerative, 600 W to 60 kW per channel
NewareCT-4008Q-5V6A-S18 channels, 5 V, 6 A, 30 W per channel

Several of these build the methods on this page into the software: BioLogic's BT-Lab task list includes DCIR, and Chroma's 17011 data sheet describes DCIR modes that comply with IEC 61960. Buy one when you need channel count, regenerative discharge, formation and grading, or months of unattended cycle-life data. Keep the bench approach for the first cells, the fixture debug, and the one-off characterisation that does not justify a cycler.

NeedBench + PythonTestFlowBuilt-in instrument functionBattery cycler
One to a few cellsYesYesYesOverkill
Dozens of cells in parallelHardHardNoYes
Weeks of cycle-life dataFragileFragileNoYes
Regenerative pack dischargeNoNoNoYes
Custom limits and reportYou write itBuilt from the runNoVendor software
Cost as of Oct 2026Free softwareFree version, then $39 or $149 a monthIncludedBy quote

Common mistakes in bench battery testing

Most wrong battery numbers trace back to setup, not to the cell.

  • •Measuring voltage on the current leads. Every milliohm of lead adds to the internal resistance you report.
  • •No diode between the supply and the cell. Keysight's guide is explicit that an OVP trip with a battery attached can damage the supply.
  • •Using Von as the end-of-discharge condition. In LIVE mode the load turns back on as the cell relaxes, so the discharge never really ends.
  • •Changing load range mid-pulse. The input drops for the range change and the IR pulse is invalid.
  • •Trusting the script as the only protection. OVP and the load's battery cut-off keep working when Python does not.
  • •Comparing IR numbers from different methods. IEC 0.2 It and 1.0 It, a 10 A pulse, and 1 kHz AC give different numbers for the same cell.

The automated test report generation guide covers turning the CSV into a report that cites where each number came from.

Where TestFlow fits

Bench battery characterisation is slow, repetitive, and unforgiving of a script that stops watching. It is exactly the kind of sequence worth describing once and running the same way every time.

  1. 1

    Connect your instruments. Pick the manufacturer and model, paste the VISA address (USB, LAN, GPIB, or serial), and the agent knows what is on your bench. No bench yet? Use a placeholder address, build the full automation, and swap in the real address when you are in the lab.

  2. 2

    Tell the agent what to test. For example, "run a VI sweep from 1 to 10 V in 1 V steps at 0.5 A load current," or "suggest the tests for a power-management device."

  3. 3

    The agent builds the complete workflow in seconds. Instrument-aware automation appears on the canvas, with the generated scripts visible in a code panel you can inspect and edit.

  4. 4

    Run it in your lab. Click Run in the TestFlow desktop app for Windows and the status panel streams results step by step, with measured values inline (VOUT = 3.301 V, asserted 3.2 to 3.4 V, PASS). One click exports a structured PDF report, or the raw results as CSV.

The TestFlow builder: a one-line test request on the left, the generated instrument workflow in the centre, and the live run with its streaming SCPI execution log on the right.
The TestFlow agent turning a one-line test request into a runnable workflow, then running it on the bench. Click to enlarge.
  • Vendor-neutral by design. One workflow drives Keysight, Tektronix, Rohde & Schwarz, Rigol, Keithley, Anritsu, and any other SCPI instrument over standard VISA.
  • Built in the browser, run on the bench. Workflows live in your workspace, so a sequence built in one lab runs the same way in another. Bench runs use the Windows desktop app.
  • Free version to start. Sign in at app.testflowinc.com and build your first workflow today; plans and quotes are on the pricing page.
Instrument vendors TestFlow drives over VISA and SCPI: Keysight, Tektronix, Rohde & Schwarz, NI, Keithley, Agilent, Anritsu, Siglent, Chroma, Fluke, Yokogawa, Kikusui, TDK-Lambda, ESPEC, Watlow, Pickering, Copper Mountain, inTEST, Thermonics, and Microchip
Works with the instruments already on your bench. Full list on the supported instruments page.

The step-by-step walkthrough, VISA address formats, and Test Planner prompts are all in the TestFlow product guide.

Frequently asked questions

Can I test battery capacity with a bench power supply and an electronic load?

Yes, for cell-level characterisation. Charge with the supply in CC-CV through a series diode, rest, then discharge with the electronic load in constant current to the cell's cut-off voltage while a DMM logs the cell voltage at the tabs. Capacity is the integrated current, and loads such as the Keysight EL34143A also report it with BATT:MEAS:CAP?.

How is DC internal resistance measured on a battery?

IEC 61960-3 discharges the cell at 0.2 It for 10 s and records U1, then steps to 1.0 It for 1 s and records U2. The DC resistance is (U1 - U2) / (I2 - I1), with voltage sensed at the cell terminals on separate leads from the current.

When should I buy a battery cycler instead of using bench instruments?

When you need many channels in parallel, weeks of unattended cycling, regenerative discharge at module or pack level, or formation and grading. Arbin, Maccor, BioLogic, Chroma, and Neware build dedicated cyclers for that work, all sold by quote as of October 2026.

Can TestFlow automate battery testing?

TestFlow automates bench characterisation: describe the charge, discharge, or internal resistance test in a sentence, and the agent builds the workflow and Python with the SCPI for your supply, load, and meters, runs it from the Windows desktop app, and reports from the logged data. It is not a production battery cycler or a BMS HIL system.

Why do I need a diode between a power supply and a battery?

Keysight's E36300 user's guide warns that if over-voltage protection trips with a battery across the output, current from the battery can sink through the supply's internal circuitry and damage it, and it says a diode must be connected in series with the output.

TestFlow

Automate every instrument in the lab,
Create test workflows in minutes

  1. 01Describe the testIn a sentence, the way you would tell a colleague.
  2. 02The agent builds itWorkflow and script for your instruments, any vendor.
  3. 03Run it, get the reportOn your bench, with the measured values.

Tags

battery test automationbattery capacity test pythonbattery discharge test electronic loadinternal resistance dc pulse methodiec 61960 internal resistanceli-ion cell characterization benchbattery cycler vs bench instrumentskeysight el34143a battery testkeithley 2281s battery test18650 capacity test
Share this article:
Ali Kamaly

Article by

Ali Kamaly

Ali Kamaly is the Co-Founder and CEO of TestFlow, an AI-native platform for electronics test automation. He writes about test automation, lab validation, and the infrastructure behind modern hardware engineering.

Your next test, automated today

Describe the test. TestFlow builds the workflow, runs it on your instruments, and writes the report. Free to start, no card needed.