parent
8db57d6dc5
commit
525ed2ae1b
@ -0,0 +1,28 @@ |
|||||||
|
# Running tests |
||||||
|
|
||||||
|
Our test suite currently must be run on an actual device. A subset of our tests may run correctly on a bare ESP32-WROVER module, but in general they do rely on the real Tangara hardware being available. |
||||||
|
|
||||||
|
Tests are implemented as a separate application build, located in the `test` |
||||||
|
directory. We use Catch2 as our test framework. |
||||||
|
|
||||||
|
To run them, navigate to the test directory, then build and flash as normal. e.g. |
||||||
|
|
||||||
|
``` |
||||||
|
idf.py -p /dev/serial/by-id/usb-cool_tech_zone_Tangara_* app-flash |
||||||
|
``` |
||||||
|
|
||||||
|
Connect to your device via serial, and you will be presented with |
||||||
|
variant of our standard dev console. To run all tests, simply execute `catch` in the console. |
||||||
|
|
||||||
|
The `catch` command accepts additional arguments as if it were a standard Catch2 test runner binary. You can therefore see a brief guide to the available options with `catch -?`. |
||||||
|
|
||||||
|
# Writing tests |
||||||
|
|
||||||
|
Tests live within the `test` subcomponent of the component that the tests are written for. In practice, this means that device driver tests should live in `src/drivers/test`, whilst most other tests live in `src/tangara/test`. |
||||||
|
|
||||||
|
## Tags |
||||||
|
|
||||||
|
Catch2 has a flexible system of test tags that can be used to categorise different test cases. Feel free to add new tags as-needed. In general, most tests should be tagged with one of: |
||||||
|
|
||||||
|
- `[integration]`, for tests that rely on the hardware being in a specific state |
||||||
|
- `[unit]`, for tests that operate purely in-memory, either without any additional device drivers needed, or by using test doubles rather than real drivers. |
@ -0,0 +1,32 @@ |
|||||||
|
/*
|
||||||
|
* Copyright 2023 jacqueline <me@jacqueline.id.au> |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: GPL-3.0-only |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "drivers/samd.hpp" |
||||||
|
|
||||||
|
#include <cstdint> |
||||||
|
|
||||||
|
#include "catch2/catch.hpp" |
||||||
|
|
||||||
|
#include "i2c_fixture.hpp" |
||||||
|
|
||||||
|
namespace drivers { |
||||||
|
|
||||||
|
TEST_CASE("samd21 interface", "[integration]") { |
||||||
|
I2CFixture i2c; |
||||||
|
auto samd = std::make_unique<Samd>(); |
||||||
|
|
||||||
|
REQUIRE(samd); |
||||||
|
|
||||||
|
SECTION("usb reports connection") { |
||||||
|
samd->UpdateUsbStatus(); |
||||||
|
|
||||||
|
auto status = samd->GetUsbStatus(); |
||||||
|
|
||||||
|
REQUIRE(status == Samd::UsbStatus::kAttachedIdle); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace drivers
|
@ -0,0 +1,7 @@ |
|||||||
|
# Copyright 2023 jacqueline <me@jacqueline.id.au> |
||||||
|
# |
||||||
|
# SPDX-License-Identifier: GPL-3.0-only |
||||||
|
|
||||||
|
idf_component_register( |
||||||
|
SRC_DIRS "battery" |
||||||
|
INCLUDE_DIRS "." REQUIRES catch2 cmock tangara fixtures) |
@ -0,0 +1,67 @@ |
|||||||
|
/*
|
||||||
|
* Copyright 2024 jacqueline <me@jacqueline.id.au> |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: GPL-3.0-only |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "battery/battery.hpp" |
||||||
|
|
||||||
|
#include <cstdint> |
||||||
|
#include <memory> |
||||||
|
|
||||||
|
#include "catch2/catch.hpp" |
||||||
|
#include "drivers/adc.hpp" |
||||||
|
#include "i2c_fixture.hpp" |
||||||
|
|
||||||
|
namespace battery { |
||||||
|
|
||||||
|
class FakeAdc : public drivers::AdcBattery { |
||||||
|
private: |
||||||
|
uint32_t mv_; |
||||||
|
|
||||||
|
public: |
||||||
|
virtual auto Millivolts() -> uint32_t override { return mv_; } |
||||||
|
auto Millivolts(uint32_t mv) -> void { mv_ = mv; } |
||||||
|
}; |
||||||
|
|
||||||
|
TEST_CASE("battery charge state", "[unit]") { |
||||||
|
I2CFixture i2c; |
||||||
|
|
||||||
|
// FIXME: mock the SAMD21 as well.
|
||||||
|
std::unique_ptr<drivers::Samd> samd{drivers::Samd::Create()}; |
||||||
|
FakeAdc* adc = new FakeAdc{}; // Freed by Battery.
|
||||||
|
Battery battery{*samd, std::unique_ptr<drivers::AdcBattery>{adc}}; |
||||||
|
|
||||||
|
SECTION("full charge is 100%") { |
||||||
|
// NOTE: in practice, our curve-fitting slightly undershoots
|
||||||
|
adc->Millivolts(4210); |
||||||
|
|
||||||
|
battery.Update(); |
||||||
|
|
||||||
|
auto state = battery.State(); |
||||||
|
REQUIRE(state.has_value()); |
||||||
|
REQUIRE(state->percent == 100); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("empty charge is 0%") { |
||||||
|
adc->Millivolts(3000); |
||||||
|
|
||||||
|
battery.Update(); |
||||||
|
|
||||||
|
auto state = battery.State(); |
||||||
|
REQUIRE(state.has_value()); |
||||||
|
REQUIRE(state->percent == 0); |
||||||
|
} |
||||||
|
|
||||||
|
SECTION("overcharge is clamped to 100%") { |
||||||
|
adc->Millivolts(5000); |
||||||
|
|
||||||
|
battery.Update(); |
||||||
|
|
||||||
|
auto state = battery.State(); |
||||||
|
REQUIRE(state.has_value()); |
||||||
|
REQUIRE(state->percent == 100); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace battery
|
Loading…
Reference in new issue