NAME

Test::Device::Chip::Adapter - unit testing on Device::Chip

SYNOPSIS

use Test::More;
use Test::Device::Chip::Adapter;

use Future::AsyncAwait;

my $adapter = Test::Device::Chip::Adapter->new;

$chip_under_test->mount( $adapter );

# An actual test
$adapter->expect_readwrite( "123" )
   ->will_done( "45" );

is( await $chip->do_thing( "123" ), "45", 'result of ->do_thing' );

$adapter->check_and_clear( '->do_thing' );

DESCRIPTION

This package provides a concrete implementation of Device::Chip::Adapter convenient for using in a unit-test script used to test a Device::Chip instance. It operates in an "expect-and-check" style of mocking, requiring the test script to declare upfront what methods are expected to be called, and what values they return.

Futures returned by this module will not yield results immediately; they must be awaited by a toplevel await keyword or invoking the ->get method. This ensures that unit tests correctly perform the required asynchronisation.

EXPECTATIONS

Each of the actual methods to be used by the Device::Chip under test has an associated expectation method, whose name is prefixed expect_. Each returns an expectation object, which has additional methods to control the behaviour of that invocation.

$exp = $adapter->expect_write_gpios( \%gpios );
$exp = $adapter->expect_read_gpios( \@gpios );
$exp = $adapter->expect_tris_gpios( \@gpios );
$exp = $adapter->expect_write( $bytes );
$exp = $adapter->expect_read( $len );
$exp = $adapter->expect_write_then_read( $bytes, $len );
$exp = $adapter->expect_readwrite( $bytes_out );
$exp = $adapter->expect_assert_ss;
$exp = $adapter->expect_release_ss;
$exp = $adapter->expect_readwrite_no_ss( $bytes_out );
$exp = $adapter->expect_write_no_ss( $bytes );

The returned expectation object allows the test script to specify what such an invocation should yield from its future.

$exp->will_done( $bytes_in );
$exp->will_fail( $failure );

Expectations for an atomic I²C transaction are performed inline, using the following additional methods:

$adapter->expect_txn_start();
$adapter->expect_txn_stop();

As a lot of existing unit tests may have already been written to the API shape provided by Test::ExpectAndCheck::Future version 0.03, the expectation object also recognises the returns method as an alias to will_done.

$exp->returns( $bytes_in );

This wrapper should be considered as a temporary back-compatibility measure however. It now prints a warning and perhaps will be removed entirely in a later version. You should avoid using it in new code; just call will_done directly.

Read Buffering

Since version 0.26.

Testing with exact read calls can be fragile; especially with UART-based protocols, as it relies on exact ordering, buffer sizes, and so on. A more flexible approach that leads to less brittle tests is to use a buffer.

This first has to be enabled:

$adapter->use_read_buffer;

At this point, no read method call will consume an expectation. Instead, it will attempt to consume data from the read buffer. This can be provided by:

$adapter->write_read_buffer( $data );

METHODS

This class has the methods available on Device::Chip::Adapter, which would normally be used by the chip instance under test. The following additional methods would be used by the unit test script controlling it.

check_and_clear

$adapter->check_and_clear( $name );

Checks that by now, every expected method has indeed been called, and emits a new test output line via Test::Builder. Regardless, the expectations are also cleared out ready for the start of the next test.

TODO

  • Handle list_gpios method

  • Handle configure

AUTHOR

Paul Evans <leonerd@leonerd.org.uk>