Author TDD for Embedded C

Web Site | Blog

Posts by James Grenning

11 Jul 2011, 14:22
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > Code download update)

I’ve updated the code download package and instructions. Many people contacted me for instruction and build environment problems. Here are the highlights of what I did:

  • Improved README.txt, so you know how I intend you to build and use the code base
  • Added eclipse project files where they were missing, and instructions on how to import the various projects into eclipse
  • Improved build for Unity tests. 32/64 bit pointer should not be a problem any more
  • Improved build for VC6

Let me know if you have problems.

James

13 Jul 2011, 01:33
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > Unity/CppUTest)

It sounds like you need to include RunTimeStub.h in LedDriverTest.cpp like this

extern "C"
{
#include "RunTimeErrorStub.h"
}

That tells the compiler that it should use C linkage conventions for symbols defined in that header file. The test files are C++, so the compiler guesses that those symbols are too.

13 Jul 2011, 02:39
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > Unity/CppUTest)

Starting with @MockIO@ is a good idea. It is a hand-crafted mock. Also look at simpler test doubles too, like are in the @LightScheduler@ example.

13 Jul 2011, 13:33
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > Unity/CppUTest)

If you can ask a more specific question, I might be able to help more.

Mocks, stubs and fakes take the place of the thing they are stubbing. In the case of @MockIO@ it replaces @IORead@ and @IOWrite@ and is behaving like the flash device for given scenarios.

Maybe you should not start with the more challenging ideas (@MockIO@). Have you worked through the @LightScheduler@, it uses a couple easier to understand test doubles, the @FakeTimeService@ and @LightControllerSpy@.

You should probably read up on linking in C and C++.

Could you edit your post so that it does not have the horizontal scroll bar.

18 Jul 2011, 13:20
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > Unity/CppUTest)

Hello Aditya

You have it wrong about having to add your files to CppUTest. I revised my post from Jul 8, 2011 2:52pm above that hopefully makes that clearer. The book’s code base t0, t1, t2, and t3 projects serve as examples of how to structure a project including test cases. Maybe you should work with and experiment with those projects, and then model your projects after them.

James

22 Jul 2011, 17:32
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > Unity/CppUTest)

Hello Aditya

It’s a good question. I prefer to not have @#includes@ in @#includes@, but the @LightScheduler.h@ interface prototypes depend on the @enum Day@ which comes from @TimeService.h@.

I’d rather not burden the @.c@ files with having to hunt down the @#includes@ needed to @#include LightScheduler.h@.

That’s how I do it. You can probably find some people to argue with me.

James

26 Jul 2011, 18:35
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > Unity/CppUTest)

Yeah, the @CHECK@ and @LONGS_EQUAL@ are surprising. That’s what this comment is for:

@ /* These checks are here to make sure assertions outside test runs don’t crash */@

Do you have “Hello world” running in your target compiler? If no, you better start there.

  • Google to see if anyone else has ported to your target compiler

If you are a pioneer: * Get some help from a colleague * Turn off memory leak detection by defining this symbol the compiler command line or IDE options (CPPUTEST_MEM_LEAK_DETECTION_DISABLED) * Compile one CppUTest file at a time * Notice src/Platforms for the files that are likely to give you trouble. Adjust as needed

25 Aug 2011, 18:17
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > How to create makefile?)

Hi Arnd and Aditya

Did you get over the problems?

Sorry for not responding, but I was at the Agile 2011 conference and then on vacation.

James

25 Aug 2011, 18:56
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > mocking a function with variable arguments)

If you take a look at the implementation of @FormatOutputSpy@ and its use of @#include @ functions @va_list@, @va_start@, @va_end@. You will also need to use @va_arg@.

Why not just use FormatOutputSpy?

James

25 Aug 2011, 18:59
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > How to ignore a parameter in a mocked function?)

You might want to ask some of this question at cpputest@googlegroups.com. Bas Vodde did most the work on CppUMock. He’d be happy to help on that forum.

James

07 Sep 2011, 16:38
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > Unit test for Netbeans)

This is outside my experience, but being at chapter 6, you have not really gotten into the faking, stubbing and mocking that you will likely need.

You can also join and post your question at the AgileEmbedded yahoo group http://tech.groups.yahoo.com/group/AgileEmbedded

James

07 Sep 2011, 16:39
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > Any suggestions for tdd in the linux kernel?)

You might want to stub out kernel functions. This has gotten some talk recently on the AgileEmbedded yahoo group http://tech.groups.yahoo.com/group/AgileEmbedded/

James

08 Sep 2011, 21:06
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > CppUTest for IAR)

Hi Marc

What files besides MemoryLeakWarningPlugin.h are goving you trouble.

I think turning off memory leak detection might help. Here is an excerpt from the MakefileWorker.

ifeq ($(CPPUTEST_USE_MEM_LEAK_DETECTION), N)
	CPPUTEST_CPPFLAGS += -DCPPUTEST_MEM_LEAK_DETECTION_DISABLED
else
    ifndef CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE
	    	CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE = -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorNewMacros.h
    endif
    ifndef CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE
	    CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE = -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorMallocMacros.h
	endif	
endif

In the IAR build environment, replicate the effect of @ -DCPPUTEST_MEM_LEAK_DETECTION_DISABLED@, which defines a symbol for all compilation units defining @CPPUTEST_MEM_LEAK_DETECTION_DISABLED@.

If you are testing for leaks off-target, leaving it disabled on target is not a bad choice.

Let’s say you can get that to compile and pass non-memory leak related tests, then you can try to enable memory leak detection. For this you will want to replicate the forced includes in the above example. For building CppUTest, you want both defined. For building your production code for in-target-test, you will want both if you use C and C++, or just the malloc forced include if you only have C production code. It won’t hurt to have both though in case you decide to use some C++ in your test code.

I hope this helps. There might be some people using IAR discussing it on the cpputest google group - cpputest@googlegroups.com

James

13 Sep 2011, 15:52
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > Some questions about TDD)

Keep talking. I’m glad to see a conversation between posters/readers.

I based my definitions mostly off of xUnit Testing Patterns (Gerard Meszaros). I might have taken some liberty though. I tend to not get too hung up on it.

The subtle difference between LightControllerSpy and FakeTimeService is that the LightControllerSpy does not provide any indirect outputs to its caller. Its job is strictly to spy on the the indirect outputs of the LightController.

The FakeTimeService is providing indirect outputs. I am probably not using Fake quite right. But that is OK in my opinion. It seemed to fit the best. So you might find people calling everything a Mock, even though the guys that invented the term use it in a more precise way. I use spy, when I’m just interested in checking if the right things are passed or the right number of calls are made. I use fake if its not really a spy, and not strictly a mock, though in the past I have used mock because of its broad acceptance. Dummy says, we really don’t care what happens.

Stub was the old term, and a stub usually was temporary in its pre-TDD role. With TDD the Test Doubles (Gerard’s most general term) do have long term value and are maintained through out the life of the software by whoever is responsible for the code/product. They help the maintainers as much or more than the original developers. They make automatic testing of unit possible, and unit testing is the only practical way to thoroughly test code.

Also keep in mind that the role of a test double could evolve, and then the name might need to be changed. Also, especially if function pointers are used, you might have several test doubles for the same thing for different purposes. There is another approach that did not make the book. That is to have a link time test double that you can install a function pointer into for different test double needs. (I need a blog post for this) This is handy when you want one link time stub, but different test scenarios have different needs from their test double. By using the function pointer, you can let each TEST_GROUP use exactly the stub they need.

One caution… it si real easy to prevent real work when arguing about the names. Names are important, but don’t make a life of being a lawyer about it at least in the case of test doubles classification. Pick the best fit and/or don’t sweat it.

James

13 Sep 2011, 15:54
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > mocking a function with variable arguments)

Hi Arnd

Good reasoning. Well done.

James

20 Sep 2011, 13:04
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > Embedded Test Strategy - With CppUTest?)

Hello Arnd

I wrote a set of scripts for converting CppUTest to Unity. It is in CppUTest/scripts/convertToUnity. Look at the readme file there.

The scripts are one of my first attempts at ruby, so I bet they could be greatly improved. If your test files are formatted using the same style as mine they should work fine. You will need to build a suitable makefile or pull the files into your target IDE.

James

03 Nov 2011, 20:21
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > To semi-colon or not to semi-colon?)

Hi Arnd

There is nothing that can be done. A TEST_GROUP is actually a C++ class and the class declaration (a struct really) must be followed by a semicolon. I avoid this problem by using the code generator scripts for getting my starting point. The starting templates have the semicolon in the right place.

James

25 Oct 2011, 12:49
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > New test framework in Visual Studio 2011)

You will find that all the unit test harnesses seem to look similar.

I’d steer you to use a gcc solution. Cygwin helps get started, but will eventually be slow. You can then get a reported 10x improvement by going to a virtual machine running linux. This might sound daunting, but is very easy.

If the TI compiler does not support C++, you might want to go with Unity. Also in CppUTest there are some ruby scripts that will convert CppUTest test cases to Unity test cases. This route might require a little polishing of the scripts, but they are how I converted CppUTest book code to Unity.

James

25 Oct 2011, 12:53
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > Embedded Test Strategy - With CppUTest?)

Many embedded TDD adoptees find plenty of value in just using off-target tests.

if you run tests in the target, you can have some of them interact directly with the target. You will have to set up a build for each environment and if you have kept your mocks separate from your production code you should be able create another build/make environment that leaves the mocks out of your target test build.

James

25 Oct 2011, 12:56
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > Two suggestions for Unity Fixture)

Ideally each test is stand alone. Though I understand the need when initializing hardware.

You can do you one-time init stuff in main.

Would that work, at least for now?

James

28 Oct 2011, 03:25
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > Getting Started Unity with MPLAB X on Mac)

UnityTestRunner is in unity_fixture.c. UnityFail is in unity.c

I think you are not compiling those. Look at MakefileUnity.mk. Notice the symbols SRC_DIRS and TEST_SRC_DIRS. The contain all the directories whose C files must be compiled and linked.

James

01 Nov 2011, 06:31
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > Getting Started Unity with MPLAB X on Mac)

Do you have a way to output a character? Sounds like putchar is not available in your library. You can add your own putchar function like this

//myputchar.c
int putchar(int c)
{
      however_mysystem_outputs_a_char(c);
}
04 Nov 2011, 06:19
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > Getting Started Unity with MPLAB X on Mac)

Can you write a hello world program and get it to work with your environment? You could use your putchar to do it, and then trouble shoot the test framework knowing how to output a char.

07 Nov 2011, 16:51
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > Getting Started Unity with MPLAB X on Mac)

To get the fast feedback from TDD, then testing off the target is needed (in most if not all cases). This means that you have to more carefully manage your hardware and OS dependencies. This also has another benefit. Presuming your product’s hardware is going to evolve and this code is not throw away, it will more easily port in the future. Double win.

10 Nov 2011, 16:25
James2009_pragsmall

James Grenning (137 posts)

(from Test Driven Development for Embedded C > Unity/CppUTest)

Setup and teardown are simply virtual functions that do nothing by default.

137 posts