Skip to content
Permalink
f3ace5ae9d
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time

Test-Driven Development with Arduino

In this lab you will learn how to carry out the process of Test-Driven development (TDD) using the Arduino framework. We will be using the PlatformIO command-line tools. There is detailed documentation covering the implementation of the Unity tools.

1 Understanding the Code

You should now use the IDE to open the exercises/02_tdd/temp/ directory which contains a simple Arduino sketch with a library. Lets look at the files. As you can see there are some additional ones:

├── lib
│   ├── avg
│   │   ├── avg.cpp
│   │   └── avg.h
│   └── readme.txt
├── platformio.ini
├── readme.md
├── src
│   └── main.cpp
└── test
    └── test_desktop
        └── test_avg.cpp
  1. The lib/ directory contains our custom library. This is where we will build the business logic for our software. It will be thoroughly unit tested.
  2. The test/ directory contains the unit testing files that will be used to test the library code.

2 Running the Unit Tests

We will be executing our test suite from the terminal by invoking the pio command together with the test subcommand. Make sure you create an account and log in.

You should also ensure the gcc toolchain is installed on your computer. Run the command gcc. If this is not found you will need to install, the instructions differ depending on your operating system:

  1. MacOS: brew install gcc
  2. Ubuntu: apt install gcc
  3. Windows 10: install Cygwin and make sure you pick the gcc tools from the selection of software it can install.
$ pio test -v -e native
  ================================== [SUMMARY] ==================================
  Environment nodemcuv2  [SKIP]
  Environment native     [SUCCESS]
  ========================= [SUCCESS] Took 0.32 seconds =========================

  ===================== [test/test_desktop] Testing... (2/2) =====================
  /test_avg.cpp:11:test_add_single_val:FAIL: Expected 0 Was 42  [FAILED]

  -----------------------
  1 Tests 1 Failures 0 Ignored
  FAIL
  =============================== [TEST SUMMARY] ================================
  test/test_desktop/env:nodemcuv2  [IGNORED]
  test/test_desktop/env:native     [FAILED]
  ========================== [FAILED] Took 0.33 seconds ==========================

Notice that the test suite fails!

3 Test-Driven Development

You are now going to modify the code to ensure that the test passes. The test adds a single value to the library. It then reads the average value which should match the value we passed (but it doesn't). We are going to apply TDD principles.

3.1 Define Requirements as a Test

For this first iteration, this has already been done, look in the test_avg.cpp file.

3.2 Write Code to pass the Test

We now need to write just enough code to pass the test. Edit the lib/avg/avg.cpp file. Test your code by running the test suite. Stop as soon as the test passes.

3.3 Refactor the Code

The third and final step is to tidy up the code, making sure the tests still pass.

3.4 Test Your Understanding

Now apply the TDD principles to fix the following issues, this will take 6 TDD iterations:

  1. If I send 2 values to the library, the average should be calculated based on the 2 values. Try adding 42 and 24, it should return 33.
    1. If the result is wrong perhaps you needed to call the avg_clear() function at the start of each test.
  2. If the average is a floating point number it should round up if the average is 0.5 or above:
    1. If I pass values of 42 and 23 the average should be 33.
    2. If I pass values of 42, 11, 17, the average should be 23.
  3. The library should return the average of the last 5 values passed so if I add 6 values it should ignore the first one we added.
    1. If I pass the values 1, 2, 3, 4, 5 the average should be 3.
    2. If I pass the values 1, 2, 3, 4, 5, 6 the average should be 4.
    3. If I pass the values 1, 2, 3, 4, 5, 6, 7 the average should be 5.

For an extension task, use TDD to implement an average function that returns the mean reading since the device was powered up.

4 Integrate into an Arduino Project

The final step is to use your custom library to create a complete temperature and humidity sensor.

  1. Connect a DHT11 sensor and capture the temperature and display in the serial monitor. 2. If you are using the Lolin32 board you should also display the temperature on the screen.
  2. Use your custom library to smooth the reading using a rolling average, display this next to each raw reading (including the screen if available).
  3. Capture the humidity as well as temperature and display this next to the temp values.
  4. How could you modify your library to smooth both the temperature and humidity?
    1. You may need to make changes to your library.
    2. Don't forget to apply the TDD methdology!