chore: refresh project agent guidance
Clarify template guidance, move skills, and document formatter and commit conventions. Co-authored-by: GPT-6 Luna <gpt.6.luna@openrouter.ai>
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
---
|
||||
name: cmake
|
||||
description: CMake build configuration for C and C++ projects started from
|
||||
the ctdd template. Use when adding modules or dependencies, or configuring
|
||||
builds, coverage, and sanitizers.
|
||||
---
|
||||
|
||||
# CMake Skill
|
||||
|
||||
This repository is a starter template, not an application whose sample
|
||||
modules define required features. Its checked-in targets are C examples
|
||||
using C23. When adding C++ targets, use `.cpp` sources and select the
|
||||
project's C++ standard explicitly (for example, `cxx_std_23`). Unity can
|
||||
be used by C++ tests. CMock is for C-compatible interfaces, not C++ class
|
||||
mocking.
|
||||
|
||||
> Replace `<src>/` with the project source directory (e.g. `ctdd/`, `src/`).
|
||||
> Replace `<module>` with the module name (e.g. `counter`, `timer`).
|
||||
|
||||
## Build Commands
|
||||
|
||||
| Action | Command |
|
||||
| --------- | ------------------------------------------------------------------------------------------ |
|
||||
| Configure | `cmake -S . -B build -G Ninja` |
|
||||
| Build | `ninja -C build` |
|
||||
| Run tests | `ninja -C build check` |
|
||||
| Coverage | `cmake -S . -B build-cov -G Ninja -DENABLE_COVERAGE=ON` then `ninja -C build-cov coverage` |
|
||||
| ASan | `cmake -S . -B build-asan -G Ninja -DENABLE_ASAN=ON` then `ninja -C build-asan` |
|
||||
|
||||
> ASan and coverage cannot be used together.
|
||||
|
||||
## Adding a Module
|
||||
|
||||
Modules live in `<src>/` as static libraries. The current example is C;
|
||||
register C modules in `<src>/CMakeLists.txt`:
|
||||
|
||||
```cmake
|
||||
add_library(<src>_<module> <module>.c)
|
||||
target_include_directories(<src>_<module> PUBLIC "${CMAKE_SOURCE_DIR}")
|
||||
target_compile_features(<src>_<module> PRIVATE c_std_23)
|
||||
```
|
||||
|
||||
For a C++ module, use a `.cpp` source and select the standard used by the
|
||||
derived project:
|
||||
|
||||
```cmake
|
||||
add_library(<src>_<module> <module>.cpp)
|
||||
target_include_directories(<src>_<module> PUBLIC "${CMAKE_SOURCE_DIR}")
|
||||
target_compile_features(<src>_<module> PRIVATE cxx_std_23)
|
||||
```
|
||||
|
||||
Replace `cxx_std_23` if the project uses a different C++ standard. Likewise,
|
||||
choose `.c`/`c_std_23` or `.cpp`/`cxx_std_23` for the application's entry
|
||||
point and test sources.
|
||||
|
||||
Link into `main` in the root `CMakeLists.txt`:
|
||||
|
||||
```cmake
|
||||
target_link_libraries(main PRIVATE ... <src>_<module>)
|
||||
```
|
||||
|
||||
## Adding a Dependency
|
||||
|
||||
Dependencies are fetched via custom `Find<name>.cmake` scripts in `deps/`.
|
||||
`deps/` is on `CMAKE_MODULE_PATH` so `find_package()` resolves to these
|
||||
scripts first.
|
||||
|
||||
### 1. Create `deps/Find<name>.cmake`
|
||||
|
||||
Pattern (follow `deps/FindUnity.cmake` or `deps/FindCMock.cmake`):
|
||||
|
||||
```cmake
|
||||
if (DEFINED _FIND<NAME>_INCLUDED)
|
||||
return()
|
||||
endif()
|
||||
set(_FIND<NAME>_INCLUDED TRUE)
|
||||
|
||||
set(<NAME>_VERSION "x.y.z")
|
||||
message(STATUS "Fetching <name> ${<NAME>_VERSION}")
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
<name>
|
||||
URL https://github.com/org/<name>/archive/refs/tags/v${<NAME>_VERSION}.zip
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(<name>)
|
||||
|
||||
if (NOT TARGET <Name>::<Name>)
|
||||
add_library(<Name>::<Name> ALIAS <name>)
|
||||
endif()
|
||||
|
||||
set(<Name>_FOUND TRUE)
|
||||
```
|
||||
|
||||
For libraries without CMakeLists.txt (like CMock), use
|
||||
`FetchContent_Populate` and compile manually. See `FindCMock.cmake`
|
||||
for the pattern.
|
||||
|
||||
### 2. Add `find_package(<Name> REQUIRED)` to `CMakeLists.txt`
|
||||
|
||||
Place it after `include(Platform)` and `include(Flags)`.
|
||||
|
||||
### 3. Link with `<Name>::<Name>`
|
||||
|
||||
In `<src>/CMakeLists.txt` or `tests/CMakeLists.txt` as needed:
|
||||
|
||||
```cmake
|
||||
target_link_libraries(<src>_<module> PRIVATE <Name>::<Name>)
|
||||
```
|
||||
|
||||
## Platform Flags
|
||||
|
||||
`deps/Platform.cmake` sets these variables for conditional logic:
|
||||
|
||||
| Variable | Meaning |
|
||||
| ----------------- | ------------------------------------------------ |
|
||||
| `IS_CLANG_OR_GCC` | Clang or GCC compiler |
|
||||
| `IS_MSVC` | MSVC compiler |
|
||||
| `IS_WINDOWS` | Windows target |
|
||||
| `IS_LINUX` | Linux target |
|
||||
| `IS_MACOS` | macOS target |
|
||||
| `IS_IOS` | iOS target |
|
||||
| `IS_ANDROID` | Android target |
|
||||
| `IS_EMSCRIPTEN` | Emscripten/WASM target |
|
||||
| `ARCH` | Normalized arch (`amd64`, `arm64`, `wasm`, etc.) |
|
||||
| `IS_AMD64` | x86_64 |
|
||||
| `IS_ARM64` | arm64/aarch64 |
|
||||
|
||||
## Compiler Flags
|
||||
|
||||
`deps/Flags.cmake` defines `BASE_OPTIONS` (warning flags) and
|
||||
`BASE_DEFINITIONS`. Apply per-target to avoid polluting fetched
|
||||
dependencies:
|
||||
|
||||
```cmake
|
||||
target_compile_options(<target> PRIVATE ${BASE_OPTIONS})
|
||||
target_compile_definitions(<target> PRIVATE ${BASE_DEFINITIONS})
|
||||
```
|
||||
|
||||
## CMock Mock Generation
|
||||
|
||||
CMock generates mocks for C-compatible interfaces. Do not pass C++ class
|
||||
headers to this helper; use a suitable fake or mocking tool for C++ APIs.
|
||||
|
||||
`tests/CMakeLists.txt` provides a `cmock_generate_mock` helper function:
|
||||
|
||||
```cmake
|
||||
cmock_generate_mock(<target> "<absolute-path-to-header>")
|
||||
```
|
||||
|
||||
With optional config file:
|
||||
|
||||
```cmake
|
||||
cmock_generate_mock(<target> "<header>" "cmock_config.yml")
|
||||
```
|
||||
|
||||
Generated mocks go into `build/mocks/` as `Mock<name>.h/.c`.
|
||||
|
||||
## Coverage
|
||||
|
||||
Enabled via `-DENABLE_COVERAGE=ON`. Requires GCC or Clang + `gcovr`.
|
||||
Report at `build-cov/coverage/index.html`. Only `<src>/` sources are
|
||||
measured; Unity, CMock, and mocks are excluded.
|
||||
|
||||
## Sanitizers
|
||||
|
||||
`deps/Sanitizers.cmake` provides AddressSanitizer via `-DENABLE_ASAN=ON`.
|
||||
Incompatible with coverage.
|
||||
@@ -0,0 +1,217 @@
|
||||
---
|
||||
name: git
|
||||
description: Git workflow for the ctdd C/C++ starter template. Use when
|
||||
committing template or example changes, creating release tags, or following
|
||||
the branching and commit message conventions.
|
||||
---
|
||||
|
||||
# Git Skill
|
||||
|
||||
This repository is a reusable starter template for C and C++ projects.
|
||||
Treat its checked-in code as examples demonstrating the build and test
|
||||
setup, not as a required application API. Template releases should keep
|
||||
the starter structure and Unity/CMock workflows useful to derived projects.
|
||||
|
||||
## Commit Messages
|
||||
|
||||
Follow [Conventional Commits v1.0.0][cc] with the 50/72 rule.
|
||||
|
||||
[cc]: https://www.conventionalcommits.org/en/v1.0.0/
|
||||
|
||||
### Format
|
||||
|
||||
```
|
||||
<type>[optional scope][!]: <subject>
|
||||
|
||||
<body>
|
||||
|
||||
[BREAKING CHANGE: <description>]
|
||||
Co-authored-by: <Name> <email>
|
||||
```
|
||||
|
||||
- Subject: max 50 characters; use imperative mood and no period.
|
||||
- Wrap body lines at 72 characters. Keep the message concise.
|
||||
- Separate the subject from the body with a blank line.
|
||||
- Use Conventional Commit types such as `feat`, `fix`, `docs`, `chore`,
|
||||
and `ci`; scopes are optional.
|
||||
- Mark breaking changes with `!` and/or a `BREAKING CHANGE:` footer.
|
||||
- No em dashes (`—`). Use a colon or rewrite the sentence.
|
||||
|
||||
Always include one `Co-authored-by:` trailer per contributing agent or
|
||||
model, using `<Name> <email>`:
|
||||
|
||||
- Name: human-readable model name, e.g. `Qwen 3.8 27B`.
|
||||
- Email local part: lowercase model identifier, replacing invalid
|
||||
characters with dots. If the model is unknown, use the product name.
|
||||
- Email domain: the service that ran the model, using its real domain.
|
||||
For self-hosted services, use your own domain. Use
|
||||
`<runtime>.local` only for local inference with no service domain.
|
||||
|
||||
Examples:
|
||||
|
||||
```
|
||||
Co-authored-by: Qwen 3.8 27B <qwen3.8.q3_k_xl@lmstudio.local>
|
||||
Co-authored-by: GPT-5.6 Luna <gpt5.6.luna@openrouter.ai>
|
||||
Co-authored-by: Claude Sonnet 4.5 <claude.sonnet4.5@github.com>
|
||||
```
|
||||
|
||||
The corporate commit-msg hook rejects these trailers, agent email
|
||||
addresses, `.local` domains, and free-text descriptions. Skip the hook
|
||||
with `--no-verify` when committing.
|
||||
|
||||
### Types
|
||||
|
||||
| Type | Use |
|
||||
| ---------- | ---------------------------------- |
|
||||
| `feat` | New feature or module |
|
||||
| `fix` | Bug fix |
|
||||
| `docs` | Documentation only |
|
||||
| `chore` | Build, deps, config, housekeeping |
|
||||
| `ci` | CI/CD changes |
|
||||
| `refactor` | Code change without feature or fix |
|
||||
| `test` | Adding or changing tests |
|
||||
| `style` | Formatting, whitespace, semicolons |
|
||||
|
||||
### Examples
|
||||
|
||||
Good:
|
||||
|
||||
```
|
||||
feat: add stopwatch timer
|
||||
|
||||
Replace Hello World with a live stopwatch that prints elapsed time
|
||||
in HH:MM:SS.mmm format, updating every 10ms with color output.
|
||||
|
||||
Co-authored-by: GPT-5.6 Luna <gpt5.6.luna@openrouter.ai>
|
||||
```
|
||||
|
||||
```
|
||||
fix: clear Unity INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
|
||||
|
||||
CMake rejects the path inside the build tree on newer versions.
|
||||
|
||||
Co-authored-by: GPT-5.6 Luna <gpt5.6.luna@openrouter.ai>
|
||||
```
|
||||
|
||||
```
|
||||
chore: bump CMock to v2.6.0
|
||||
|
||||
Co-authored-by: GPT-5.6 Luna <gpt5.6.luna@openrouter.ai>
|
||||
```
|
||||
|
||||
Bad:
|
||||
|
||||
```
|
||||
added a new thing # no type, lowercase, vague
|
||||
feat: add stopwatch # no body for a significant change
|
||||
feat: add stopwatch timer. # trailing period
|
||||
feat: add timer — it's fast # em dash not allowed
|
||||
```
|
||||
|
||||
## Committing
|
||||
|
||||
Stage changes:
|
||||
|
||||
```sh
|
||||
git add -A
|
||||
```
|
||||
|
||||
Write the complete message, including co-author trailers, to a message
|
||||
file, then commit while skipping the rejecting hook:
|
||||
|
||||
```sh
|
||||
git commit --no-verify -F <message-file>
|
||||
```
|
||||
|
||||
## Tagging
|
||||
|
||||
This project uses semantic versioning for template releases.
|
||||
|
||||
### Creating a tag
|
||||
|
||||
Create the tag:
|
||||
|
||||
```sh
|
||||
git tag -a v0.1.0 -m "Release v0.1.0"
|
||||
```
|
||||
|
||||
Push the tag:
|
||||
|
||||
```sh
|
||||
git push origin v0.1.0
|
||||
```
|
||||
|
||||
Tag messages follow the same rules as commit messages: no em dashes,
|
||||
wrapped at 72 characters.
|
||||
|
||||
### Tag naming
|
||||
|
||||
| Version | Meaning |
|
||||
| -------- | ------------------------------------ |
|
||||
| `v0.x.0` | Minor changes, breaking template API |
|
||||
| `v0.x.y` | Patch changes, backward-compatible |
|
||||
| `v1.x.0` | Major release |
|
||||
|
||||
### When to tag
|
||||
|
||||
- After merging a feature branch that changes the template structure
|
||||
- Before sharing the template with others
|
||||
- When CMakeLists.txt, deps/, or build system changes could affect
|
||||
projects using this template
|
||||
|
||||
### Listing tags
|
||||
|
||||
```sh
|
||||
git tag -l
|
||||
```
|
||||
|
||||
### Deleting a tag
|
||||
|
||||
Delete the local tag:
|
||||
|
||||
```sh
|
||||
git tag -d v0.1.0
|
||||
```
|
||||
|
||||
Remove the remote tag:
|
||||
|
||||
```sh
|
||||
git push origin --delete v0.1.0
|
||||
```
|
||||
|
||||
## Branching
|
||||
|
||||
For local development:
|
||||
|
||||
```sh
|
||||
git checkout -b feat/add-counter
|
||||
```
|
||||
|
||||
Branch naming:
|
||||
|
||||
| Prefix | Use |
|
||||
| -------- | ------------- |
|
||||
| `feat/` | New feature |
|
||||
| `fix/` | Bug fix |
|
||||
| `chore/` | Housekeeping |
|
||||
| `docs/` | Documentation |
|
||||
|
||||
## Common Commands
|
||||
|
||||
| Command | Use |
|
||||
| ----------------------- | --------------------------------- |
|
||||
| `git log --oneline -10` | Recent history |
|
||||
| `git diff --staged` | Check staged changes |
|
||||
| `git status` | Current state |
|
||||
| `git reset HEAD~1` | Undo last commit (keep changes) |
|
||||
| `git rebase -i HEAD~3` | Interactive rebase last 3 commits |
|
||||
|
||||
## Checklist Before Committing
|
||||
|
||||
- [ ] Tests pass: `ninja -C build check`
|
||||
- [ ] Commit message follows 50/72 rule
|
||||
- [ ] Conventional commit type used
|
||||
- [ ] Co-author trailer for every contributing agent or model
|
||||
- [ ] No em dashes
|
||||
- [ ] No large unchanged regions reformatted
|
||||
- [ ] No speculative code or unused imports
|
||||
@@ -0,0 +1,301 @@
|
||||
---
|
||||
name: tdd
|
||||
description: Test-driven development with Unity and CMock for C and C++
|
||||
projects started from the ctdd template. Use when adding modules, writing
|
||||
tests, or following Red-Green-Refactor.
|
||||
---
|
||||
|
||||
# TDD Skill
|
||||
|
||||
This repository is a starter template, and its checked-in examples are C.
|
||||
Use these workflows as examples when building a C or C++ project from the
|
||||
template; do not treat the sample modules as required product features.
|
||||
Unity is used for both C and C++ tests. The CMock examples below apply to
|
||||
C-compatible interfaces. CMock does not provide general mocking for C++
|
||||
classes, so choose an appropriate fake or mocking tool for C++ APIs. When a
|
||||
C++ test calls a C API, expose that API with C linkage.
|
||||
|
||||
> Replace `<src>/` with the project source directory (e.g. `ctdd/`, `src/`).
|
||||
> Replace `<module>` with the module name (e.g. `counter`, `timer`).
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Action | Command |
|
||||
| ----------------------- | ------------------------------------------------------- |
|
||||
| Configure (default) | `cmake -S . -B build -G Ninja` |
|
||||
| Configure (coverage) | `cmake -S . -B build-cov -G Ninja -DENABLE_COVERAGE=ON` |
|
||||
| Build | `ninja -C build` |
|
||||
| Run tests (full output) | `ninja -C build check` |
|
||||
| Run tests (summary) | `ninja -C build test` |
|
||||
| Run tests + coverage | `ninja -C build-cov coverage` |
|
||||
|
||||
## Red-Green-Refactor
|
||||
|
||||
Every change to `<src>/` follows this cycle:
|
||||
|
||||
1. **RED** : Write a failing test. Confirm it fails.
|
||||
2. **GREEN** : Write the minimum code to pass. Confirm it passes.
|
||||
3. **REFACTOR** : Clean up without changing behavior. Tests still pass.
|
||||
|
||||
Never skip the RED step. If the test passes immediately, you wrote the test
|
||||
before the implementation was missing.
|
||||
|
||||
## Adding a New Module
|
||||
|
||||
### 1. Write the header
|
||||
|
||||
Create `<src>/<module>.h` with the public prototype(s).
|
||||
|
||||
C:
|
||||
|
||||
```c
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
|
||||
int fn_name(int arg);
|
||||
```
|
||||
|
||||
C++:
|
||||
|
||||
```cpp
|
||||
#pragma once
|
||||
#include <cstddef>
|
||||
|
||||
auto fn_name(int arg) -> int;
|
||||
```
|
||||
|
||||
### 2. Write the test
|
||||
|
||||
Create `tests/test_<module>.c` for C or
|
||||
`tests/test_<module>.cpp` for C++. Choose a state-based Unity test for pure
|
||||
logic or an interaction-based test for a C dependency:
|
||||
|
||||
**State-based** (pure functions, no mocks):
|
||||
|
||||
```c
|
||||
#include "unity.h"
|
||||
#include "<src>/<module>.h"
|
||||
|
||||
void setUp(void) {}
|
||||
void tearDown(void) {}
|
||||
|
||||
void test_fn_name_returns_expected(void) {
|
||||
TEST_ASSERT_EQUAL_INT(42, fn_name(1));
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(test_fn_name_returns_expected);
|
||||
return UNITY_END();
|
||||
}
|
||||
```
|
||||
|
||||
A C++ state-based test uses a `.cpp` source and the same Unity assertions:
|
||||
|
||||
```cpp
|
||||
#include "unity.h"
|
||||
#include "<src>/<module>.h"
|
||||
|
||||
auto setUp() -> void {}
|
||||
auto tearDown() -> void {}
|
||||
|
||||
auto test_fn_name_returns_expected() -> void {
|
||||
TEST_ASSERT_EQUAL_INT(42, fn_name(1));
|
||||
}
|
||||
|
||||
auto main() -> int {
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(test_fn_name_returns_expected);
|
||||
return UNITY_END();
|
||||
}
|
||||
```
|
||||
|
||||
**Interaction-based** (mocking a C-compatible dependency with CMock):
|
||||
|
||||
```c
|
||||
#include "unity.h"
|
||||
#include "<src>/<module>.h"
|
||||
#include "Mock<dep>.h"
|
||||
|
||||
void setUp(void) { Mock<dep>_Init(); }
|
||||
void tearDown(void) { Mock<dep>_Verify(); Mock<dep>_Destroy(); }
|
||||
|
||||
void test_fn_calls_dep(void) {
|
||||
dep_fn_ExpectAndReturn(arg, expected);
|
||||
TEST_ASSERT_TRUE(fn_name());
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(test_fn_calls_dep);
|
||||
return UNITY_END();
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Register the test in `tests/CMakeLists.txt`
|
||||
|
||||
Add after existing test targets, before the `check` target. Use the source
|
||||
extension and compile feature for the test language. The current examples
|
||||
are C:
|
||||
|
||||
**State-based (no mock):**
|
||||
|
||||
```cmake
|
||||
add_executable(test_<module> test_<module>.c)
|
||||
target_include_directories(test_<module> PRIVATE "${CMAKE_SOURCE_DIR}")
|
||||
target_link_libraries(test_<module> PRIVATE <src>_<module> Unity::Unity)
|
||||
target_compile_features(test_<module> PRIVATE c_std_23)
|
||||
add_test(NAME test_<module> COMMAND test_<module>)
|
||||
list(APPEND TEST_TARGETS test_<module>)
|
||||
```
|
||||
|
||||
**Interaction-based (with mock):**
|
||||
|
||||
```cmake
|
||||
add_executable(test_<module> test_<module>.c)
|
||||
target_include_directories(test_<module> PRIVATE "${CMAKE_SOURCE_DIR}")
|
||||
target_link_libraries(test_<module> PRIVATE <src>_<module> Unity::Unity CMock::CMock)
|
||||
target_compile_features(test_<module> PRIVATE c_std_23)
|
||||
cmock_generate_mock(test_<module> "${CMAKE_SOURCE_DIR}/<src>/<dep>.h")
|
||||
add_test(NAME test_<module> COMMAND test_<module>)
|
||||
list(APPEND TEST_TARGETS test_<module>)
|
||||
```
|
||||
|
||||
For a C++ Unity test, use a `.cpp` test source and select the C++ standard
|
||||
for that target, for example:
|
||||
|
||||
```cmake
|
||||
add_executable(test_<module> test_<module>.cpp)
|
||||
target_include_directories(test_<module> PRIVATE "${CMAKE_SOURCE_DIR}")
|
||||
target_link_libraries(test_<module> PRIVATE <src>_<module> Unity::Unity)
|
||||
target_compile_features(test_<module> PRIVATE cxx_std_23)
|
||||
add_test(NAME test_<module> COMMAND test_<module>)
|
||||
list(APPEND TEST_TARGETS test_<module>)
|
||||
```
|
||||
|
||||
Replace `cxx_std_23` with the standard chosen for the derived project.
|
||||
|
||||
### 4. Stub the implementation
|
||||
|
||||
For C, create `<src>/<module>.c` with a dummy return:
|
||||
|
||||
```c
|
||||
#include "<src>/<module>.h"
|
||||
|
||||
int fn_name(int arg) {
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
For C++, create `<src>/<module>.cpp`:
|
||||
|
||||
```cpp
|
||||
#include "<src>/<module>.h"
|
||||
|
||||
auto fn_name(int arg) -> int {
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Register a C library in `<src>/CMakeLists.txt`:
|
||||
|
||||
```cmake
|
||||
add_library(<src>_<module> <module>.c)
|
||||
target_include_directories(<src>_<module> PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
target_compile_features(<src>_<module> PRIVATE c_std_23)
|
||||
```
|
||||
|
||||
For C++, use the `.cpp` source and the standard selected for the project:
|
||||
|
||||
```cmake
|
||||
add_library(<src>_<module> <module>.cpp)
|
||||
target_include_directories(<src>_<module> PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
target_compile_features(<src>_<module> PRIVATE cxx_std_23)
|
||||
```
|
||||
|
||||
### 5. Confirm RED
|
||||
|
||||
```sh
|
||||
ninja -C build check
|
||||
```
|
||||
|
||||
The test must fail. If it does not, something is wrong.
|
||||
|
||||
### 6. Implement and confirm GREEN
|
||||
|
||||
Write the real implementation. Run tests again:
|
||||
|
||||
```sh
|
||||
ninja -C build check
|
||||
```
|
||||
|
||||
All tests must pass.
|
||||
|
||||
## CMock Patterns
|
||||
|
||||
### Expecting a call with arguments
|
||||
|
||||
```c
|
||||
dep_fn_Expect(arg1, arg2);
|
||||
```
|
||||
|
||||
### Expecting a call and returning a value
|
||||
|
||||
```c
|
||||
dep_fn_ExpectAndReturn(arg, expected_value);
|
||||
```
|
||||
|
||||
### Verifying a call was NOT made
|
||||
|
||||
Do not set any `_Expect`. If the function is called, CMock fails
|
||||
automatically in `tearDown`.
|
||||
|
||||
### Multiple calls
|
||||
|
||||
```c
|
||||
dep_fn_ExpectAndReturn(first_call_arg, first_return);
|
||||
dep_fn_ExpectAndReturn(second_call_arg, second_return);
|
||||
```
|
||||
|
||||
Calls are matched in order.
|
||||
|
||||
## Test Naming
|
||||
|
||||
- `test_<function>_<scenario>`
|
||||
- Use present tense: `test_upper_converts_lowercase`
|
||||
- Cover: happy path, edge cases, boundaries, and error conditions
|
||||
|
||||
## Unity Assertions
|
||||
|
||||
| Assertion | Use |
|
||||
| -------------------------------- | ---------------- |
|
||||
| `TEST_ASSERT_TRUE(x)` | Boolean true |
|
||||
| `TEST_ASSERT_FALSE(x)` | Boolean false |
|
||||
| `TEST_ASSERT_EQUAL_INT(a, b)` | Integer equality |
|
||||
| `TEST_ASSERT_EQUAL_STRING(a, b)` | String equality |
|
||||
| `TEST_ASSERT_NULL(p)` | Null pointer |
|
||||
| `TEST_ASSERT_NOT_NULL(p)` | Non-null pointer |
|
||||
|
||||
## Coverage
|
||||
|
||||
To check coverage after tests:
|
||||
|
||||
```sh
|
||||
ninja -C build-cov coverage
|
||||
```
|
||||
|
||||
Open `build-cov/coverage/index.html` in a browser.
|
||||
|
||||
## Checklist
|
||||
|
||||
Before considering a task done:
|
||||
|
||||
- [ ] Header declares the public API
|
||||
- [ ] Test covers at least one happy path and one edge case
|
||||
- [ ] Test registered in `tests/CMakeLists.txt` with the correct language
|
||||
- [ ] Library registered in `<src>/CMakeLists.txt` (if new module)
|
||||
- [ ] `ninja -C build check` passes with zero failures
|
||||
- [ ] CMock is used only for C-compatible interfaces
|
||||
- [ ] C++ targets select the intended C++ standard
|
||||
- [ ] C++ code follows the trailing-return-type convention
|
||||
- [ ] East const (`char const*`) and `snake_case` naming are used
|
||||
Reference in New Issue
Block a user