pw_unit_test: Make simple runner look like GTest
This makes these changes to the unit test framework:
(1) Makes the simple test runner output match GTest
(2) Adds a new RunAllTestsStart() and RunAllTestsEnd() event
(3) Adds an intentionally-failing expectation to the sample test
Example output:
[==========] Running all tests.
[ RUN ] PigweedTest.ExpectBool
[ OK ] PigweedTest.ExpectBool
[ RUN ] PigweedTest.ExpectBasicComparisons
[ OK ] PigweedTest.ExpectBasicComparisons
[ RUN ] PigweedTest.ExpectStringEquality
[ OK ] PigweedTest.ExpectStringEquality
[ RUN ] PigweedTest.NonCopyableType
[ OK ] PigweedTest.NonCopyableType
[ RUN ] PigweedTest.MacroArgumentsOnlyAreEvaluatedOnce
[ OK ] PigweedTest.MacroArgumentsOnlyAreEvaluatedOnce
[ RUN ] FixtureTest.CustomFixture
[ OK ] FixtureTest.CustomFixture
[ RUN ] PigweedTestFixture.TheNumberIs35
[ OK ] PigweedTestFixture.TheNumberIs35
[ RUN ] PigweedTestFixture.YupTheNumberIs35
[ OK ] PigweedTestFixture.YupTheNumberIs35
[ RUN ] PigweedTestFixture.MissingExpectations
../pw_unit_test/framework_test.cc:156: Failure
Expected: missed_expectations == 200
[ FAILED ] PigweedTestFixture.MissingExpectations
[==========] Done running all tests.
[ PASSED ] 8 test(s).
[ FAILED ] 1 test(s).
Change-Id: I813096a9d62423e256993ae03724337d52702297
diff --git a/pw_build/BUILD.gn b/pw_build/BUILD.gn
index ebe935d..75003fa 100644
--- a/pw_build/BUILD.gn
+++ b/pw_build/BUILD.gn
@@ -27,6 +27,9 @@
cflags = [
"-Wall",
"-Wextra",
+
+ # Warn when a switch on an enum does not cover all the cases.
+ "-Wswitch",
]
}
diff --git a/pw_unit_test/framework.cc b/pw_unit_test/framework.cc
index 24fbb7c..b89a4b2 100644
--- a/pw_unit_test/framework.cc
+++ b/pw_unit_test/framework.cc
@@ -38,9 +38,18 @@
}
int Framework::RunAllTests() {
+ run_tests_summary_.passed_tests = 0;
+ run_tests_summary_.failed_tests = 0;
+
+ if (event_handler_ != nullptr) {
+ event_handler_->RunAllTestsStart();
+ }
for (TestInfo* test = tests_; test != nullptr; test = test->next) {
test->run();
}
+ if (event_handler_ != nullptr) {
+ event_handler_->RunAllTestsEnd(run_tests_summary_);
+ }
return exit_status_;
}
@@ -64,6 +73,14 @@
void Framework::EndTest(Test* test) {
current_test_ = nullptr;
+ switch (current_result_) {
+ case TestResult::kSuccess:
+ run_tests_summary_.passed_tests++;
+ break;
+ case TestResult::kFailure:
+ run_tests_summary_.failed_tests++;
+ break;
+ }
if (event_handler_ == nullptr) {
return;
diff --git a/pw_unit_test/public/pw_unit_test/event_handler.h b/pw_unit_test/public/pw_unit_test/event_handler.h
index 8a8338b..4fd9ca4 100644
--- a/pw_unit_test/public/pw_unit_test/event_handler.h
+++ b/pw_unit_test/public/pw_unit_test/event_handler.h
@@ -75,11 +75,25 @@
bool success;
};
+struct RunTestsSummary {
+ // The number of passed tests among the run tests.
+ int passed_tests;
+
+ // The number of passed tests among the run tests.
+ int failed_tests;
+};
+
// An event handler is responsible for collecting and processing the results of
// a unit test run. Its interface is called by the unit test framework as tests
// are executed and various test events occur.
class EventHandler {
public:
+ // Called before all tests are run.
+ virtual void RunAllTestsStart() = 0;
+
+ // Called after all tests are run.
+ virtual void RunAllTestsEnd(const RunTestsSummary& run_tests_summary) = 0;
+
// Called when a new test case is started.
virtual void TestCaseStart(const TestCase& test_case) = 0;
diff --git a/pw_unit_test/public/pw_unit_test/framework.h b/pw_unit_test/public/pw_unit_test/framework.h
index 111b892..d633dfa 100644
--- a/pw_unit_test/public/pw_unit_test/framework.h
+++ b/pw_unit_test/public/pw_unit_test/framework.h
@@ -91,6 +91,7 @@
constexpr Framework()
: current_test_(nullptr),
current_result_(TestResult::kSuccess),
+ run_tests_summary_{.passed_tests = 0, .failed_tests = 0},
exit_status_(0),
event_handler_(nullptr),
memory_pool_() {}
@@ -178,6 +179,9 @@
// Overall result of the current test case (pass/fail).
TestResult current_result_;
+ // Overall result of the ongoing test run, which covers multiple tests.
+ RunTestsSummary run_tests_summary_;
+
// Program exit status returned by RunAllTests for Googletest compatibility.
int exit_status_;
diff --git a/pw_unit_test/public/pw_unit_test/simple_printing_event_handler.h b/pw_unit_test/public/pw_unit_test/simple_printing_event_handler.h
index 25c1568..f777568 100644
--- a/pw_unit_test/public/pw_unit_test/simple_printing_event_handler.h
+++ b/pw_unit_test/public/pw_unit_test/simple_printing_event_handler.h
@@ -41,6 +41,8 @@
SimplePrintingEventHandler(WriteFunction write_function, bool verbose = false)
: write_(write_function), verbose_(verbose) {}
+ void RunAllTestsStart() override;
+ void RunAllTestsEnd(const RunTestsSummary& run_tests_summary) override;
void TestCaseStart(const TestCase& test_case) override;
void TestCaseEnd(const TestCase& test_case, TestResult result) override;
void TestCaseExpect(const TestCase& test_case,
diff --git a/pw_unit_test/simple_printing_event_handler.cc b/pw_unit_test/simple_printing_event_handler.cc
index 1ae5d29..9024158 100644
--- a/pw_unit_test/simple_printing_event_handler.cc
+++ b/pw_unit_test/simple_printing_event_handler.cc
@@ -19,16 +19,39 @@
namespace pw::unit_test {
+void SimplePrintingEventHandler::RunAllTestsStart() {
+ WriteAndFlush("[==========] Running all tests.\n");
+}
+
+void SimplePrintingEventHandler::RunAllTestsEnd(
+ const RunTestsSummary& run_tests_summary) {
+ WriteAndFlush("[==========] Done running all tests.\n");
+ WriteAndFlush(
+ "[ PASSED ] %d test(s).\n", run_tests_summary.passed_tests);
+ if (run_tests_summary.failed_tests) {
+ WriteAndFlush(
+ "[ FAILED ] %d test(s).\n", run_tests_summary.failed_tests);
+ }
+}
+
void SimplePrintingEventHandler::TestCaseStart(const TestCase& test_case) {
WriteAndFlush(
- ">>> Running %s.%s\n", test_case.suite_name, test_case.test_name);
+ "[ RUN ] %s.%s\n", test_case.suite_name, test_case.test_name);
}
void SimplePrintingEventHandler::TestCaseEnd(const TestCase& test_case,
TestResult result) {
- const char* status = result == TestResult::kSuccess ? "succeeded" : "failed";
- WriteAndFlush(
- "<<< Test %s.%s %s\n", test_case.suite_name, test_case.test_name, status);
+ // Use a switch with no default to detect changes in the test result enum.
+ switch (result) {
+ case TestResult::kSuccess:
+ WriteAndFlush(
+ "[ OK ] %s.%s\n", test_case.suite_name, test_case.test_name);
+ break;
+ case TestResult::kFailure:
+ WriteAndFlush(
+ "[ FAILED ] %s.%s\n", test_case.suite_name, test_case.test_name);
+ break;
+ }
}
void SimplePrintingEventHandler::TestCaseExpect(
@@ -37,9 +60,10 @@
return;
}
- const char* result = expectation.success ? "SUCCESS" : "FAILURE";
- WriteAndFlush("[%s] %s\n", result, expectation.expression);
- WriteAndFlush(" at %s:%d\n", test_case.file_name, expectation.line_number);
+ const char* result = expectation.success ? "Success" : "Failure";
+ WriteAndFlush(
+ "%s:%d: %s\n", test_case.file_name, expectation.line_number, result);
+ WriteAndFlush(" Expected: %s\n", expectation.expression);
}
int SimplePrintingEventHandler::WriteAndFlush(const char* format, ...) {