
So... what is this class about?
A screencast of setting up and using the course development environment. This video shows the steps of the next lecture put into action.
For your local development environment we’ll be using a single, custom-made Docker container created just for this course. Instead of the messy process of installing a bunch of separate tools and runtimes, you only need to install Docker and fetch the image we’ve prepared for you.
An introduction to the course project.
Reviewing the project requirements before the Requirements Review Meeting
Transforming requirement specifications into feature lists.
Introduction to using Expect.
Introduction to Ceedling.
How to test main().
Homework 1-1
A deep dive into the concept of mocking.
We build up a small manually-mocked project (see `DIY` folder in course source code). This is for those who like to learn how things work as well as those who don’t quite grok how their compiler and linker make the magic happen.
We prepare to work on our second feature by refining our architecture some. This is a peek at how design happens — more on this later — and covers a simple case of mocking again.
Drive LEDs in some way that lets us check all digital inputs.
Homework 1-2
An optional unit with links to in-depth discussions of how CMock’s generated mocks operate.
Let's fix our blinking light. We want it to be a regular blink rate.
This lecture justifies starting test-driven development in main, shows how spikes reveal subsystem knowledge, and outlines automation decisions and throwaway versus releasable features.
Homework 2-1
We introduce the Model-Conductor-Hardware pattern, using it to test drive our Analog subsystem. We also play with our module script to destroy the Analog files after we create a triad of MCH files!
We get the opportunity to reuse our Filter from the previous course. We discuss why this form of reuse isn’t all that rare but how we prepared ourselves for this style of reuse. We add in our filter code.
Iteration 2-2
Now that we have seen some good examples of TDD with interaction tests, we can revisit the question of why we are using mocks in the first place.
Our filter works-ish… except that a proper filter relies on a particular corner frequency. This means processing at a particular rate. So we test-drive our code development to write the actual timer code now.
Iteration 2-3
We check on how we did during the last two iterations, and we plan out what we’re going to accomplish in the next iteration.
It’s time to start talking to our device. Instead of implementing complicated messages like our results commands, we’re going to start with the simplest messages we can find.
We’ll be implementing the Version command first. We test drive the command handler using MCH again, though we call it Handlers-Conductor-Hardware for clarity. We also introduce _ReturnThruPtr and _ExpectAnyArgs for validating CommandHardware_CheckForMsg().
Iteration 3-1
We reuse the parser and the buffer from our first course.
Iteration 3-2
We learn another useful pattern, one particularly well suited for reuse.
Homework 3-3
We roll out our second command handler. This one actually requires our parser to pass in data!
We add our third command handler, this time enabling us to fetch results. We see how refactoring goes well with testing.
This is a lecture to review all that we've talked about so far.
Homework 3-4
How did this iteration go? What's on the agenda for next iteration?
We determine what we’re working on for the fourth iteration. We decide to focus on triggering first, then some related configurability with the parameter system. We end with a really short story about giving LED feedback.
From here on out we focus on the main flow of development.
We refactor our Capture system in preparation for capturing on a trigger.
Homework 4-1
We present concepts on how to design code and tests to minimize future work in the face of inevitable change and maintenance.
We build our first trigger and talk about testing static variables.
Homework 4-2
We start adding Trigger Modes and use this to introduce how custom Unity handlers make for much more awesome CMock failure messages.
Homework 4-3
We begin building our parameter system and configure our tests to process integers as hex codes instead of numerals.
Unity and CMocks’s :treat_as: support helps maintain CMock’s cross platform ability as well as provides you useful shortcuts for displaying your own custom C types.
We add the Param Set command and introduce the Observer pattern to help us build it.
Homework 4-4
Configure and test analog channel selection in an embedded capture module using a channel mask, refactoring data handling, and unit tests to ensure accurate buffer headers and results.
We visit our finished feature list, admire our final test suite size, and we show a video walkthrough of a manual system test. Dr Surly is happy!
There’s always more to learn. Here are resources on how to continue your learning.
Welcome (Back) to Dr. Surly’s School for Mad Scientists!
Unit Testing and Test Driven Development help smart, capable developers like you create robust, reliable, and maintainable software that lets you sleep soundly at night. In this course you will apply these concepts to embedded code and system software in C.
This material builds on the foundation of our first course, Unit Testing & Other Embedded Software Catalysts. If you’ve taken our first course or you’re already familiar with TDD and xUnit frameworks, this course is a great next step.
Dr. Surly’s School for Mad Scientists
When you’re trying to take over the world you learn two things quite quickly. First, you end up building lots of technology like death rays and such that requires high quality firmware. Second, minions, climate-altering satellites, and lairs are expensive. While Dr. Surly’s lab has become quite proficient at software design and testing, supplemental revenue to fund all manner of villainy is a necessary evil. It’s all part of the standard world domination business model, and you get to benefit.
In This Course You Will:
Learn interaction-based testing with stubbing and mocking in a real-world project.
Use new tools! CMock & Ceedling complement the C testing tool Unity.
Iteratively refactor already working code with the support of your test suite.
See techniques and patterns for unit testing tricky code.
Try strategies for prioritizing and planning an embedded project.
Encounter big idea philosophies for process, design, and testing.
Connect with a supportive community.
Learn by Doing—Build a Real-World Project from Start to Finish
The end result of this course is an actual, functional application that can run on real hardware. No simplistic exercises or toy examples. The hardware isn’t necessary for this course, but if you do have the hardware, it will serve as final proof that your code works. And, the final deliverable might just be handy for other projects too.
The project is the mechanism for learning in this course. We’ll grow the project from requirements using a structured, iterative process much as you would in a real project. We teach development, testing, design, and process skills as we build this project, showing where they are applicable in real life.
You will learn key concepts first from us demonstrating the skills by example, then through guided use, and finally as homework assignments that allow you to practice the skill on your own as you implement your project.
This Course Includes:
0x01 (1) Large project from requirements to finished product
0x19 (25) Code-centered lectures
0x0D (13) Code-exercises contributing to the main project
0x1F (31) Helpful resource-packed supplemental primers, guides, and how-to’s
0x195 (405) Minutes of thorough video lectures
Links, quizzes, helpful hints, and more
Have questions? Please write us at… tdd@throwtheswitch.org
Join us in our mission to take over the world (with quality embedded software)!