Preview only show first 10 pages with watermark. For full document please download

How+to+use+ceedling+for+embedded+test-driven+development

Ceedling

   EMBED


Share

Transcript

How to Use Ceedling for Embedded Test-Driven Development with Step-by-Step Examples Matt Chernosky http://electronvector.com Copyright © 2!" Matt Chernosky. #ll rights reser ve$. Contents %elcome..........................................................................................................................................................................& %hat is 'est-(riven (evelopment )'((*+.........................................................................................................., 'he 'ools.......................................................................................................................................................................... nstalling Cee$ling......................................................................................................................................................." Creating a ew Cee$ling 0ro1ect........................................................................................................................... Example 3!: Starting '(( with Cee$ling............................................................................................................4 Create a Mo$5le......................................................................................................................................................4 mplement a 6eat5re...........................................................................................................................................!! 7epeat.......................................................................................................................................................................!& 7e8actoring..............................................................................................................................................................! Mocking 9ar$ware nter8aces...............................................................................................................................! Example 32: Mocking a 9ar$ware nter8ace with CMock..........................................................................!4 Create the 'emperat5re Sensor Mo$5le.....................................................................................................!4 %rite 5r 6irst 'est..............................................................................................................................................!4 Create the 65nction ;n$er 'est......................................................................................................................2! Mock the 2C nter8ace.......................................................................................................................................2! mplement the 65nction ;n$er 'est.............................................................................................................22 #$$ing #nother 'est...........................................................................................................................................22 7e8erences....................................................................................................................................................................2, So5rce Co$e...........................................................................................................................................................2, (oc5mentation.....................................................................................................................................................2, Cee$ling <5ick 7e8erence......................................................................................................................................2 'est #ssertions.......................................................................................................................................................2 Mock 65nction 6ormats.....................................................................................................................................2" How to Use Ceedling for Embedded Test-Driven Test-Driven Development  2 Welcome Maybe yo5=ve hear$ o8 Test-Driven Development )'((*> an$ maybe yo5=ve even tho5ght it seeme$ like a reasonable i$ea. If you havent tried TDD yet though! you really should" 'his g5i$e contains step-by-step examples to get yo5 starte$ test $riving in C> especially 8or embe$$e$ so8tware applications. %e=ll look at how to 5se the 5nit test 8ramework calle$ Cee$ling to help 5s $o this. n the 8irst example> we=ll see how to create tests an$ write the co$e to make them pass. n the secon$ example we look at mocking> an$ learn how to 5se it sim5late o5r har$ware. #ll the tests in these examples compile an$ r5n on yo5r host 0C )with ?CC*> with no target har$ware nee$e$. How to Use Ceedling for Embedded Test-Driven Development  & What is Test-Driven Development #TDD$% 'he premise o8 '(( is that we 5se the creation o8 5nit tests to incrementally $rive the $evelopment o8 the so8tware. 'he steps look like: !. %rite a test> an$ watch it 8ail. 2. mplement 15st eno5gh co$e to make the test pass. &. 7e8actor. ,. 7epeat. 'his allows 5s to be very clear abo5t what the co$e is to $o> beca5se we=ve $e8ine$ every behavior in a test. %ith each iteration yo5 a$$ a bit more 85nctionality to yo5r so8tware> an$ the tests give yo5 con8i$ence that yo5=re $oing it correctly. ne o8 the $i88ic5lties o8 5nit testing is that it takes some $egree o8 experience to write testable co$e. 8 yo5 write the tests 8irst tho5gh> yo5=ll 8ig5re o5t how to make yo5r co$e testable while yo5 write it. 'his means yo5 won=t waste yo5r time with this problem at all@ 6or me> the greatest aspect o8 '(( is that it takes a big problem to solve )how to implement a so8tware application* an$ re$5ces it to a simple problem )what is the next little thing  nee$ this so8tware to $o*. 'hen  15st write a test 8or that 8eat5re> implement it an$ repeat. Ao5 simply stop when yo5 $on=t nee$ any more 8eat5res. #n$ when yo5 $o stop> yo5=re con8i$ent that what yo5 have is working exactly how yo5 want it to. t=s 5nlikely that yo5=ll be spen$ing a lot o8 time chasing $own b5gs. How to Use Ceedling for Embedded Test-Driven Development  , The Tools 'he testing tools 5se$ in this example are Cee$ling> ;nity an$ CMock. 'hese are the best C 5nit test tools available> 8rom the people over at http://www.throwtheswitch.org/ . Cee$ling is an a5tomate$ testing 8ramework 8or C applications. t=s b5ilt aro5n$ 7ake> which is the 75by programming lang5age=s b5il$ tool. 'hat=s why all o8 the BCee$ling comman$s are act5ally 7ake comman$s. n or$er to $o '((> yo5 nee$ to be able to create an$ r5n tests easily since yo5=ll be $oing it all the time. Cee$ling provi$es a5tomatic test $iscovery> mock generation an$ test exec5tion> which makes it the best option 8or 5nit testing in C. t also b5il$s an$ r5ns tests on the host 0C> so when working on an embe$$e$ pro1ect we $on=t have to waste time $ownloa$ing to the target. ;nity is the 5nit test 8ramework provi$e$ with Cee$ling. t gives 5s all o8 o5r test assertions constr5cting o5r tests. CMock is the mocking 8ramework 5se$ with Cee$ling. 'he mocking 8ramework is what lets 5s sim5late interactions with other so8tware mo$5les> so that we can test o5r so8tware 5nits in isolation. How to Use Ceedling for Embedded Test-Driven Development   Installing Ceedling Cee$ling reD5ires 75by to r5n an$ 5ses ?CC to b5il$ each test. !. nstall 75by %in$ows installer: https://$l.bintray.com/oneclick/r5byinstaller/r5byinstaller-2.&.!.exe ther instr5ctions: https://www.r5by-lang.org/en/$oc5mentation/installation/ . &e sure that the 'uby bin folder is in your path> e.g. C:75by2&bin 2. nstall Cee$ling with the 75by FgemF tool with the comman$: gem install ceedling Installation Error: “certificate verify failed”  I’ve recently had an issue trying to use the gem! command" It’s a problem with the #uby$ems server %where Ceedling and other gems are hosted&" If you get an error li'e this( ERROR: Could not find a valid gem 'ceedling' (>= 0), here is wh: !na"le to download data from htt#s:$$ru"gems%org$ & connect returned=* errno=0 state=v+ read server certificate : certificate verif failed ( https://api.rubygems.org/specs.4.8.gz) The )uic' fi* is to install a new certificate into #uby" Download this certificate file( https(++raw"githubusercontent"com+rubygems+rubygems+master+lib+rubygems+ssl,c erts+inde*"rubygems"org+$lobalign#ootC."pem and place it into C:\Ruby23\lib\ruby\2.3.0\rubygems\sslcerts" /ote that your path may be different if you installed to another folder or installed a different version" &. 8 yo5=re on %in$ows> yo5=ll likely nee$ to install ?CC.  recommen$ installing with Cygwin )https://cygwin.com/install.html*. %hen installing be s5re to select the F(evelF packages to have ?CC installe$. 'hen p5t the Cygwin bin 8ol$er in yo5r path> e.g. C:cygwin",bin. How to Use Ceedling for Embedded Test-Driven Development  " Creating a (ew Ceedling )ro*ect ;se the Gcee$ling new Hpro1ectameIG comman$ to create a new pro1ect: $ ceedling new MyProject create MyProject/vendor/ceedling/docs/eedlingPac!et.pd" create MyProject/vendor/ceedling/docs/#ception%ummary.pd" ... create MyProject/vendor/ceedling/vendor/unity/src/unity.h create MyProject/vendor/ceedling/vendor/unity/src/unity&internals.h create MyProject/project.yml create MyProject/ra!e"ile.rb Project 'MyProject' created( ) *ool documentation is located in vendor/ceedling/docs ) #ecute 'ra!e )*' to view available test + build tas!s 'his generates a pro1ect tree an$ the con8ig5ration 8iles nee$e$ to 5se Cee$ling. 0ro1ect creation only nee$s to be $one once when starting a pro1ect. mportant among the create$ 8ol$ers are: • src: %here all o8 o5r so5rce 8iles will go. • b5il$: Contains anything generate$ by Cee$ling $5ring the b5il$. • test: %here o5r 5nit test 8iles will go. ow we have a pro1ect in the GMy0ro1ectG 8ol$er. ote the instr5ctions 8rom the Cee$ling o5tp5t when we create$ the pro1ect -- we can 5se Grake -'G to show 5s how to 5se it: $ cd MyProject $ ra!e )* ra!e clean temporar... , -elete all build arti"acts and ra!e clobber build a... , -elete all generated "iles and ra!e environment variables , ist all con"igured environment ra!e "iles:header , ist all collected header "iles ra!e "iles:source , ist all collected source "iles ra!e "iles:test , ist all collected test "iles ra!e logging , #nable logging How to Use Ceedling for Embedded Test-Driven Development   ra!e module:create0module&path1 and tes... , 2enerate module source3 header ra!e module:destroy0module&path1 and test... , -estroy module source3 header ra!e paths:source , ist all collected source paths ra!e paths:support , ist all collected support paths ra!e paths:test , ist all collected test paths ra!e summary no bui... , #ecute plugin result summaries ra!e test: or sourc... , 5un single test 01 real test ra!e test:all , 5un all unit tests ra!e test:delta , 5un tests "or changed "iles ra!e test:path0dir1 contains 0dir... , 5un tests whose test path ra!e test:pattern0rege1 epressio... , 5un tests by matching regular ra!e verbosity0level1 obnoi... , %et verbose output silent:061 ) ra!e version version in"o , -isplay build environment Cee$ling is b5ilt on 7ake> which is 75by=s $epen$ency-base$ b5il$ tool. Cee$ling an$ its 5nit test operations are implemente$ as ra+e tas+s. 'hese are the comman$s we will 5se to b5il$ an$ r5n o5r tests. /ote( ince we0re using #a'e we can e*tend our build capabilities by adding our own ra'e tas's to do whatever we would li'e1 e"g" generating documentation or downloading to the target" How to Use Ceedling for Embedded Test-Driven Development  J E,ample ./ 0tarting TDD with Ceedling n this example we=ll walk thro5gh a single '(( micro-cycle> a$$ing a 8eat5re by writing a test an$ getting it to pass. /ote that a new Ceedling pro2ect must have been created as described in the previous section" Create a 1odule ow it=s time to write some co$e. magine we=re b5il$ing a car an$ we want to b5i l$ a mo$5le to implement the lighting system. %e create a mo$5le like this: $ ra!e module:create0lights1 2enerating 'lights'... m!dir )p ./test/. m!dir )p ./src/. 7ile ./test/./test&lights.c created 7ile ./src/./lights.c created 7ile ./src/./lights.h created 'his creates three 8iles: Glights.cG to implement o5r mo$5le> Glights.hG to $e8ine the p5blic inter8ace an$ a test 8ile where we can p5t the 5nit tests 8or it. 'hese 8iles are a5tomatically create$ in the correct 8ol$ers o8 o5r tree. /ote( 3e could also have provided a deeper path in which to create the module1 e"g" ra-e module:create.electrical$lights/" #t this point> we can try r5nning o5r 5nit tests: $ ra!e test:all *est 'test&lights.c' )))))))))))))))))))) 2enerating runner "or test&lights.c... ompiling test&lights&runner.c... ompiling test&lights.c... ompiling unity.c... ompiling lights.c... ompiling cmoc!.c... in!ing test&lights.out... 5unning test&lights.out... How to Use Ceedling for Embedded Test-Driven Development  4 ))))))))))) *#%* 9*P9* ))))))))))) 0test&lights.c1   )))))))))))))))))))) ;2<5#- *#%* %9MM=5> )))))))))))))))))))) 0test&lights.c1 *est: test&module&generator&needs&to&be&implemented =t line ?4@: ;mplement me( )))))))))))))))))))) A#5= *#%* %9MM=5> )))))))))))))))))))) *#%*#-: ? P=%%#-: 6 7=;#-: 6 ;2<5#-: ? 'his tells 5s that a single test was r5n an$ it was ignored . 'he module:create task has 5se$ a template to create the test 8ile. nsi$e the test 8ile testKlights.c is a single test name$ test&module&generator&needs&to&be&implemented which 5ses a special ignore $irective to tell Cee$ling to ignore this test. 'he 85nction looks like this: void test&module&generator&needs&to&be&implementedvoid@ B *#%*&;2<5#&M#%%=2#;mplement me(@C D 'his is the convention 8or 5nit tests which Cee$ling. 'est 8iles have names that start with test& an$ they go in the Btest 8ol$er. %ithin each o8 these 8iles> 5nit tests are 85nctions whose names start with test&. #lso in the test 8ile are the set9p@ an$ tear-own@ 85nctions. 'hese 85nctions are r5n be8ore an$ a8ter each o8 the test 85nctions in the test 8ile. 'hese 85nctions are yo5rs to 5se i8 yo5 nee$ them. How to Use Ceedling for Embedded Test-Driven Development  ! Implement a 2eature ow that we have a mo$5le 8or the lights> it=s time to a$$ some 85nctionality. n the test$riven way> we=ll 8irst a$$ a test that $escribes some $esire$ behavior. Say we want this behavior: 3hen the headlight switch is off1 then the headlights are off" n this case we=re going to replace test&module&generator&needs&to&be&implemented@ with a new test 85nction: void test&Ehen*heFeadlight%witch;s""&*hen*heFeadights=re""void@ B // Ehen the headlight switch is o""...   lights&%etFeadlight%witch""@C // then the headlights are o"". *#%*&=%%#5*&#G9="alse3 lights&=reFeadlightsn@@C D %hat we=ve $one here is $e8ine two new 85nctions to implement in the lights mo$5le> lights&%etFeadlight%witch""@ an$ lights&=reFeadlightsn@. %e call the 8irst 85nction to t5rn the lights o88> an$ then call the secon$ to con8irm the state o8 the hea$li ghts. 'he *#%*&=%%#5*&#G9=@ macro is what we 5se to veri8y that the val5e ret5rne$ 8rom lights&=reFeadlightsn@ is the expecte$ val5e )"alse*. 'his is one o8 the many macros available 8or comparing vario5s types> all o8 which are explaine$ in the ;nity $oc5mentation )https://gith5b.com/'hrow'heSwitch/;nity/blob/master/$ocs/;nityL2S5mmary.p$8 *. ow we can r5n o5r tests> b5t obvio5sly this is going to 8ail with all kin$s o8 compilation errors> beca5se these 85nctions $on=t even exist yet. $ ra!e test:all *est 'test&lights.c' )))))))))))))))))))) 2enerating runner "or test&lights.c... ompiling test&lights&runner.c... ompiling test&lights.c... ... H %hell eecuted command: 'gcc.ee );test );test/support );src   );MyProject/vendor/ceedling/vendor/unity/src How to Use Ceedling for Embedded Test-Driven Development  !!   );MyProject/vendor/ceedling/vendor/cmoc!/src );build/test/moc!s )-*#%* )-2<9&MP;#5 )g )c test/test&lights.c )o build/test/out/test&lights.o' H =nd eited with status: 0?1. ra!e aborted( ... *as!s: *P IH build/test/results/test&lights.pass IH   build/test/out/test&lights. out IH build/test/out/test&lights.o %ee "ull trace by running tas! with ))trace@ )))))))))))))))))))) A#5= *#%* %9MM=5> )))))))))))))))))))) )))))))))))))))))))) *#%*#-: ? P=%%#-: ? 7=;#-: 6 ;2<5#-: 6 'his may sort o8 8eel like we=re cheating> since lights&%etFeadlight%witch""@ $oesn=t act5ally $o anything an$ lights&=reFeadlightsn@ simply ret5rns "alse> b5t as we a$$ more tests we=ll contin5e to a$$ 85nctionality. 'epeat %e can now contin5e a$$ing B8eat5res to the mo$5le 5ntil it $oes every thing that we nee$ it to -- by a$$ing tests an$ then writing the co$e to make them pass. 6or example might want to implement this behavior: 3hen the headlight switch is on1 then the headlights are on" How to Use Ceedling for Embedded Test-Driven Development  !& So> we create an a$$itional test: void test&Ehen*heFeadlight%witch;sn&*hen*heFeadights=renvoid@ B // Ehen the headlight switch is on...   lights&%etFeadlight%witchn@C // then the headlights are on. *#%*&=%%#5*&#G9=true3 lights&=reFeadlightsn@@C D 8 we r5n this test it will 8ail beca5se lights&%etFeadlight%witchn@ $oesn=t exist yet> b5t when we 5p$ate lights.h: ,i"nde" lights&F ,de"ine lights&F ,include Jstdbool.hH void lights&%etFeadlight%witch""void@C void lights&%etFeadlight%witch""void@C bool lights&=reFeadlightsnvoid@C ,endi" // lights&F #n$ a$$ the implementation in lights.c: ,include lights.h ,include Jstdbool.hH static bool areightsn I "alseC void lights&%etFeadlight%witch""void@ B areightsn I "alseC D void lights&%etFeadlight%witchnvoid@ B areightsn I trueC How to Use Ceedling for Embedded Test-Driven Development  !, D bool lights&=reFeadlightsnvoid@ B return areightsnC D 'hen we can r5n o5r tests an$ watch them both pass: $ ra!e test:all *est 'test&lights.c' )))))))))))))))))))) 2enerating runner "or test&lights.c... ompiling test&lights&runner.c... ompiling test&lights.c... in!ing test&lights.out... 5unning test&lights.out... ))))))))))) *#%* 9*P9* ))))))))))) 0test&lights.c1  K  )))))))))))))))))))) A#5= *#%* %9MM=5> )))))))))))))))))))) *#%*#-: L P=%%#-: L 7=;#-: 6 ;2<5#-: 6 'efactoring Every time we get a test to pass> is an opport5nity to re8actor. Since we have a s5ite o8 passing tests> we can change the co$e in any way an$ we=ll imme$iately know i8 we broke something. 'his allows 5s the ability to 8reely experiment with improving the co$e> e.g. to make it simpler or easier to 5n$erstan$. How to Use Ceedling for Embedded Test-Driven Development  ! 7e8actoring can also be $one to the tests as well. Ao5 may notice that as yo5 a$$ more an$ more tests> some become re$5n$ant or yo5 en$ 5p with a lot o8 $5plication across tests. Ao5=ll want to keep this 5n$er control as yo5 work> so that they tests $on=t get too $i88ic5lt to 5n$erstan$. How to Use Ceedling for Embedded Test-Driven Development  !" 1oc+ing Hardware Interfaces 9ow can yo5 5nit test yo5r embe$$e$ so8tware+ %hat abo5t yo5r har$ware $epen$encies+ 'he secret is moc'ing" %e can mock the inter8aces to o5r har$ware so that we dont need the actual hardware to test. 'his allows 5s to r5n o5r tests more D5ickly an$ be8ore the har$ware might even be available. 8 we=re $eveloping the so8tware 8or an embe$$e$ microcontroller> we=re probably going to be 5sing the microcontroller-provi$e$ har$ware mo$5les 8or things like S0> 2C> timers> etc. 6or each o8 these har$ware inter8aces> we want to have a correspon$ing so8tware mo$5le containing the microcontroller har$ware $epen$encies )i.e. har$ware register accesses*. How to Use Ceedling for Embedded Test-Driven Development  ! %e can then mock each o8 these har$ware inter8aces> eliminating o5r har$ware $epen$encies b5t still allowing 5s to 5nit test o5r application. nstea$ o8 compiling these tests 8or the embe$$e$ microcontroller> we compile them 8or an$ r5n them on o5r host 0C. 'o help yo5 create yo5r mocks yo5 want to 5se a moc'ing framewor' . 'he mocking 8ramework incl5$e$ with Cee$ling is CMock. t allows yo5 to create mocks o8 in$ivi$5al so8tware mo$5les 8rom their hea$er 8iles. Ceedling improves the e,perience by automatically using C1oc+ to generating the moc+s that we need" How to Use Ceedling for Embedded Test-Driven Development  !J E,ample 3/ 1oc+ing a Hardware Interface with C1oc+  /ote that this e*ample assumes that we already have an e*isting Ceedling pro2ect" ee the section titles Creating a /ew Ceedling 4ro2ect if you need help" magine that we want to talk to an external 2C temperat5re sensor. Create the Temperature 0ensor 1odule et=s create a mo$5le that will be o5r temperat5re sensor $river. $ ra!e module:create0temp%ensor1 2enerating 'temp%ensor'... m!dir )p ./test/. m!dir )p ./src/. 7ile ./test/./test&temp%ensor.c created 7ile ./src/./temp%ensor.c created 7ile ./src/./temp%ensor.h created Write 4ur 2irst Test %hat is the 8irst thing  want to be able to $o with this sensor+ =$ like to be able to rea$ the c5rrent temperat5re val5e. Cool. So  take a look at the $atasheet 8or my 8ictional temperat5re sensor an$  can see that it How to Use Ceedling for Embedded Test-Driven Development  !4 has a b5nch o8 !"-bit registers -- each with J-bit a$$resses -- one o8 which is the temperat5re register. 'he scaling o8 the val5es is s5ch that a register val5e o8  is -!.NC an$ a register val5e o8 x&66 is O!,."NC. 'his makes each bit eD5ivalent to .2NC. ow lets a$$ o5r 8irst test to testKtempSensor.c.  want to know that when  rea$ a temperat5re register val5e o8 x&66 that the temperat5re calc5late$ is !,.". void test&when*emp5egister5eadsMaAalue&then*he*emp;s*heMaAaluevoid@ B uint8&t temp5egister=ddress I 66C "loat epected*emperature I ?64.N"C "loat tolerance I 6.?"C //Ehen iLc&read5egister&#pect=nd5eturntemp5egister=ddress3 6""@C //*hen "loat actual*emperature I temp%ensor&get*emperature@C *#%*&=%%#5*&7=*&E;*F;<tolerance3 epected*emperature3 actual*emperature@C D 6irst we set 5p some variables to hol$ o5r expecte$ val5es. 'hen in the FwhenF cla5se> we nee$ to sim5late )or mock* the 2C mo$5le ret5rning a val5e o8 x&88 on a rea$ o8 the temperat5re a$$ress. 6or the moment> we preten$ that there is another i2c mo$5le )it $oesn=t act5ally exist yet* which han$les the 2C comm5nication with the temperat5re sensor. 'his is where o5r har$ware $epen$ent co$e will event5ally go. So> the iLc&read5eadgister&#pect=nd5eturn 85nction is act5ally a mock 85nction 5se$ to sim5late a call to a 85nction calle$ iLc&read5egister in the i2c mo$5le. %e=ll come back to this in a moment. How to Use Ceedling for Embedded Test-Driven Development  2 'he FthenF cla5se is where we test that the tempSensor mo$5le act5ally ret5rns the correct temperat5re when we call temp%ensor&get*emperature. 'his 85nction $oesn=t exist yet either. Create the 2unction Under Test ets create the temp%ensor&get*emperature 85nction with a $5mmy implementation: tempSensor.h: , i"nde" temp%ensor&F , de"ine temp%ensor&F "loat temp%ensor&get*emperaturevoid@C , endi" // temp%ensor&F tempSensor.c: , include temp%ensor.h "loat temp%ensor&get*emperaturevoid@ B return 6.6"C D 1oc+ the I3C Interface 8 we try an$ r5n the test now> the compiler will complain that it $oesn=t know abo5t the iLc&read5eadgister&#pect=nd5eturn mock 85nction. 'his is beca5se the iLc&read5egister 85nction $oesn=t exist an$ we haven=t yet tol$ Cee$ling to mock it. We dont actually need to implement this function however" Its enough to declare the function prototype in a header file and tell Ceedling to moc+ it with C1oc+" Create the hea$er 8ile> i2c.h: , i"nde" iLc&F , de"ine iLc&F , include Jstdint.hH uint?N&t iLc&read5egisteruint8&t register=ddress@C How to Use Ceedling for Embedded Test-Driven Development  2! , endi" // iLc&F 'he way we tell Cee$ling to mock this mo$5le is to a$$ this line to testKtempSensor.c: , include moc!&iLc.h 'his tells Cee$ling: 5ou 'now the i6c"h header you see over there7 3ell""" use C8oc' to generate the implementation and compile it in for us1 o'ay7  %hen CMock gets a hol$ o8 the hea$er 8ile it looks at all the 85nctions $e8ine$ there an$ generates several mock 85nctions 8or each... incl5$ing the iLc&read5egister&#pect=nd5eturn 85nction we 5se$ in the test. 'his mock 85nction appen$s an a$$itional arg5ment to the original iLc&read5egister 85nction> which is the val5e we want the 85nction to ret5rn to the calling 85nction. 6or more $etails on all the mock 85nctions available with CMock> see the CMock $oc5mentation at: https://gith5b.com/'hrow'heSwitch/CMock/blob/master/$ocs/CMockKS5mmary.m$3generat e$-mock-mo$5le-s5mmary. Implement the 2unction Under Test ow we can implement the logic 8or o5r temp%ensor&get*emperature 85nction. 5r new tempSensor.c is: , include temp%ensor.h , include iLc.h , include Jstdint.hH "loat temp%ensor&get*emperaturevoid@ B uint?N&t rawAalue I iLc&read5egister66@C return )?66.6" K 6.L"  "loat@rawAalue@C D 8 we r5n o5r test> it sho5l$ pass now. 5dding 5nother Test %e=ll next want to a$$ more tests 8or other possible ret5rn val5es 8rom iLc&read5egister. 'his is easily $one by changing the ret5rn val5e provi$e$ to the mock 85nction. How to Use Ceedling for Embedded Test-Driven Development  22 6or example> to test that the minim5m temperat5re val5e is rea$ correctly: void test&when*emp5egister5eadsMinAalue&then*he*emp;s*heMinAaluevoid@ B uint8&t temp5egister=ddress I 66C "loat epected*emperature I )?66.6"C "loat tolerance I 6.?"C //Ehen iLc&read5egister&#pect=nd5eturntemp5egister=ddress3 66@C //*hen "loat actual*emperature I temp%ensor&get*emperature@C *#%*&=%%#5*&7=*&E;*F;<tolerance3 epected*emperature3   actual*emperature@C D (ow we have a driver for an e,ternal hardware device that we can test without any of the hardware" %e can contin5e to $evelop the $river -- a$$ing more tests an$ 8eat5res -- by b5il$ing an$ testing on o5r host 0C. Py p5tting all o8 the microcontroller-$epen$ent 2C operations into their own mo$5le> we easily mocke$ them with Cee$ling an$ CMock. n 8act> we $i$n=t even have to implement this mo$5le yet -- we 15st ha$ to $e8ine its inter8ace in the hea$er 8ile. ;sing o5r mocks> we create$ 5nit tests that veri8y the behavior o8 o5r temperat5re sensor $river. 5s the rest of our application is developed! we can easily run these unit tests at any time to ma+e sure the driver will still wor+ correctly" How to Use Ceedling for Embedded Test-Driven Development  2& 'eferences 0ource Code 'he so5rce co$e 5se$ in these examples is available on ?it95b. E,ample . https://gith5b.com/ElectronQector/try-t$$-with-cee$ling E,ample 3 https://gith5b.com/ElectronQector/mocking-har$ware-cee$ling-cmock Documentation Ceedling https://gith5b.com/'hrow'heSwitch/Cee$ling/blob/master/$ocs/Cee$ling0 acket.m$ Unity https://gith5b.com/'hrow'heSwitch/;nity C1oc+  https://gith5b.com/'hrow'heSwitch/CMock/blob/master/$ocs/CMockKS5m mary.m$ How to Use Ceedling for Embedded Test-Driven Development  2, Ceedling 6uic+ 'eference ceedling new Jproject)nameH Create a new Cee$ling pro1ect name$ Jproject)nameH. ra!e )* Show all available rake )Cee$ling* tasks 8or the pro1ect. ra!e module:create0Jmodule)nameH1 Create a new mo$5le name$ Jmodule)nameH. Creates a so5rce 8ile> hea$er 8ile an$ 5nit test 8ile. ra!e module:destroy0Jmodule)nameH1 (elete an existing mo$5le name$ Jmodule) nameH. ra!e test:all 75n all 5nit tests in the pro1ect. ra!e test:Jmodule)nameH 75n only the 5nit tests 8or this mo$5le. ra!e clobber (elete everything create$ $5ring the b5il$ o8 the tests. ike cleaning> b5t more. Test 5ssertions *#%*&=%%#5*condition@ 0ass i8 the con$ition is tr5e. *#%*&=%%#5*&*59#condition@ 0ass i8 the con$ition is tr5e. *#%*&=%%#5*&7=%#condition@ 0ass i8 the con$ition is 8alse. *#%*&7=;@ 6ail the test imme$iately. *#%*&;2<5#@ # test containing this statement is ignore$. *#%*&=%%#5*&7=*&E;*F;< delta3 epected3 actual@ 0ass i8 the two 8loat val5e are within delta o8 each other. *#%*&=%%#5*&#G9=&%*5;<2 epected3 actual@ 0ass i8 the two n5ll-terminate$ strings match. *#%*&=%%#5*&#G9=&%*5;<2&#< epected3 actual3 len@ 0ass i8 the two strings match 5p to len. How to Use Ceedling for Embedded Test-Driven Development  2 *#%*&=%%#5*&<9pointer@ 0ass i8 the pointer is a n5ll pointer. *#%*&=%%#5*&<*&<9pointer@ 0ass i8 the pointer is not a n5ll pointer. *#%*&=%%#5*&#G9=&M#M5> epected3 actual3 len@ 0ass i8 the two regions o8 memory match. *#%*&=%%#5*&#G9=&;<* epected3 actual@ 0ass i8 the two signe$ integers match. *#%*&=%%#5*&#G9=&9;<* epected3 actual@ 0ass i8 the two 5nsigne$ integers match. *#%*&=%%#5*&#G9=&;<*&=55=> epected3 actual3 elements@ 0ass i8 the two arrays match. &M#%%=2# can appen$e$ to any o8 the other test assertions. 'hen there is on a$$itional arg5ment at the en$ o8 the arg5ment list which is a string to be printe$ i8 the test 8ails. &M#%%=2# 6or the complete list o8 test assertions> see the ;nity $oc5mentation at: https://gith5b.com/'hrow'heSwitch/;nity. 1oc+ 2unction 2ormats 4riginal 2unction C1oc+ 7enerated E,pect 2unction void "uncvoid@ void "unc&#pectvoid@ void "uncparams@ void "unc&#pectepected¶ms@ retval "uncvoid@ void "unc&#pect=nd5eturnretval&to&return@ retval "uncparams@ void "unc&#pect=nd5eturnepected¶ms3 retval&to&return@ 6or the complete list o8 available mock 85nctions> see the CMock $oc5mentation here: https://gith5b.com/'hrow'heSwitch/CMock/blob/master/$ocs/CMockKS5mmary.m$3generat e$-mock-mo$5le-s5mmary. How to Use Ceedling for Embedded Test-Driven Development  2"