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