#include #include #include "hal.h" #include "mock_hal.h" #include "tmp36_mock.h" #include "{{PROJECT_NAME}}_app.h" using ::testing::_; using ::testing::AnyNumber; using ::testing::Return; using ::testing::HasSubstr; // ============================================================================ // Unit Tests -- verify WeatherApp behavior with mock sensor // ============================================================================ class WeatherUnitTest : public ::testing::Test { protected: void SetUp() override { ON_CALL(mock_, millis()).WillByDefault(Return(0)); EXPECT_CALL(mock_, serialBegin(_)).Times(AnyNumber()); EXPECT_CALL(mock_, serialPrint(_)).Times(AnyNumber()); EXPECT_CALL(mock_, serialPrintln(_)).Times(AnyNumber()); EXPECT_CALL(mock_, millis()).Times(AnyNumber()); } ::testing::NiceMock mock_; Tmp36Mock sensor_; }; TEST_F(WeatherUnitTest, BeginPrintsStartupMessage) { WeatherApp app(&mock_, &sensor_); EXPECT_CALL(mock_, serialBegin(115200)).Times(1); EXPECT_CALL(mock_, serialPrintln(HasSubstr("WeatherApp started"))).Times(1); app.begin(); } TEST_F(WeatherUnitTest, BeginTakesInitialReading) { sensor_.setTemperature(25.0f); WeatherApp app(&mock_, &sensor_); app.begin(); EXPECT_EQ(app.readCount(), 1); EXPECT_NEAR(app.lastCelsius(), 25.0f, 0.1f); } TEST_F(WeatherUnitTest, ReadsAfterInterval) { sensor_.setTemperature(20.0f); WeatherApp app(&mock_, &sensor_); ON_CALL(mock_, millis()).WillByDefault(Return(0)); app.begin(); EXPECT_EQ(app.readCount(), 1); // Not enough time yet ON_CALL(mock_, millis()).WillByDefault(Return(1999)); app.update(); EXPECT_EQ(app.readCount(), 1); // Now 2 seconds have passed ON_CALL(mock_, millis()).WillByDefault(Return(2000)); app.update(); EXPECT_EQ(app.readCount(), 2); } TEST_F(WeatherUnitTest, DoesNotReadTooEarly) { sensor_.setTemperature(22.0f); WeatherApp app(&mock_, &sensor_); ON_CALL(mock_, millis()).WillByDefault(Return(0)); app.begin(); ON_CALL(mock_, millis()).WillByDefault(Return(1500)); app.update(); EXPECT_EQ(app.readCount(), 1); } TEST_F(WeatherUnitTest, CelsiusToFahrenheitConversion) { sensor_.setTemperature(0.0f); WeatherApp app(&mock_, &sensor_); app.begin(); EXPECT_NEAR(app.lastCelsius(), 0.0f, 0.1f); EXPECT_NEAR(app.lastFahrenheit(), 32.0f, 0.1f); } TEST_F(WeatherUnitTest, BoilingPoint) { sensor_.setTemperature(100.0f); WeatherApp app(&mock_, &sensor_); app.begin(); EXPECT_NEAR(app.lastCelsius(), 100.0f, 0.1f); EXPECT_NEAR(app.lastFahrenheit(), 212.0f, 0.1f); } TEST_F(WeatherUnitTest, NegativeTemperature) { sensor_.setTemperature(-10.0f); WeatherApp app(&mock_, &sensor_); app.begin(); EXPECT_NEAR(app.lastCelsius(), -10.0f, 0.1f); EXPECT_NEAR(app.lastFahrenheit(), 14.0f, 0.1f); } TEST_F(WeatherUnitTest, PrintsTemperatureOnRead) { sensor_.setTemperature(25.0f); WeatherApp app(&mock_, &sensor_); EXPECT_CALL(mock_, serialPrint(HasSubstr("Temperature: "))).Times(1); EXPECT_CALL(mock_, serialPrintln(HasSubstr(" F)"))).Times(1); app.begin(); } TEST_F(WeatherUnitTest, MultipleReadingsTrackNewTemperature) { WeatherApp app(&mock_, &sensor_); sensor_.setTemperature(20.0f); ON_CALL(mock_, millis()).WillByDefault(Return(0)); app.begin(); EXPECT_NEAR(app.lastCelsius(), 20.0f, 0.1f); sensor_.setTemperature(30.0f); ON_CALL(mock_, millis()).WillByDefault(Return(2000)); app.update(); EXPECT_NEAR(app.lastCelsius(), 30.0f, 0.1f); EXPECT_EQ(app.readCount(), 2); }