> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lagerdata.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Your First Test

> A complete walkthrough of testing a device with Lager

This guide walks you through a complete test workflow, in Python or in Rust. It starts at connectivity and ends at an automated test. At the end, you can use the CLI interactively and write your own Lager test scripts.

<Note>
  First complete the [Getting Started](/source/getting-started/overview) guide. This tutorial assumes that you installed the CLI, added your box, and configured your instruments with nets.
</Note>

***

## Part 1: CLI Walkthrough

Let's step through a typical test flow using individual CLI commands. This is useful for ad-hoc testing, debugging, and getting familiar with your setup.

### Step 1: Verify your box is online

```bash theme={null}
lager hello --box my-lager-box
```

**Expected output:**

```
my-lager-box says hello!
```

### Step 2: Check connected instruments

```bash theme={null}
lager instruments --box my-lager-box
```

This shows all instruments the box can see. Confirm your power supply, debug probe, and any other instruments appear.

### Step 3: View your configured nets

```bash theme={null}
lager nets --box my-lager-box
```

This shows the named nets you'll use in subsequent commands. Note the net names -- you'll need them below.

### Step 4: Set defaults to reduce typing

```bash theme={null}
lager defaults add --box my-lager-box
lager defaults add --supply-net POWER
lager defaults add --debug-net DEBUG_NET
```

With defaults set, you can omit `--box` and net names from subsequent commands.

### Step 5: Flash firmware

```bash theme={null}
lager debug flash --hex firmware.hex
```

**Expected output:**

```
Flashing firmware.hex to target...
Flash complete. 32768 bytes written.
```

### Step 6: Power on your device

```bash theme={null}
# Set voltage with protection thresholds
lager supply voltage 3.3 --ovp 3.6 --ocp 0.5 --yes

# Enable the output
lager supply enable --yes
```

### Step 7: Take a measurement

```bash theme={null}
lager adc SENSOR_1
```

**Expected output:**

```
ADC 'SENSOR_1': 2.450000 V
```

### Step 8: Power down

```bash theme={null}
lager supply disable --yes
```

Always disable power supplies when you're done testing.

***

## Part 2: Your First Test Script

Now convert the manual CLI steps into a repeatable test. A script always cleans up after itself and disables power, even when an error occurs.

You can write it in Python, which runs on the box through `lager python`. You can also write it in Rust, as an ordinary `cargo test` in your firmware repository that uses the [`lager-net` crate](/source/reference/rust/overview). Both versions below flash, power on, measure, assert, and clean up.

<CodeGroup>
  ```python my_first_test.py theme={null}
  from lager import Net, NetType

  def main():
      # Get our nets
      psu = Net.get('POWER', type=NetType.PowerSupply)
      debug = Net.get('DEBUG_NET', type=NetType.Debug)
      sensor = Net.get('SENSOR_1', type=NetType.ADC)

      try:
          # Flash firmware
          print("Flashing firmware...")
          debug.connect()
          debug.flash(['firmware.hex'])
          debug.reset()
          print("Flash complete.")

          # Power on the DUT
          print("Enabling power supply at 3.3V...")
          psu.set_voltage(3.3)
          psu.set_current(0.5)
          psu.enable()
          print("Power enabled.")

          # Take a measurement
          voltage = sensor.input()
          print(f"Sensor reading: {voltage:.4f} V")

          # Check the result
          if 2.0 <= voltage <= 3.0:
              print("PASS: Sensor voltage within expected range.")
          else:
              print(f"FAIL: Sensor voltage {voltage:.4f}V outside range [2.0, 3.0]")

      finally:
          # Always clean up, even if an error occurs
          print("Disabling power supply...")
          psu.disable()
          print("Done.")

  if __name__ == '__main__':
      main()
  ```

  ```rust tests/my_first_test.rs theme={null}
  use lager::LagerBox;

  #[test]
  fn sensor_reads_in_range_after_boot() -> lager::Result<()> {
      // Reads LAGER_BOX_HOST from the environment.
      let lager = LagerBox::from_env()?;
      let psu = lager.supply("POWER");
      let debug = lager.debug("DEBUG_NET");
      let sensor = lager.adc("SENSOR_1");

      // Flash firmware
      println!("Flashing firmware...");
      debug.connect()?;
      debug.flash("firmware.hex")?;
      debug.reset(false)?;
      println!("Flash complete.");

      // Power on the DUT
      println!("Enabling power supply at 3.3V...");
      psu.set_voltage(3.3)?;
      psu.set_current(0.5)?;
      psu.enable()?;
      println!("Power enabled.");

      // Take a measurement and check the result; disable power before
      // asserting so the DUT is never left energized by a failing test.
      let voltage = sensor.read()?;
      println!("Sensor reading: {voltage:.4} V");
      psu.disable()?;

      assert!(
          (2.0..=3.0).contains(&voltage),
          "sensor voltage {voltage:.4} V outside range [2.0, 3.0]"
      );
      Ok(())
  }
  ```
</CodeGroup>

<Note>
  Cleanup protects your hardware, so both versions do it. The Python version uses `try/finally`, which disables the power supply even when an error occurs. The Rust version disables power before its assertion. An earlier `?` error also ends the test, and the failure shows the state of the supply.
</Note>

***

## Part 3: Running It

Execute the Python script on your Lager Box:

```bash theme={null}
lager python my_first_test.py --box my-lager-box
```

Or run the Rust test from your project (with `lager = { package = "lager-net", version = "0.4" }` in `[dev-dependencies]`):

```bash theme={null}
LAGER_BOX_HOST=<box-ip> cargo test
```

**Expected output (Python):**

```
Flashing firmware...
Flash complete.
Enabling power supply at 3.3V...
Power enabled.
Sensor reading: 2.4500 V
PASS: Sensor voltage within expected range.
Disabling power supply...
Done.
```

If you need to send additional files along with your script (firmware binaries, config files), use `--add-file`:

```bash theme={null}
lager python my_first_test.py --box my-lager-box --add-file firmware.hex
```

***

## What's Next

You've completed your first test with Lager. Here are some directions to explore:

* **[CLI Reference](/source/reference/cli/overview)** -- Full documentation for every CLI command
* **[Python API](/source/reference/python/overview)** -- Complete Python SDK reference
* **[Rust API](/source/reference/rust/overview)** -- Write your HIL suite as `cargo test` integration tests
* **[Troubleshooting](/source/getting-started/troubleshooting)** -- Solutions when things go wrong
* **[Glossary](/source/getting-started/glossary)** -- Definitions for technical terms used in the docs

The [demo script](https://github.com/lagerdata/lager/blob/main/docs/examples/demo_script.py) is a larger example. It combines robot arm control, USB hub power cycling, debug probe flashing, and ADC measurement.
