Unit testing RTOS dependent code – RTOS Test-Double

When you’ve got legacy code that depends on the Real-time Operating System, you have a challenge to get your code off the target for unit testing. If you want to test with the concurrency provided by the RTOS, these are not really unit tests, and you won’t be able to write thorough tests, and you need unit tests to be through.

You’re going to need to make a test-double so you can get your code off the RTOS and into your development system for unit testing. In this article we’ll go through the steps to get started.

Continue reading

Hiding Non-standard C Keywords for Off-Target Testing

Some silicon vendors extend the C language so the programmers can easily interact with the silicon. Using these extensions tie production code to the silicon vendors compiler and consequently the code can only run on the target system. This is not a problem during production, but is a problem for off-target unit testing.

The good news is that we may be able to get around this problem without having to change production code, one of our goals when adding tests to legacy code.
Continue reading

#include Test Double

It’s day one of adding tests to your legacy C code. You get stopped dead when the compiler announces that the code you are coaxing into the test harness can’t be compiled on this machine. You are stuck on the Make it compile step of Crash to Pass.

Moving your embedded legacy C code (embedded C code without tests) into a test harness can be a challenge. The legacy C code is likely to be tightly bound to the target processor. This might not be a problem for production, but for off-target unit testing, it is a big problem.

For C we have a limited mechanisms for breaking dependencies. In my book, I describe at length link-time and function pointer substitutions, but only touch on preprocessor stubbing.

In this article we’ll look at #include Test-Double as a way to break dependencies on a problem #include file.

Continue reading

Spying on Embedded ‘asm’ directives

Sometimes embedded developers have to use inline assembler instructions to get better control of the processor, or to improve performance. How should we deal with those when we’re doing TDD and testing off the target?

What’s the problem? The embedded asm statements cause compilation errors if the assembler instructions are not part of the off-target test platform instruction set. Also some of the instructions might not be legal in the test environment. This article shows how to insert a test double for the asm directives with gcc and CppUTest.

Continue reading

Legacy Code Change – a Boy Scout Adds Tests

Here is a legacy code change policy for a team adopting TDD that has a legacy code base:

  • Test-drive new code
  • Add tests to legacy code before modification
  • Test-drive changes to legacy code

Refactoring without tests is dangerous; with all the details we must keep straight, a mistake is easy to make. How many code reviews have you been in where the recommended design changes are not made because “we already tested it”? You avoid the change because it’s dangerous to change code without tests. So, the Boy Scout adds tests too. For more on Boy Scouts, see previous post.

Continue reading

Agile Design and Embedded

One important realization on the journey from a BDUF approach to an iterative and agile approach is that design is never done. Designs evolve. The waterfall emphasis has been to unnaturally try to control software physics by imposing requirements freezes and burdensome change control. The process of developing software is part science and part creative. You are applying science toward the invention of something. Design is capturing knowledge both about what the end user need is, and one solution to that need.
Continue reading

Why Test Driven Development for Embedded?

Embedded software has all the challenges of “regular” software, like poor quality and unreliable schedules. It is just software with some additional challenges. The additional challenges do not disqualify TDD for embedded. TDD even helps with some of those uniquely embedded challenges.
Continue reading

What Should you Expect from a Unit Test Harness

A unit test harness’ job is to provide:

  • A concise common language to express test cases
  • A concise common language to express expected results
  • A place to collect all the unit test cases for the project, system, or subsystem
  • The facilities to run the test cases, either in full or partial batches
  • A concise report of the test suite success or failure
  • A detailed report of any test failures