Write a Component Test
Turn one public compatibility claim into focused, discoverable, source-owned evidence.
Locate the owning test tree
Every physical component declares its production sources and any test sources through current CMake registration. Place behavior tests under the owning module’s tests/ tree and include public headers the same way a consumer does.
modules/io-hashing/
├── include/System/IO/Hashing/...
├── CMakeLists.txt
└── tests/System/IO/HashingTests.cpp
Do not add a source to a central hand-maintained test list. The component registration collects its test tree and gives it the owning target plus declared test dependencies.
Write one observable contract
#include <gtest/gtest.h>
#include <cstdint>
#include <vector>
#include "System/IO/Hashing/Crc32.hpp"
TEST(HashingDocumentationExample, StandardVector) {
const std::vector<std::uint8_t> input{
'1', '2', '3', '4', '5', '6', '7', '8', '9'};
EXPECT_EQ(
System::IO::Hashing::Crc32::HashToUInt32(
input.data(), static_cast<std::int32_t>(input.size())),
0xCBF43926u);
}
Name the behavior rather than the implementation strategy. The standard vector proves a public result; a test named UsesPolynomialTable would unnecessarily freeze a private technique.
Cover boundary and failure behavior
A useful compatibility slice normally needs more than a happy path:
- empty, one-element, minimum, and maximum valid input;
- invalid values and the exact public exception family/parameter name when contractual;
- copy, move, close/dispose, repeated-call, and post-failure state;
- overlap, aliasing, mutation, and invalidation for contiguous storage;
- callback reentrancy, removal, exceptions, and concurrent use for event/threaded APIs;
- platform-specific branches with honest skips rather than unconditional green assertions.
Configure the narrow component
cmake -S /path/to/sharp-runtime -B build-io-hashing \
-G Ninja \
-DCMAKE_BUILD_TYPE=Debug \
-DSHARP_RUNTIME_COMPONENTS=IO.Hashing \
-DSHARP_RUNTIME_BUILD_TESTS=ON
Use the selected pinned checkout, not whichever branch happens to be current elsewhere. A component build tests its declared closure and catches dependency leaks earlier than an All build.
Build and run serially when memory is constrained
cmake --build build-io-hashing \
--target SharpRuntimeTests_IO_Hashing \
--parallel 1
./build-io-hashing/SharpRuntimeTests_IO_Hashing \
--gtest_filter=HashingDocumentationExample.StandardVector
ctest --test-dir build-io-hashing \
--output-on-failure \
-R '^IO\.Hashing::HashingDocumentationExample\.StandardVector$'
CMake converts dots in a physical component name to underscores for the executable target. GoogleTest discovery prefixes CTest names with the original dotted component. Use ctest -N to inspect actual discovery rather than guessing a count from TEST macros.
Distinguish discovery from execution
| Evidence | Claim it supports |
|---|---|
ctest -N after built discovery | Cases currently discovered in that build tree. |
| Focused executable/filter result | One suite/case actually ran in this environment. |
| Complete CTest gate result | All discovered cases were attempted, with measured pass/skip/fail totals. |
| Source test file exists | Only that source coverage was authored—not that discovery or execution succeeded. |
Add special fixtures where positive tests cannot prove the rule
A normal unit test cannot prove that a private header is unreachable, a forbidden conversion fails, or a template constraint rejects a type. Use a negative consumer fixture for those compile-time contracts. Use the module-boundary validator for dependency visibility. Use an integration test only when the behavior genuinely crosses component boundaries.
Finish the contributor loop
- Run the focused test and its neighboring suite.
- Run the owning component target from a clean enough build to exercise discovery.
- Run boundary and catalogue validation.
- Run the full gate when the environment and resource budget allow it.
- Update API deviations, limitations, tutorials, and generated catalogue inputs when public behavior changed.
- Record measured results with SHA, toolchain, platform, date, and exact terminology.