Unit Testing And Other Embedded Software Catalysts

Dr. Surly’s School for Mad Scientists: Introduction to Test Driven Development for Embedded & System Software in C

Last updated 2022-01-10 | 4.6

- Develop Embedded and System Software in C using Unit Tests.
- Apply Test Driven Development practices and design patterns to your own projects.
- Produce quality
- maintainable
- and self-documented software designs through test-first thinking.

What you'll learn

Develop Embedded and System Software in C using Unit Tests.
Apply Test Driven Development practices and design patterns to your own projects.
Produce quality
maintainable
and self-documented software designs through test-first thinking.
Understand how to use the open source Unity test framework
Take over the world.

* Requirements

* You should have basic proficiency in C programming.
* You should have some experience with Embedded or Systems Programming. If you've ever dealt with a register or bit mask
* you're our kind of people.
* No prior testing experience is required.
* While certain tools are required for this course
* they're all free
* and we'll guide you through all necessary installation and configuration as we go.

Description

Welcome 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 course introduces the Unity framework, key principles, and a variety of techniques so that you can apply Unit Testing and Test Driven Development in complex and low-level C code. Once you’ve completed this material or if you’re already familiar with TDD and xUnit frameworks our course Interaction Testing, Mocking & Embedded Software in C 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:

  • Develop in C using Test Driven Development. Write real, executable tests on your first day.

  • Learn concepts from Agile, XP, Scrum, and Lean practices for producing well designed, high quality, scope-managed, and self-documented code.

  • Utilize the free, open source tool Unity in real-world testing scenarios. No toy examples.

  • Follow us through real-world programming examples and see techniques and patterns for unit testing tricky code.

  • Encounter big idea philosophies for process, design, and testing.

  • Apply your new skills to challenging practice problems.

  • Connect with a supportive community.

Learn How To Apply Unit Testing To Your Embedded and System C Software

You will learn skills that have become staples in higher level languages but are sadly underutilized in the C world. In particular, you will learn to write unit tests in the uniquely challenging setting of embedded and system software.

Of course, the test-driven techniques you will learn produce code that enables thorough, smart testing. But, a happy side effect of TDD is code that tends to adhere to generally good design principles. You won’t only be learning testing in this course but also good design.

This Course Includes:

  • 0x1D (29) Code-centered lectures

  • 0x05 (5) Development projects

  • 0x12 (18) Helpful resource-packed supplemental primers, guides, and how-to's

  • Links, quizzes, helpful hints, and more

Can’t decide? Need something more? Please write us at… [email protected]

Join us in our mission to take over the world (with quality embedded software)!

Who this course is for:

  • This course is for C developers seeking to learn Unit Testing and Test Driven Development. If you are new to the C language or programming for hardware, this course may be too advanced for you.

Course content

4 sections • 33 lectures

An Introduction to Dr. Surly's School for Mad Scientists Preview 01:39

Welcome to our mad scientist lab. If you’re going to take over the world some day, inevitably you're going to be building electronics and programming low level code. You may be insane, but you’re not dumb. You’re taking this course to learn structured and responsible testing practices for low-level code. We’re going to be working in C and using open source tools like Unity to get you writing tests as soon as possible for a variety of example projects. You learn best by doing and so there’s plenty of doing in this course.

If you want to know more about Dr. Surly, the patron saint of mad scientist firmware developers, you can read his much abridged life story. It’s one page, and it’s attached.

A Syllabus for Taking Over the World Preview 01:08

An overview of the material of this course and how it relates to our other courses, quizzes, homework, where to find the pencil sharpener, etc.

Unit Testing with Training Wheels Preview 01:17

Unit testing embedded and system code is a relatively new development. In fact, the tool we use in this course was created at a time when many thought such things couldn’t be done.

The nuts and bolts of Section 2 is to push off lots of yacking at you until later in favor of getting you writing tests as soon as possible. Don’t worry. We will address your inevitable questions soon enough. Please be patient.

What We Need to Get Started, Part 1 Preview 03:51

We need to get you set up before you tear into writing tests. That means being familiar with the documentation we provide and your options for a development environment. In this lecture we discuss:

  1. All the core documentation you’ll want to reference regularly plus a variety of thorough treatments of topics related to this course but outside its immediate scope.

  2. Options for development (a readymade web-based sandbox or do-it-yourself local environment).


Note: We are beginning the process of transitioning the course project development environment from web-based SourceLair (discussed in this video lecture) to locally-installed Docker that is discussed in the next lecture. Please choose SourceLair or Docker for developing your project. We apologize for any added complexity due to the new option.

What We Need to Get Started, Part 2 Preview 03:55

Here we introduce an alternative—and eventual replacement—for SourceLair as your development environment. All the needed tools and project materials are included in a Docker image you can execute locally. Please choose SourceLair or Docker moving forward.


Note: We are beginning the process of transitioning this course from using SourceLair to using a locally executed development environment packaged up as a Docker image. Executing commands at the SourceLair terminal shown in other lectures is virtually identical to doing so at the command line within the Docker environment.

Are We Ready? Preview 04:01

If you chose to use the web-based development sandbox we introduced in the previous lecture, in this lecture we walk you through that environment and how it will be used in the course. Together we will verify that your setup is working properly.


Note: Running commands in SourceLair’s terminal are virtually identical to doing the same using the Docker-based local development environment we introduced as an alternative to SourceLair in the preceding lecture. The big differences between SourceLair and the Docker-based environment are (A) Web-based vs. local execution (B) Using a web-based code editor vs. using your own favorite local code editor.

Debugging Tips For Unity Set Up and How To Get Help Preview 01:31

This lecture covers your options for asking questions not addressed in the course material. For instance, you may need help debugging issues in the previous step (lecture). Or, you may have specific technical or philosophical questions that arise during the rest of the course.

The testing setup we employ early on is easy to use and generally problem free. Our supplemental documents cover lots of issues and potential questions. But if you're stuck, you have several options for help.

Bam! Our First Test Preview 06:56

In this lecture we guide you through developing and running your very first shiny new unit tests using Unity!

Will It Pass?

A tiny pop-quiz to verify you understood the last section

The Source Preview 19:00

In this lecture we guide you through developing a full set of unit tests for a real source code module! Along the way we show you how to think through just what exactly should be tested and then how to structure your unit tests to accomplish this.

Challenge Accepted! Preview 00:18

We give you a challenge where you can apply the skills you’ve learned on your own.

Breaking It Down Preview 17:22

In this lecture we explain what's happening under the hood of these testing tools and why the tools were designed the way they are. We break down a project's code in diagrams to show how your source and test code live separately but in harmony.

We get into the nitty gritty of how and where you actually run your executable unit tests:

  • Locally (native)

  • In a simulator

  • On target

And we address the scope of testing approaches:

  • Unit

  • Integration

  • System

For more on the fine details of unit, integration, and system testing, please see our supplemental “Extra Goodness” document (document archive attached to Lecture 4): What’s the difference? Unit, Integration, and System Testing.

Lecture Appendix

If you want to really dig in to understand a testing framework like Unity:

  • Go ahead and look at Unity’s source code: https://github.com/ThrowTheSwitch/Unity/

  • Take a gander at MinUnit—A minimal unit testing framework for C in 3 lines of code: http://www.jera.com/techinfo/jtns/jtn002.html

It’s Alive! (Section 2 Review) Preview 00:31

Section Wrapup and Review

Source & Tests: Together at Last Preview 01:08

We introduce Section 3 and lay out how you can grow your source code and test code together, in parallel, at the same time.

The Flow Preview 20:33

In this lecture we walk you through creating a new embedded source module from scratch. You will begin building a real GPIO module and unit testing all the necessary register settings as you build up the code from requirements. You’ll be developing the source and the tests together. We identify and demonstrate good practices as we go.

A Few Thoughts On The Subject

We verify that you have this whole flow-thing down.

It’s TDD Preview 10:06

We introduce the concepts of Test-Driven Development and Behavior-Driven Development. Surprise! You’ve already been using these concepts. We explain their principles and many benefits… and how they apply to building up a suite of unit tests.

Getting Philosophical Preview 00:34

In this lecture we share useful resources on the concepts covered in the previous lecture. Additionally we point you to a variety of studies on and philosophical discussions about the value and tradeoffs of unit testing itself. With the materials of this lecture you will be able to speak intelligently to your colleagues about both the pros and cons of unit testing practice. We also assign some homework.

A Second Helping Preview 06:52

In this lecture we further develop the embedded GPIO module we began in this section and we pick up the pace a little. We continue demonstrating test-first and behavior-driven test development for additional pieces of the GPIO interface.

And, we specifically address good practices for working with:

  • Newly implemented but mostly blank functions

  • Error codes and conditions

  • Bounds checking

Registers are fairly simple—except when they’re not. Different processors use different styles of register interaction and produce a variety of behaviors. See our supplemental document (attached in Lecture 4): Testing Special Cases for more perspective on testing tricky register interactions.

Your Turn Preview 00:32

We assign some homework for you in the GPIO module of this section to complete using your new skills.

Seeking a Mantra Preview 07:37

In this lecture we take a step back and discuss two important concepts underlying the decisions we've been making along the way:

  • Do the Simplest Thing That Could Possibly Work

  • Ya Ain’t Gonna Need It

These are powerful concepts that may feel a little wrong at first. We explain why they are a good way to work and how testing plays nice with these approaches. We then demonstrate them in action in testing the Init() function of our GPIO module.

Pop Quiz!

We give another brief quiz to verify our progress.

Less Simple Is Still Simple Preview 12:17

In this lecture we work through a case that seems complicated on its surface. Our mantra of Simplest Thing That Could Possibly Work seems to lead us to call source functions in our unit tests that are outside the test case under development. We show how to think through decomposing these rather common cases into tests and also introduce setUp() and tearDown() within the testing framework.

Homework Preview 00:11

We assign the final homework assignment for this section. Once completed, you will have a fully working embedded GPIO module and a full suite of unit tests to verify that it works.

Section 3 Review Preview 00:50

Section Wrapup & Review

Where in Unit Testing Are We? Preview 01:06

We discuss where all our work so far belongs in the grand scheme of things and explain how and where our testing approach applies beyond only the work we've done so far.

This section will help you think about the “edges” of your code and how testing applies to common scenarios of state machines, math functions, and data containers.

For an in-depth look at testing special cases (e.g. main(), for() loops, various register setting scenarios), see our supplemental “Extra Goodness” document (in the archive attached to Lecture 4): Testing Special Cases.

Ghost in the Machine Preview 25:17

In this lecture we walk through the development and testing of a State Machine module used to implement a protocol parser. We discuss and demonstrate how all our recently developed skills apply quite well to this sort of module.

Your Ghosts Preview 00:15

You complete the protocol parsing state machine module from the previous lecture using everything you’ve learned.

It Adds Up Preview 12:18

We walk you through the development of Math Function module with our approach by demonstrating the development of a well-tested low pass filter.

Add Your Own Preview 00:30

You complete the Fibonacci module from the previous lecture on your own using all that you’ve learned.

Containing our Excitement Preview 11:32

We walk through the development of a data container module (a circular buffer) using all our newly acquired methods and skills.

Contain Yourself Preview 00:40

Once again you complete the circular buffer implementation from the previous lecture using everything you’ve learned along the way.

Where to, Mack? (Section 4 Review) Preview 01:32

We review all the work we’ve done in all the sections of our course and where it falls in the scheme of things. Go on towards world domination with your mad scientist plans.

For an in-depth look at testing special cases (e.g. main(), for() loops, various register setting scenarios), see our supplemental “Extra Goodness” document (in the archive attached to Lecture 4): Testing Special Cases. Heck, take a look at all the documents in the archive as they will address many issues we can’t cover in the main course.