assert, and judge whether a passing suite is actually thorough. The hands-on practice happens through the assert walkthrough in Section 5; the lab puts you on the other side of the autograder, writing the tests that hold a module accountable.
By the end of this lesson, cadets will be able to:
assert and a simple test runner. (Outcomes 3, 7)Complete before class. These set the vocabulary we will use.
| Reading | Source |
|---|---|
Test planning and unit testing in depth: test plans, the normal / edge / error breakdown, assert, and judging suite thoroughness. |
Supplementary notes (instructor-written) |
There is no Beej chapter for this lesson. The instructor-written notes are the assigned reading; they line up section for section with the overview in Section 4.
assert macro you will use in class.You have been on the receiving end of tests since Lesson 1: write code, push it, see whether the autograder turns green. Today you learn to build that green yourself. Testing is not a chore you do at the end; it is how you decide whether code can be trusted at all. The material below is the spine of the lecture and the reference you will use during the lab.
The Lesson 26 deck covers why we test, the assert macro, the normal / edge / error breakdown of a test plan, writing unit tests with a simple runner, and how to judge whether a suite is thorough. The slides are the spine of the in-class lecture; the assert walkthrough is where you practice each idea hands-on.
Code that compiles is not code that works. A function can build cleanly, run without crashing, and still return the wrong answer on inputs you did not try. Testing is the discipline of trying those inputs on purpose, before your users (or your teammates, or a graded review) try them for you.
There is one rule that shapes everything else in this lesson: tests can show the presence of bugs, but never their absence. A passing test tells you the code is correct for that one case. It says nothing about the cases you did not write. That is why a test plan matters more than raw test count: thoroughness comes from choosing the right cases, not from piling up more of the same.
C's simplest test tool lives in <assert.h>. You give assert a condition. If the condition is true, nothing happens and the program continues. If it is false, the program prints the failing expression with its file and line, then aborts immediately.
That hard, loud stop is the point. A bug cannot hide when assert halts the program on it. The core unit-test pattern is one line:
The left side is what your code produced; the right side is the answer you worked out by hand before running it. One caution that bites every C programmer eventually: use == for comparison, never a single =. A single = is assignment, which would overwrite your value and quietly pass. Practice this in the assert walkthrough in Section 5.
A test plan is a short list, written before you write the tests, of the cases that matter. The reliable way to build one is to walk three categories for every function:
| Category | What it means |
|---|---|
| Normal | Ordinary, in-range input the function plainly should handle. A populated list, a typical value. |
| Edge | The boundaries. Empty input, a single element, a value sitting exactly on a threshold, the largest allowed value, all-equal or all-negative data. |
| Error | Input the contract calls out specially: a value not found, a count of zero that must not divide, anything the function is supposed to reject or handle defensively. |
Most bugs live at the edges and error conditions, not in the normal cases. A function that passes every normal case can still divide by zero on an empty list or return an off-by-one rank for the top element. Writing the plan first forces you to name those cases before the code lulls you into thinking it works.
A unit test checks one function in isolation. In this course a test is a small void function full of assert calls. You build an input, call the function, and assert on the result:
Because a failed assert aborts the whole program, running many tests in one run needs a little infrastructure: a test runner that runs each test in isolation so one failure does not hide the rest. The lab provides that runner; you write the tests and register them. You have seen this multi-file shape since Lesson 20: a header declares the contract, an implementation honors it, and now a third file tests it.
Once you have a suite, the last skill is judging whether it is any good. The trap is to count assertions: a suite with fifteen assertions all on typical mid-range inputs is weaker than a suite of six that reaches the empty case, the boundary case, and the error case. Coverage of categories beats raw count.
A practical way to judge a suite: for each function, can you point to at least one normal case, one edge case, and one error case? If a whole category is missing, that is exactly where a bug will slip through. The lab makes this concrete by grading your suite against a buggy module: you earn credit for the bugs your tests actually catch, and the only way to catch them all is to test the boundaries. All of this becomes hands-on in the assert walkthrough in Section 5; the self-check quiz there lets you rehearse the normal / edge / error judgment before the lab.
Three things to do in class. Use the checklist to track your progress.
Thirteen tasks across three sections. Type one line at a time at the prompt. The terminal shows what your program did when it ran; the right pane is your running test report.
Enter your name. It will appear on the completion screen so you can include it in your screenshot for the Lesson 26 reflection.
assert: the simplest test oracle in C. Type each line at the prompt. The terminal shows what your program did when it ran; the right pane is your running test report. A failing assertion stops the program cold, just like the real assert.h.assert macro. The task card tells you what to type next; only the expected line advances the walkthrough so the test report stays predictable. Mistype twice and the hint button will pulse. When you finish, free mode unlocks so you can write your own assertions.
Six questions. Pick or type your answer, submit, and read the feedback before moving on. Pass at 70% or above; below that, review and take it again.
Enter your name. It will appear on the score card so you can include it in your screenshot for the Lesson 26 reflection.
tests.c through GitHub Classroom before Lesson 27.tests.c, the autograder output you do not understand, and the case you are stuck testing. Specific questions get unstuck quickly. A course Resources section collects the standing references (the DFCS C Programming Standard, the Git troubleshooting card, and more) for self-service.