Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 21 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
# AUnit PlatformIO Integration
# ArduinoUnit PlatformIO Integration

**My template** for using [AUnit](https://github.com/bxparks/AUnit) in [PlatformIO](https://platformio.org/) with a [logic analyser](https://core-electronics.com.au/usb-logic-analyzer-24mhz-8-channel.html) and with a custom ESP-32S2 based board.
**My template** for using [`arduinounit`](https://github.com/mmurdoch/arduinounit) in [PlatformIO](https://platformio.org/) with a [logic analyser](https://core-electronics.com.au/usb-logic-analyzer-24mhz-8-channel.html) and with a custom ESP-32S2 based board.

> [!NOTE]
> This repo was originally for [`AUnit`](https://github.com/bxparks/AUnit) but I needed the `MockStream` object so I converted to ArdunioUnit.
> **If you want to use `AUnit`, you see see their tutorial on migrating from ArduinoUnit [here](https://github.com/bxparks/AUnit?tab=readme-ov-file#ArduinoUnitCompatible)**

<p align="center">
<img src="assets/setup.png" alt="Annotated hardware setup" width="300">
</p>

For those looking to implement their own version of AUnit with PlatformIO, I wish you the best of luck. This was incredibly complex to get working. My method also uses a [physical logic analyser](https://core-electronics.com.au/usb-logic-analyzer-24mhz-8-channel.html) and [Saleae's Logic2 application](https://www.saleae.com/pages/downloads?srsltid=AfmBOop1eoIiGSyJggODsT0lgRuMeX46d3sEPPDvJscgZumQkeUSdmga) to make this work well with: physical testing, software compatibility and development. If you don't have a logic analyser, you will need some sort of way to read the serial data from the board and pipe it into the the [custom test runner](https://docs.platformio.org/en/latest/advanced/unit-testing/frameworks/custom/runner.html) which is located in `test/**/test_custom_runner.py`.
For those looking to implement their own version of ArduinoUnit with PlatformIO, I wish you the best of luck. This was incredibly complex to get working. My method also uses a [physical logic analyser](https://core-electronics.com.au/usb-logic-analyzer-24mhz-8-channel.html) and [Saleae's Logic2 application](https://www.saleae.com/pages/downloads?srsltid=AfmBOop1eoIiGSyJggODsT0lgRuMeX46d3sEPPDvJscgZumQkeUSdmga) to make this work well with: physical testing, software compatibility and development. If you don't have a logic analyser, you will need some sort of way to read the serial data from the board and pipe it into the the [custom test runner](https://docs.platformio.org/en/latest/advanced/unit-testing/frameworks/custom/runner.html) which is located in `test/**/test_custom_runner.py`.

## Summary

To run a test, use the provided [PIO test hierarchy](https://docs.platformio.org/en/stable/advanced/unit-testing/structure/hierarchy.html#test-hierarchy) and try to minimise the amount of separate test files. Each test file `*.cpp` will be compiled and flashed inividually which takes a while. So make sure you can fit in as much as you can in the one flash to avoid 10 minute test runs.

In each test, you are using **just** [AUnit](https://github.com/bxparks/AUnit). This is the methodology and [hierarchy](https://docs.platformio.org/en/latest/advanced/unit-testing/structure/hierarchy.html) for creating tests:
In each test, you are using **just** [ArduinoUnit](https://github.com/mmurdoch/arduinounit). This is the methodology and [hierarchy](https://docs.platformio.org/en/latest/advanced/unit-testing/structure/hierarchy.html) for creating tests:

0. Install python test dependencies
- `source ~/.platformio/penv/bin/activate` then `pip install logic2-automation`
1. Create a test in a folder prefixed with `test_`
- This requires a `.cpp` file with the AUnit software that runs all tests in that file with the `aunit::TestRunner::run();` command.
- This requires a `.cpp` file with the ArduinoUnit software that runs all tests in that file with the `Test::run` command.
2. Run the PIO test

### Python Runner
Expand All @@ -26,7 +30,7 @@ This implementation uses a [python handler/runner](https://docs.platformio.org/e

This file is a generic bridge to parse the results of each test. PIO will search each directory and parent directory until it has reached the root of `test_dir`. This means each test can have custom handlers with precedence. At the moment, only a generic one is needed in the `embedded/` folder to handle all those test cases.

This Python file will then connect to your logic analyser software ([Logic2](https://saleae.github.io/logic2-automation/index.html)) and create raw and high-level ASCII CSV analysis files. After those files are created by the logic analyser, the PIO `test_custom_runner.py` file will then scrape that output for the AUnit success and failure messages. That data is then formatted with the PIO test cases class and presented in the rich report.
This Python file will then connect to your logic analyser software ([Logic2](https://saleae.github.io/logic2-automation/index.html)) and create raw and high-level ASCII CSV analysis files. After those files are created by the logic analyser, the PIO `test_custom_runner.py` file will then scrape that output for the ArduinoUnit success and failure messages. That data is then formatted with the PIO test cases class and presented in the rich report.

## Known Limitations

Expand All @@ -41,30 +45,25 @@ This Python file will then connect to your logic analyser software ([Logic2](htt
- Make sure you have installed the python dependencies as listed in the summary section above.
- Make sure your python interpreter is selected as `~/.platformio/penv/bin/python`.

**No test cases or no summary file**

- Make sure baud rate is correct

## Todo List

- Stop the recording once the tests have finished [link](https://saleae.github.io/logic2-automation/automation.html#saleae.automation.CaptureConfiguration) and [method to use](https://saleae.github.io/logic2-automation/automation.html#manualcapturemode). This will have to be done by stopping it manually while parsing when the summary line is detected
- This may be impossible with current API
- Test if this works on another computer
- Note: Continuous capturing is only available with a [HLA](https://github.com/saleae/logic2-automation/issues/4) it seems. This would also require another system to export back and fourth from logic and unity. Probably not worth it.
- Test with more complex AUnit test outputs
- Test with more complex ArduinoUnit test outputs

Example **ArduinoUnit** output for reference:

```
ESP-ROM:esp32s2-rc4-20191025
Build:Oct 25 2019
rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3ffe6100,len:0x55c
load:0x4004c000,len:0xa70
load:0x40050000,len:0x29d8
entry 0x4004c18c
TestRunner started on 2 test(s).
Test exampleTest passed.
AUnitPlatformIO.ino:12: Assertion failed: (3) == (2).
Test exampleTest2 failed.
TestRunner duration: 0.011 seconds.
TestRunner summary: 1 passed, 1 failed, 0 skipped, 0 timed out, out of 2 test(s).
Dummy test 1
Test exampleTest1 passed.
MOCK_OUTPUT: value? 10*10=100
Test exampleTest2 passed.
Serial output prefixed with no newlineTest exampleTest3 passed.
Test summary: 3 passed, 0 failed, and 0 skipped, out of 3 test(s).
```
9 changes: 5 additions & 4 deletions install_venv_pkgs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@

# This file currently does nothing

Import("env")
Import("env") # type: ignore

print("Running python prerequisites")

# List installed packages
env.Execute("$PYTHONEXE -m pip list")
env.Execute("$PYTHONEXE -m pip list") # type: ignore


# Install custom packages from the PyPi registry
env.Execute("$PYTHONEXE -m pip install logic2-automation")
env.Execute("$PYTHONEXE -m pip install logic2-automation") # type: ignore

# Install missed package
try:
import saleae
except ImportError:
env.Execute("$PYTHONEXE -m pip install logic2-automation")
env.Execute("$PYTHONEXE -m pip install logic2-automation") # type: ignore
3 changes: 1 addition & 2 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
; https://docs.platformio.org/page/projectconf.html

[env:custom]
lib_deps =
bxparks/AUnit@^1.7.1
lib_deps = https://github.com/mmurdoch/arduinounit
test_framework = custom
extra_scripts = install_venv_pkgs.py
framework = arduino
Expand Down
3 changes: 3 additions & 0 deletions test/embedded/include/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,5 +221,8 @@ def create_all_test_cases(self) -> List[TestCase]:
if re_match := re.search(TestParser.TEST_REGEX, line["line"]):
test_cases.append(self._generate_test_case(
timestamped_lines, re_match, index))
# TODO Make a check that checks the last line to make sure that the
# amount of tests the code found matches the amount in the test cases
# list.

return test_cases
1 change: 1 addition & 0 deletions test/embedded/test_custom_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def setup(self):

def stage_testing(self):
# 1. Gather test results from Serial, HTTP, Socket, or other sources
print("Starting logic")
logic = LogicAnalyser();
# Setup serial analysis
self.LOGIC_BOOT_OK = logic.start_serial_analysis()
Expand Down
42 changes: 26 additions & 16 deletions test/embedded/test_dummy/main.cpp
Original file line number Diff line number Diff line change
@@ -1,22 +1,38 @@
#line 2 "AUnitPlatformIO.ino"

#include <AUnit.h>
#line 2 "main.cpp"
#include <ArduinoUnit.h>

test(exampleTest1)
{
Serial.println("Dummy test 1");
assertEqual(3, 3);
}

void square(Stream &io)
{
io.print("value? ");
int x = io.parseInt();
io.print(x);
io.print("*");
io.print(x);
io.print("=");
io.println(x * x);
}

test(exampleTest2)
{
assertNotEqual(3, 3);
MockStream ms;
ms.input.print(10);
square(ms);
Serial.print("MOCK_OUTPUT: ");
Serial.println(ms.output);
assertEqual(ms.output, "value? 10*10=100\r\n");
}

test(exampleTest3)
{
Serial.print("Serial output prefixed with no newline");
// Serial.println("Serial output on own line");
assertLess(5, 5);
assertEqual(5, 5);
}

//----------------------------------------------------------------------------
Expand All @@ -25,20 +41,14 @@ test(exampleTest3)

void setup()
{
#if !defined(EPOXY_DUINO)
delay(1000); // wait for stability on some boards to prevent garbage Serial
#endif
Serial.begin(115200); // ESP8266 default of 74880 not supported on Linux
Serial.begin(115200);
while (!Serial)
; // for the Arduino Leonardo/Micro only
#if defined(EPOXY_DUINO)
Serial.setLineModeUnix();
#endif
pinMode(1, OUTPUT);
digitalWrite(1, HIGH);
{
} // Portability for Leonardo/Micro
delay(2000); // Delay to wait for logic to startup
}

void loop()
{
aunit::TestRunner::run();
Test::run();
}