TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming...
Transcript of TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming...
![Page 2: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/2.jpg)
Agenda
2
Introduction
Test-Driven Development
CppUTest
TDD in C
TDD in Embedded systems
![Page 3: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/3.jpg)
Introduction
3
![Page 4: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/4.jpg)
4
Scaling Lean & Agile Development
Thinking and Organizational Tools for Large-Scale Scrum
Craig LarmanBas Vodde
Practices for Scaling Lean & Agile
DevelopmentLarge, Multisite, and Offshore Products
with Large-Scale Scrum
Craig LarmanBas Vodde
![Page 5: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/5.jpg)
5
![Page 6: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/6.jpg)
6
![Page 7: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/7.jpg)
Test-Driven Development
7
![Page 8: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/8.jpg)
TDD
The single rule of Test-Driven Development (or test-first programming ) :
Only ever write code to fix a failing test
• Write a test (which fails -> “red”)
• Write the code (to make test pass -> “green ”)
• Refactor the code and test (youʼre still “green ”)
8
![Page 9: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/9.jpg)
Not a unit test when...
• It talks to the database
• It communicates across the network
• It touches the file system
• It can't run at the same time as any of your other unit tests
• You have to do special things to your environment (such as editing config files) to run it.
9
![Page 10: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/10.jpg)
CppUTest
10
![Page 11: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/11.jpg)
What is CppUTest?
• sUnit -> JUnit -> xUnit variant
• Framework for unit tests in C and C++
• Not need any external scripting.
11
![Page 12: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/12.jpg)
First test
#include "CppUTest/TestHarness.h"
TEST_GROUP(FirstTest){};
TEST(FirstTest, First){ LONGS_EQUAL(1,0);}
TestFirst.cpp
![Page 13: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/13.jpg)
First test
#include "CppUTest/TestHarness.h"
TEST_GROUP(FirstTest){};
TEST(FirstTest, First){ LONGS_EQUAL(1,0);}
TestFirst.cpp
Main CppUTest header
Most CppUTest functionality is included in this
header
![Page 14: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/14.jpg)
First test
#include "CppUTest/TestHarness.h"
TEST_GROUP(FirstTest){};
TEST(FirstTest, First){ LONGS_EQUAL(1,0);}
TestFirst.cpp
Declaration of a new
TEST_GROUP.
All tests have to belong to one test
group.
![Page 15: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/15.jpg)
First test
#include "CppUTest/TestHarness.h"
TEST_GROUP(FirstTest){};
TEST(FirstTest, First){ LONGS_EQUAL(1,0);}
TestFirst.cpp
Do not forget this semi-column
It will lead to strange compiler
errors.
![Page 16: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/16.jpg)
First test
#include "CppUTest/TestHarness.h"
TEST_GROUP(FirstTest){};
TEST(FirstTest, First){ LONGS_EQUAL(1,0);}
TestFirst.cpp
First test.
First parameter is group name
Second parameter is test name
![Page 17: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/17.jpg)
First test
#include "CppUTest/TestHarness.h"
TEST_GROUP(FirstTest){};
TEST(FirstTest, First){ LONGS_EQUAL(1,0);}
TestFirst.cppLONGS_EQUAL
compares ints
First parameter is expected value
Second parameter is actual value
![Page 18: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/18.jpg)
First test
#include "CppUTest/CommandLineTestRunner.h"
int main(int ac, char** av){ return CommandLineTestRunner::RunAllTests(ac, av);}
#include "AllTests.h"
Main.cpp
![Page 19: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/19.jpg)
First test
#include "CppUTest/CommandLineTestRunner.h"
int main(int ac, char** av){ return CommandLineTestRunner::RunAllTests(ac, av);}
#include "AllTests.h"
Main.cpp
CppUTest header
![Page 20: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/20.jpg)
First test
#include "CppUTest/CommandLineTestRunner.h"
int main(int ac, char** av){ return CommandLineTestRunner::RunAllTests(ac, av);}
#include "AllTests.h"
Main.cpp
Call CommandLineTestRunner::RunAllTests class. This will execute all tests and return an
error if one fails.
![Page 21: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/21.jpg)
First test
#include "CppUTest/CommandLineTestRunner.h"
int main(int ac, char** av){ return CommandLineTestRunner::RunAllTests(ac, av);}
#include "AllTests.h"
Main.cpp
Pass command line arguments to CppUTest.
![Page 22: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/22.jpg)
First test
#include "CppUTest/CommandLineTestRunner.h"
int main(int ac, char** av){ return CommandLineTestRunner::RunAllTests(ac, av);}
#include "AllTests.h"
Main.cpp
Include all the test groups via AllTests.h
![Page 23: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/23.jpg)
First test
IMPORT_TEST_GROUP(FirstTest);
AllTests.h
Import test group using IMPORT_TEST_GROUP
This is only needed when tests are in a separate library, but it is a good habit to always
do this.
![Page 24: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/24.jpg)
First test
CPPUTEST = ../../CppUTest
CPPFLAGS += -I $(CPPUTEST)/includeLDFLAGS += $(CPPUTEST)/lib/libCppUTest.a -lstdc++
all: TestFirst ./TestFirst
TestFirst: TestFirst.o Main.o
Makefile
![Page 25: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/25.jpg)
First test
CPPUTEST = ../../CppUTest
CPPFLAGS += -I $(CPPUTEST)/includeLDFLAGS += $(CPPUTEST)/lib/libCppUTest.a -lstdc++
all: TestFirst ./TestFirst
TestFirst: TestFirst.o Main.o
Makefile
Define a variable with the location of CppUTest
![Page 26: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/26.jpg)
First test
CPPUTEST = ../../CppUTest
CPPFLAGS += -I $(CPPUTEST)/includeLDFLAGS += $(CPPUTEST)/lib/libCppUTest.a -lstdc++
all: TestFirst ./TestFirst
TestFirst: TestFirst.o Main.o
Makefile
Add the include path to the default compilation options.
![Page 27: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/27.jpg)
First test
CPPUTEST = ../../CppUTest
CPPFLAGS += -I $(CPPUTEST)/includeLDFLAGS += $(CPPUTEST)/lib/libCppUTest.a -lstdc++
all: TestFirst ./TestFirst
TestFirst: TestFirst.o Main.o
Makefile
Add CppUTest and STD C++ to the default linker option
![Page 28: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/28.jpg)
First test
CPPUTEST = ../../CppUTest
CPPFLAGS += -I $(CPPUTEST)/includeLDFLAGS += $(CPPUTEST)/lib/libCppUTest.a -lstdc++
all: TestFirst ./TestFirst
TestFirst: TestFirst.o Main.o
Makefile
Create a default target
![Page 29: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/29.jpg)
First test
CPPUTEST = ../../CppUTest
CPPFLAGS += -I $(CPPUTEST)/includeLDFLAGS += $(CPPUTEST)/lib/libCppUTest.a -lstdc++
all: TestFirst ./TestFirst
TestFirst: TestFirst.o Main.o
Makefile
Run the tests(makefiles require tabs! Be careful with your
IDE settings)
![Page 30: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/30.jpg)
First test
CPPUTEST = ../../CppUTest
CPPFLAGS += -I $(CPPUTEST)/includeLDFLAGS += $(CPPUTEST)/lib/libCppUTest.a -lstdc++
all: TestFirst ./TestFirst
TestFirst: TestFirst.o Main.o
Makefile
Declare which object files to link
![Page 31: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/31.jpg)
First test
CPPUTEST = ../../CppUTest
CPPFLAGS += -I $(CPPUTEST)/includeLDFLAGS += $(CPPUTEST)/lib/libCppUTest.a -lstdc++
all: TestFirst ./TestFirst
TestFirst: TestFirst.o Main.o
Makefile
Make default targets will take care of the test!
![Page 32: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/32.jpg)
First test
./TestFirst
TestFirst.cpp:10: error: Failure in TEST(FirstTest, First)make: *** [all] Error 1 expected <1 0x1> but was <0 0x0>
.Errors (1 failures, 1 tests, 1 ran, 1 checks, 0 ignored, 0 filtered out, 0 ms)
Output
![Page 33: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/33.jpg)
Exercise
• Make a first test.
• Let it fail.
• Make it pass.
![Page 34: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/34.jpg)
Cheat Sheet/* in CheatSheetTest.cpp */#include "CppUTest/TestHarness.h"
/* Declare TestGroup with name CheatSheet */TEST_GROUP(CheatSheet) {/* declare a setup method for the test group. Optional. */ void setup () {/* Set method real_one to stub. Automatically restore in teardown */ UT_PTR_SET(real_one, stub); }
/* Declare a teardown method for the test group. Optional */ void teardown() { }}; /* Do not forget semicolumn */
/* Declare one test within the test group */TEST(CheatSheet, TestName){ /* Check two longs are equal */ LONGS_EQUAL(1, 1);
/* Check a condition */ CHECK(true == true);
/* Check a string */ STRCMP_EQUAL("HelloWorld", "HelloWorld");}
/* In allTest.cpp */IMPORT_TEST_GROUP(CheatSheet);
/* In main.cpp */
#include "CppUTest/CommandLineTestRunner.h"#include "AllTests.h"
int main(int ac, char** av){ return CommandLineTestRunner::RunAllTests(ac, av);}
![Page 35: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/35.jpg)
TDD in C
35
![Page 36: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/36.jpg)
Use C or C++?• Why C++ (e.g. gcc):
• Able to use C++ unit test framework
• Able to use C++ features in tests
• Why C:
• Not annoyed by the small differences
• Able to use a C compiler.
• E.g. run tests in “real environment”
![Page 37: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/37.jpg)
Compilation• Fast build:
• Limit dependencies - Especially header dependencies!
• Incremental build - Generate dependency files
• Compile modules/subsystems
• Execute tests in Makefile!
• Without fast compile: TDD very hard
![Page 38: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/38.jpg)
Refactoring
• All manual -> Almost no refactoring tools
• Eclipse CDT has some support• But be careful. They break stuff.
• xRefactory emacs plugin (not tried it)
• Function to function pointer refactoring.
![Page 39: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/39.jpg)
TDD Cycle
• Same cycle
• Biggest problems:
• Lack of refactoring
• Slow cycle• use prediction
![Page 40: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/40.jpg)
Object Storage• Exercise:
• Object Storage module.
• Allocates a block of memory of “object number” times “object size”
• Reserves and releases objects
• Provides fast index-ed find based on 2 integers
![Page 41: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/41.jpg)
Badly structured
![Page 42: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/42.jpg)
Dependencies separated
![Page 43: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/43.jpg)
C Design• C can be used as OO language!
• Good written C is OO
• OO techniques
• Structs with Function Pointers
• Class-structs
• Global function pointers
![Page 44: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/44.jpg)
Structs with function pointers
Takes much memory per object
struct A{ void (*openA)(struct A* a); void (*closeA)(struct A* a);// Private int member; int anotherMember;};
![Page 45: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/45.jpg)
Class structstruct classA{ void (*open)(struct A* a); void (*close)(struct A* a);};
struct A{ struct classA * cls;// Private int member; int anotherMember;};
#define A_open(a) (((struct A*)a)->cls->open(a))#define A_close(a) (((A*)a)->cls->close(a))
Better. Much work though
![Page 46: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/46.jpg)
Global function pointers
Simple and allows dynamic stubbing and objects.Very limited though
struct A{ int member; int anotherMember;};
extern void (*a_open)(struct A*);extern void (*a_close)(struct A*);
Headervoid a_open_imp(struct A*){ printf("A Open\n");}
void (*a_open)(struct A*) = a_open_imp;
Source
![Page 47: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/47.jpg)
f2fp refactoring
void function (int para); void function (int para){ do_implementation ();}
Header Source
before
afterextern void (*function) (int para);
void function_imp (int para){ do_implementation ();}
void (*function)(int para) = function_imp;
![Page 48: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/48.jpg)
Stubbing• Stub level:
• Preprocessor (rare)
• Function pointer
• Link
• Stub type• Recording
• Generic
• Exploding
![Page 49: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/49.jpg)
Level: preprocessor#include "stubs.h"
void something (){ function(100);}
#define function(a) function_stub(a, b)
Source Stub header
Advantages: Disadvantages:
- Creates lots of flexibility.
-> for example. Can stub out just one call.
- Changes the production code
- Requires different build configurations
![Page 50: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/50.jpg)
Level: function pointer
Advantages: Disadvantages:
- Ability to runtime change
- Pretty safe
- Requires f2fp refactoring
- One extra call
- Dangling function points (use UT_PTR_SET)
TEST_GROUP(group){ void setup () { UT_PTR_SET(real_one, stub); }
![Page 51: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/51.jpg)
Level: link stubs
Advantages: Disadvantages:
- Can give a lot of flexibility!
- No change in production code
- Easy to re-use stubs
- Be careful of different configurations. Just have one stub (use generic link stubs)
- Difficult (impossible) to call “the real thing”
void function (){ /* Do stubbed things */}
![Page 52: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/52.jpg)
Type: Exploding
void function (){ FAIL("stub: function was called");}
Especially useful when starting. When it explodes something went wrong or you need to implement it.
![Page 53: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/53.jpg)
Type: Dynamic
Benefits of both function pointer and link level stubs!
void (*function_stub) () = NULL;
void function (){ if (function_stub) function_stub ();}
![Page 54: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/54.jpg)
Type: RecordingVery generic usage. More work.
struct function_call{ static int num_calls; int in_parameter1; int return_value; function_call* next;};
function_call* g_function_call;
int function (int parameter){ if (g_function_call) { g_function_call->num_calls++; g_function_call->in_parameter1 = parameter; int ret_value = g_function_call->return_value; g_function_call = g_function_call->next; return ret_call; }}
![Page 55: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/55.jpg)
Type: Combinationint function (int parameter){ if (function_stub) return function_stub(parameter); if (g_function_call) { g_function_call->num_calls++; g_function_call->in_parameter1 = parameter; int ret_value = g_function_call->return_value; g_function_call = g_function_call->next; return ret_call; } FAIL("Forgot to set stub or function_call struct.");}
Very flexible.
![Page 56: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/56.jpg)
Hello World!
• Exercise:
• Test-drive “Hello World!”
![Page 57: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/57.jpg)
Embedded TDD
57
![Page 58: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/58.jpg)
The Real Thing?• Run unit tests on real hardware?
• Probably not. Too slow.
• Every now and then it could be possible.
• Use the real compiler?
• Often not.
• Do run higher level tests on real HW every now and then!
![Page 59: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/59.jpg)
Design• Separate hardware dependencies
• Separate OS
• Separate asm from C
• Function pointer vs link stubs
• Static vs dynamic vs ʻdynamic staticʼ memory allocation
![Page 60: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/60.jpg)
Yes, it IS different
• Integer size
• Endian
• Different compiler -> different binary code
• Bottlenecks (profile on dev env... but be careful)
![Page 61: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/61.jpg)
Exercises
61
![Page 62: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/62.jpg)
Chat Client-Server
62
• Exercise:
• Multiple-clients connect to server
• Message send to server are distributed to clients
• Messages are printed
• POSIX sockets or IPC or ... ?
![Page 63: TDD in C - Odd-e€¦ · TDD The single rule of Test-Driven Development (or test-first programming ) : Only ever write code to fix a failing test • Write a test (which fails ->](https://reader031.fdocuments.in/reader031/viewer/2022022612/5b9bd4ea09d3f2f6368b8d0f/html5/thumbnails/63.jpg)
Lines of Code
• Exercise:
• Count “lines of code” of C program
• Ignore the pre-processor
63