# Testing

## Overview

Testing PyFTDI is challenging because it relies on several pieces of hardware:

- one or more FTDI device

- I2C, SPI, JTAG bus slaves or communication equipment for UART

The `tests` directory contain several tests files, which are primarily aimed at demonstrating usage of PyFTDI in common use cases.

Most unit tests are disabled, as they require specific slaves, with a dedicated HW wiring. Reproducing such test environments can be challenging, as it requires dedicated test benchs.

This is a growing concern as PyFTDI keeps evolving, and up to now, regression tests were hard to run.

## Hardware tests

Please refer to the `pyftdi/tests` directory. There is one file dedicated to each feature to test. Note that you need to read and edit these tests files to fit your actual test environment, and enable the proper unit test cases, as most are actually disabled by default.

You need specific bus slaves to perform most of these tests.

## Virtual test framework

With PyFTDI v0.45, a new test module enables PyFTDI API partial testing using a pure software environment with no hardware. This also eases automatic testing within a continuous integration environment.

This new module implements a virtual USB backend for PyUSB, which creates some kind of virtual, limited USB stack. The PyUSB can be told to substitute the native platform’s libusb with this module.

This module, `usbvirt` can be dynamically confifured with the help of YaML definition files to create one or more virtual FTDI devices on a virtual USB bus topology. This enables to test `usbtools` module to enumerate, detect, report and access FTDI devices using the regular URL Scheme syntax.

`usbvirt` also routes all vendor-specific USB API calls to a secondary `ftdivirt` module, which is in charge of handling all FTDI USB requests.

This module enables testing PyFtdi APIs. It also re-uses the MPSSE tracker engine to decode and verify MPSSE requests used to support I2C, SPI and UART features.

For now, it is able to emulate most of GPIO requests (async, sync and MPSSE) and UART input/output. It also manages the frequency and baudrate settings.

It is not able to emulate the MPSSE commands (with the exception of set and get GPIO values), as it represents a massive workload…

### Beware: WIP

This is an experimental work in progress, which is its early inception stage.

It has nevertheless already revealed a couple of bugs that had been hiding within PyFtdi for years.

There is a large work effort ahead to be able to support more use cases and tests more APIs, and many unit tests to write.

It cannot replace hardware tests with actual boards and slaves, but should simplify test setup and help avoiding regression issues.

### Usage

No hardware is required to run these tests, to even a single FTDI device.

The test configuration files are described in YaML file format, therefore the ruamel.yaml package is required.

    pip3 install ruamel.yaml
    PYTHONPATH=. FTDI_LOGLEVEL=info pyftdi/tests/mockusb.py

### Configuration

The `pyftdi/tests/resources` directory contains definition files which are loaded by the mock unit tests.

Although it is possible to create fine grained USB device definitions, the configuration loader tries to automatically define missing parts to match the USB device topology of FTDI devices.

This enables to create simple definition files without having to mess with low level USB definitions whenever possible.

#### EEPROM content

The EEPROM configuration tool tool can be used to load, modify and generate the content of a virtual EEPROM, see EEPROM management.

#### Examples

> - An example of a nearly comprehensive syntax can be found in `ft232h.yaml`.

> - Another, much more simple example with only mandatory settings can be found in `ft230x.yaml`.

> - An example of multiple FTDI device definitions can be found in `ftmany.yaml`

## Availability

Note that unit tests and the virtual infrastructure are not included in the distributed Python packages, they are only available from the git repository.