Stacks

Write Unit Tests for Untested Code in C with Atlas (2026)

Updated 8 min read

Atlas adds real unit tests to a C module that has none, matching the conventions the repo already uses instead of inventing its own. Atlas reads the target .c file and its header, uses the lsp tool's documentSymbol operation to enumerate every exported function so no public symbol is missed, greps for an existing test file to copy the repo's Unity framework setup and naming style, writes the new test with the write tool, and then actually runs it with Unity via ctest. The run is the point: a test that was never executed is not a test.

How does Atlas write unit tests for an untested C module?

Atlas reads the target C module and its header, then uses the lsp tool's documentSymbol operation to enumerate its exported symbols so no public function is missed. A src/parser.c file with 9 functions declared in include/parser.h needs coverage for the ones the header exposes, not just the one you were thinking about.

Untested C code is usually untested because its surface was never made explicit. The header is the contract, and documentSymbol turns that contract into a checklist. Atlas walks it: every function declared in include/parser.h gets considered, and the static helpers in src/parser.c that no other translation unit can reach are deliberately excluded. Atlas indexes code by AST declarations using tree-sitter, not blind line windows, so the enumeration is over real declarations rather than lines that look like function signatures inside a comment or a macro. The result is a list of functions to cover, ordered by the ones with the most branching.

How does Atlas match my repo's existing C test conventions?

Atlas greps for an existing test file and copies the repo's framework, include style, and naming convention. In a C project that means opening test/test_buffer.c and reading 3 things: how it includes unity.h, how setUp and tearDown are defined, and how the runner registers each RUN_TEST case.

C test suites are idiosyncratic in a way that most languages are not. One project registers tests by hand in a main function, another generates the runner, another wires everything through CMakeLists.txt and a ctest add_test call per file. There is no single right answer, only the answer this repo already picked. Atlas copies the repo's existing test conventions rather than inventing its own, which is why the grep step is not optional. Atlas searches code with hybrid semantic and keyword retrieval fused by reciprocal rank fusion, so finding the closest analogous test file to the module under test is a query rather than a directory crawl.

What does the Atlas write tool do before creating a C test file?

The Atlas write tool shows the diff in the permission prompt before anything lands on disk, so 0 bytes are written until you approve. A new test/test_parser.c, the CMakeLists.txt entry that registers it with ctest, and any fixture data are all reviewed first.

Review before write matters more in C than in most languages, because a test file is also a compilation unit. A test that includes the wrong header, or that is registered in CMakeLists.txt in a way that pulls in a second definition of main, breaks the build rather than failing cleanly. Atlas computes a unified diff for every file edit and surfaces it for approval before writing, so those mistakes are caught at review time. Every Atlas tool call is also permission-gated against allow, ask, and deny rules before it runs, so the write is an approved action, not an assumed one. clang-format then normalizes the new file to the repo's style.

Why does Atlas actually run the C tests it writes?

Atlas runs the suite with the bash tool and reads the failures, because a test that was never executed is not a test. Output over 2000 lines or 50 KB is truncated in context and the full log is saved to a file you can read, which matters when a C build prints a compiler warning per translation unit.

An unexecuted C test is a liability: it might not compile, it might assert on the wrong thing, it might pass vacuously because the assertion is inside a branch that never runs. Atlas runs Unity via ctest and reads the real output. Where the build and test output is large, the Atlas bash tool truncates its displayed output at 2000 lines or 50 KB and retains the complete log to a file whose path it reports, so a linker error buried under 400 warnings is still findable with grep. Atlas iterates with the edit tool until the suite is green, keeping progress in a todowrite list when the module is large.

How does Atlas keep a large C test-writing effort on track?

Atlas keeps progress in a todowrite list when the C module is large, with one entry per exported function from include/parser.h. A module with 9 public functions and 3 covered is visibly one third done, rather than looking finished because the last test run was green.

The trap in adding tests to legacy C is that green means nothing about coverage. Three passing Unity tests over a nine function header is a green ctest run and an untested module. The todowrite list, seeded from the lsp tool's documentSymbol enumeration, is what keeps that honest: each exported function is an entry, and an entry closes only when a real Unity assertion exercises it. Atlas fans out work to subagents that can run in the foreground or in parallel background sessions, so a large C codebase with several untested modules can be worked in slices. Conan resolves whatever test dependencies the project pulls in, and clang-format keeps every new test/ file consistent with the rest.

Step by step

  1. 01Run atlas in a C project with a Makefile so Atlas can read your headers, source files, and build rules.
  2. 02Have Atlas read the module under test, then run the lsp tool's documentSymbol operation to enumerate the functions declared in its header so no public symbol is missed.
  3. 03Grep for an existing test file such as test/test_buffer.c to copy the repo's Unity framework setup, include style, and naming convention.
  4. 04Write the new spec file with the write tool, which shows the diff in the permission prompt before anything lands on disk.
  5. 05Register the new test with ctest through the repo's existing build entry, matching how the sibling test file is registered.
  6. 06Run the suite with Unity via ctest through the bash tool; output over 2000 lines or 50 KB is truncated and the full log is saved to a file you can read.
  7. 07Iterate with the edit tool until the suite is green, keeping one todowrite entry per exported function when the C module is large.
  8. 08Run clang-format on the new files under test/, review the unified diff, then commit.

Frequently asked questions

how to add unit tests to a C module that has none
Have Atlas read the module and run the lsp tool's documentSymbol operation to enumerate every function declared in its header, grep for an existing test file to copy the repo's Unity conventions, write the new test with the write tool, and run it with Unity via ctest.
will an AI agent invent its own C test framework instead of using mine
Atlas greps for an existing test file first and copies the repo's framework, include style, and naming convention. In a C project that means matching how test/test_buffer.c includes unity.h, defines setUp and tearDown, and registers each RUN_TEST case.
does Atlas run the C tests it writes or just write them
Atlas runs them. The documented workflow writes the spec with the write tool and then executes the suite with Unity via ctest through the bash tool, because a test that was never executed is not a test. Failures are read and fixed with edit until the suite is green.
how do I see the full ctest output when the build prints hundreds of warnings
The Atlas bash tool truncates displayed output at 2000 lines or 50 KB and saves the complete log to a file, reporting the path. Read that file to find the linker error or failed assertion buried under compiler warnings from every translation unit.
how do I know a C module is actually covered and not just green
Green means the tests that exist passed, not that the module is covered. Atlas seeds a todowrite list from the exported functions the lsp tool's documentSymbol found in the header, so a module with 9 public functions and 3 tested is visibly incomplete.
does Atlas ask before creating a new test file in my C repo
Yes. The write tool shows the diff in the permission prompt before anything lands on disk, and every Atlas tool call is permission-gated against allow, ask, and deny rules. A new test/test_parser.c and its build registration are both reviewed before they exist.
atlas C project setup
Run atlas in a project with a Makefile. Atlas reads your headers, source files, and build rules, and can find memory leaks or add Unity tests, with the diff reviewed before make. Tests run as Unity via ctest, dependencies resolve through Conan, and formatting runs through clang-format.
should I test static functions in a C file
The documented Atlas workflow enumerates the exported symbols with the lsp tool's documentSymbol operation, which is the header's contract. Static helpers in the .c file that no other translation unit can reach are not part of that public surface, so coverage starts with what include/ declares.

Try Atlas in your terminal

The terminal-native AI coding agent. Free core, single binary.

Install Atlas

Related guides

Write Unit Tests for Untested Code with Atlas in 2026

How to write unit tests for untested code with Atlas in 2026: the lsp tool enumerates exported symbols, grep copies repo conventions, and bash actually runs the suite.

Atlas for C in 2026

Atlas is a terminal-native AI coding agent for C in 2026. Run it in a project with a Makefile, have it find memory leaks or add Unity tests, and review the diff.

Self-review your working diff before committing in C with Atlas in 2026

C developers in 2026 use Atlas to self-review uncommitted changes, catching mistakes before review or CI. Atlas integrates with `clang-format`, `Unity via ctest`, and `Conan` for C code quality.

Locate Where a Behavior Is Implemented in C with Atlas (2026)

Locate where a behavior is implemented in a C codebase with Atlas in 2026. Combine codebase_search, ripgrep-backed grep, and the lsp tool to find the exact .c file and symbol.

Run Atlas Headless in CI for C Projects in 2026

Automate C code quality and refactoring in CI pipelines with Atlas. Run Atlas headless to get machine-readable output for Unity via ctest, Conan, and clang-format projects in 2026.

Add a Regression Test for a C Bug Fix with Atlas in 2026

Lock in C bug fixes with Atlas in 2026. Learn to write failing Unity via ctest regression tests, apply fixes, and verify with real C toolchain commands like Conan and clang-format.

Diagnose a hanging or long-running command in C with Atlas in 2026

C developers in 2026 use Atlas to diagnose hanging or slow commands like `make` or `Conan`. Quickly identify if a C build is blocked on input or genuinely slow, and get unstuck efficiently.

Run the Test Suite and Triage the Failures in C With Atlas (2026)

Turn a wall of red C test output into a list of distinct root causes. Atlas runs Unity via ctest, retains the full log when output truncates, and tracks each cause.

Browse this resource hub