Home > On-Demand Archives > Workshops >
Test-Driven Development
James Grenning - Watch Now - EOC 2021 - Duration: 01:18:26
Test-Driven Development is a technical practice that supports Agile's iterative and incremental development cycle. TDD helps you quickly discover mistakes, preventing defects. You weave a test safety net as you grow your product's behavior one test at a time. This safety net supports you now and in the future to help you keep code working as you change it. Oh yeah, don't let me forget to tell you it's fun and once you learn it, you save time and money.
Maybe you have heard of Test-Driven Development but don't quite get it. A good way to understand TDD is to pair program with an experienced practitioner. We will start with a brief overview and demo of Test-Driven Development. In this interactive workshop, you can practice TDD in C. You don't need to install any tools for this workshop. You'll run the exercise on my exercise server. You will know what TDD is after this session. We'll conclude the workshop with a debrief on your experience.
Before attending this workshop, it is highly recommended that you watch this talk from the 2020 Embedded Online Conference.
Hello Marko
I am so sorry I missed this. I gues I am not notified when there are questions. Please reach out to me if you have other questions on my website
wingman-sw.com
The time spend proactively test-driving code, rather than reactively debugging is in TDD's favor, once you learn it. Now, believing me is another thing. Pretty much you need to convince yourself by trying TDD. My EOC workshops is a start and my courses can help you get the feel of TDD and start to see its power.
The small steps are very non-intuitive and one of the underpinnings of TDD. What size steps do you work in when you are debugging? You work in small steps debugging because you have to. You inspect each minute detail to see what you got wrong.
Why do we work in small steps during debugging? I'll answer: Because we are only good at solving one problem at a time. The small steps of TDD show we accept this limitation, and help you work within your limits.
You'll also see that TDD influences design, leading you to separate unit-testable code from code needed integration tests (HW or environment-dependent code).
14:02:56 From Michael Kirkhart : @ James Grenning: I like the shirt in your picture: "The code does not work - why?" 14:03:40 From Michael Kirkhart : LOL 14:04:22 From busa2191 : Is there audio? 14:05:00 From Derek Konigsberg : There’s a “Join With Computer Audio” option when connecting to Zoom. Its easy to miss it. 14:05:06 From Will Hsiung : Hi James, great to see you again! 14:05:13 From Ira Wolf : yes 14:05:14 From Carlos : YES 14:05:15 From Clayton Pannell : yes 14:05:15 From Diogo Freitas : yes 14:05:16 From Raul Pando : Yep 14:05:17 From JackW : yep! 14:05:18 From Paul Malcolm : audio is great 14:05:19 From Gerhard : yes 14:05:21 From David C : Yep! 14:05:45 From Keith J : Hey James - looking forward to the "refresher" 14:06:28 From Iván GB : People is having problems to join due to the capacity limit of the ZOOM 14:07:00 From afwaanquadri : Where are these instructions? 14:07:23 From Gerhard : Will be published in a few moments. 14:08:18 From Leandro Pérez : HI everyone from Colombia :) 14:08:49 From Piotr Zdunek : How can we open the exercises? 14:08:58 From Benny : Hello :) 14:09:04 From René Andrés Ayoroa : Hi from Paraguay 14:09:10 From gatoAlfa : Hi Leandro! ?? 14:09:15 From jvillasante : And I thought TDD wasn’t that popular anymore :) 14:09:49 From René Andrés Ayoroa : How can we open the exercises? 14:10:00 From Jeremy Schreiber : You can't yet 14:10:17 From enrico : good book 14:10:25 From Naveen Shankar : Fantastic book! 14:12:20 From enrico : whats c ? 14:12:43 From Piotr Zdunek : high level framework for assembly 14:12:51 From enrico : lol im jk 14:13:00 From Piotr Zdunek : me too :D 14:13:15 From Iván GB : Debug later programming :D 14:13:53 From Michael Kirkhart : LOL - definition of debugging! 14:14:00 From Leandro Pérez : Great definition 14:14:11 From David : I'm a programmer and I (try not to) write bugs 14:17:45 From jvillasante : I’m a programmer and even my tests are buggy 14:17:59 From enrico : lol 14:18:20 From David Campelo : :) 14:19:15 From Benny : I'm a bug and I write programs ;) 14:19:34 From jvillasante : LOL 14:21:39 From Piotr Zdunek : Encapsulation is king 14:22:02 From António Carvalho (Bosch) : int is too large 14:22:26 From Benny : 128 bit? 14:22:26 From jvillasante : If you are using malloc kind of functions why not go all the way and use C++? 14:22:43 From Piotr Zdunek : Not many embedded systems use cpp 14:22:59 From Benny : exactly 14:23:04 From Gerhard : Arduino? 14:23:04 From mdohring : empty 14:23:09 From jvillasante : Those aren’t allowed to use malloc either, I guess. 14:23:14 From David Campelo : after creating it's empty 14:23:45 From Iván GB : Dynamic allocation is "dangerous" and many embedded systems do not have an MMU to avoid mem fragmentation 14:24:05 From enrico : its only dangerous if you need to free() 14:24:12 From António Carvalho (Bosch) : if you can run Linux on an embedded system, you can run whatever 14:24:12 From enrico : no free...no problem 14:24:16 From Hariharan G : More like free causes fragmentation 14:24:26 From Piotr Zdunek : if you don't need to free(), then why do you need dynamic allocation? 14:24:29 From patelk5 : https://en.wikipedia.org/wiki/The_Power_of_10:_Rules_for_Developing_Safety-Critical_Code 14:24:45 From patelk5 : if you are writing safety crticial code, it is good to avoid dynamic allocation 14:24:46 From jvillasante : Allocate at initialization and do not free until shutdown… kind of an arena 14:24:49 From Derek Konigsberg : I do wish static allocation and data structure encapsulation didn’t often feel mutually exclusive. 14:25:52 From Iván GB : If you do not use free, better use static 14:26:44 From Piotr Zdunek : I think there is no point in freeing before shutdown, but I don't know all the requirements and constraints :) 14:27:57 From Andrei : warning unused self 14:28:20 From Iván GB : Well, another issue could be the space assigned to the heap. I think the decission depends on the memory constraints you have 14:28:51 From jvillasante : Did I miss the link to the playground? 14:28:57 From jvillasante : Or haven’t been posted yet? 14:29:04 From afwaanquadri : Its not yet posted 14:29:06 From António Carvalho (Bosch) : hasn't been posted yet 14:29:18 From jvillasante : Ok, thanks @afwan! 14:29:52 From Iván GB : And malloc is not deterministic in time. I stop here :P 14:30:17 From afwaanquadri : Why can't we just write up the source code first and then start writing the test cases? 14:30:33 From Jason Cose : there is a vid from 2020 that tells why 14:30:45 From Jason Cose : check the notes for this meeting 14:30:47 From António Carvalho (Bosch) : you can. but this way you're defining the behavior before the implemetation 14:30:47 From Jason Cose : there is a link 14:30:48 From Piotr Zdunek : Technically if you follow TDD you will write a better code with less bugs if you start with tests 14:31:09 From Andrei : In theory, you define the API, write the test and implement the code 14:32:01 From Keith J : @Afwan - in order to create test coverage, there shouldn't be code that isn't tested so tests drive code... otherwise you don't have complete coverage (and know the tests work) 14:32:02 From jvillasante : I don’t know if a real Red/Green/Refactor workflow will work in an embedded situation, you need those tests to run fast, otherwise it will just slow you down 14:32:20 From Iván GB : The point is that if you start coding trying to cause the fails, you Will write better code. That is why he starts doing the test fail I guess 14:32:57 From Anthony : It also means you write the minimum code necessary to pas the tests. 14:32:59 From Hariharan G : Also it affects the design since you are thinking about the modules testability first 14:33:57 From Sean : In an ideal world you will write most of your tests off target 14:34:29 From mdohring : test name typo? 14:34:32 From jvillasante : So, I’m getting ahead of myself… what do you guys think about mocking and test doubles? 14:34:44 From Ben Sweet : is_not_empty_after_push? 14:34:57 From enrico : mocking is good...never used test doubles 14:35:06 From enrico : that's when you link fom a lib right ? 14:35:25 From António Carvalho (Bosch) : if you can prove with tets that your code is correct off target then it will let you be a little more confident about it being correct when running on the device 14:35:28 From jvillasante : It’s kind of mocking but without the recording 14:36:39 From Anthony : Mocking is good, fakes and shims are not so much. I don't know how that maps to test doubles. I usually will create test classes which inherit from the class under test just to expose privates or other inconvenient things. 14:36:40 From jvillasante : BOOM… a test that depends on a hidden side effect? 14:36:47 From Piotr Zdunek : I personally prefer to avoid any mathematical operations in return statement. 14:37:37 From António Carvalho (Bosch) : ah, forget C. just use LISP 14:38:31 From jvillasante : Did somebody mention Rust already? :) 14:39:33 From Clayton Pannell : ? 14:40:00 From Benny : rust is too complicated for me 14:40:13 From Andrei : compile error in get 14:40:16 From Benny : C es btter:) 14:40:20 From jvillasante : @Benny, look into zig then 14:40:26 From Benny : *fills 14:40:50 From Iván GB : Rust? It should be easier, avoiding many of the hard parts of C/C++ 14:41:11 From Benny : put borrow checker in c! 14:41:22 From gatoAlfa : I think the parameter name in the .h file helps the user understand the usage of the parameter, the type doesn’t help much. Any particular reason to omit the name in the .h 14:41:35 From Gerhard : LONGS_EQUAL 14:41:41 From jvillasante : Zig has a very interested design on which everything that allocates needs to explicitly be passed an allocator 14:41:53 From jvillasante : And unlike Rust, it’s trying to compete with C, not with C++ 14:42:16 From Benny : interesting... 14:42:40 From Benny : first time I hear about zig 14:42:54 From António Carvalho (Bosch) : nothing can compete with the behemoth that is C++ unless it can also get 40+ years of adding complexity 14:42:55 From jvillasante : Pretty interesting, still not 1.0 yet… 14:43:10 From Piotr Zdunek : I'm not sure if anything takes over C in embedded systems, there is simply too much legacy code and compilers, it would be a lot of effort to move to anything else 14:44:28 From Nathan Jones : If anyone is wondering how James is coming up with all these great tests, I found this blog post on his website to be very useful: https://blog.wingman-sw.com/tdd-guided-by-zombies. 14:44:32 From Benny : I do BSP so only C for me ;) 14:44:59 From afwaanquadri : Need to add a check for overflow. It can keep incrementing the values 14:45:14 From Andrei : You need to C it to believe it :D 14:46:04 From António Carvalho (Bosch) : here it comes 14:46:14 From Steve Wheeler : I once had to find a bug in circular buffer code that was written as a state machine with 64 states. This looks a bit more straightforward. 14:46:18 From Nathan Jones : Starting to look like an intentional DDoS 14:46:26 From afwaanquadri : :D 14:46:32 From James Grenning : https://wingman-sw.com/exercises/emb2021 14:46:50 From Gustavo : I don't think C will ever be taken over on bare-metal But what I think will happen is that more and more projects will be developed with "virtual machines", like micropython, and we are the guys who will support these BSPs :) 14:46:50 From Kurtovic Tarik, Omerbegovic Adna (1.59) : _sound of the universe imploding_ 14:47:36 From Tom.Davies : boom 14:49:22 From Jón Hákon Richter : is there a finite amount of people that can join the servers? 14:50:22 From DMI: Franco MASSARO : Sorry I have to leave 14:51:31 From Clayton Pannell : it feels weird not using vim 14:51:35 From gatoAlfa : How I reset, I lost all the content in my CircularBufferTest.cpp 14:51:39 From Benny : should I add additional variable in the struct? 14:52:41 From Stephane Boucher to James Grenning(Direct Message) : We need to make sure to wrap up the session by about 2:50, so I can start Jacob's workshop in time 14:53:40 From gatoAlfa : Yes revert works. (lost code) 14:54:55 From Arjun N A : Hi can you repeat what is that we have to do. I missed out a couple of minutes during your presentation. Sorry. 14:56:30 From Arjun N A : Should we create the circular buffer? 14:57:18 From Arjun N A : ooh okay, I think we should replicate what you did for the previous 10 mins? 14:58:00 From António Carvalho (Bosch) : how do I run the tests? 14:58:56 From Shaun Hayward : sorry but I unfortunately have to drop. Thank you for a good workshop (and July "bat" avatar is free if anyone wants it :) ) 15:00:23 From António Carvalho (Bosch) : for some reason it was not working on Firefox. I had to move to Edge 15:00:59 From Arjun N A : Hi, Can you please share where I should start in the TDD 15:01:24 From Arjun N A : Yes 15:01:24 From gatoAlfa : Thanks everyone, have to leave. I will keep open and will try to finish later today. 15:01:33 From Peter Jamrozinski : Will you have this code skeleton available elsewhere via GitHub? 15:01:37 From James Grenning : https://wingman-sw.com/exercises/emb2021 15:01:52 From Marinna Martini : I was locked out and just got in - is there a way to catch up? 15:02:16 From Leandro Pérez : I have learned TDD in the past 10 minutes... lol 15:02:23 From Burak ŞEKER : Can we reach to this link later on to do the exercise via recording? I was too late due to zoom limitation and I would like to do it later 15:03:56 From Tony Arkles : James, when I reached the dynamic memory portion here, I got that lovely memory leak error. Is that something that is included “for free” in CppUTest?! Because it’s awesome! 15:04:19 From Leandro Pérez : How can test many condition at the same time? What is the syntaxis? 15:04:57 From Leandro Pérez : I got it 15:05:23 From S : I'm unable to connect on Firefox or Chrome. Timed out. 15:05:43 From Paul : OpenDNS is now classifying emb-1a.wingman-sw.com as a security threat 15:05:57 From Yuriy Kozhynov : Will the link will work later? 15:06:20 From Rocco Brandi : TEST(CircularBuffer, report_capacity) { LONGS_EQUAL(100, CircularBuffer_Capacity(buffer)); } 15:06:26 From Rocco Brandi : is passing always 15:06:44 From Rocco Brandi : even if the function CircularBuffer_Capacity doesn't exists 15:07:29 From Rocco Brandi : opps! 15:08:50 From Iain Chalmers : Q: At what point in the cycle would you typically do your commits to source control? Immediately on writing a test that fails, or as a full test + passing code? 15:08:55 From Miehl : If you want to practice TDD with a template after this exercise is over, you can use this one: https://github.com/makomi/tdd_templates/tree/master/C_CppUTest It is a template for a code kata, i.e. everything is set up - you just need to write your tests and code 15:09:42 From Leandro Pérez : Interesting TDD 15:09:53 From Marinna Martini : @Miehl thanks 15:09:56 From patelk5 : CircularBufferTest.cpp:100: error: Failure in TEST(CircularBuffer, put_get_is_fifo) Memory leak(s) found. 15:10:04 From S : No idea what happened, but I put in http://wingman-sw.com and went to the website, then typed in the rest and it connected. 15:10:55 From patelk5 : do we have to call free somewhere if we used calloc to allocate buffer array? 15:11:37 From patelk5 : I am getting memory leaks 15:11:44 From Peter Jamrozinski : If we want to come back later, will our progress still be saved under our "avatar"? 15:11:59 From patelk5 : never mind 15:12:00 From James Grenning : https://linoit.com/users/jwgrenning/canvases/emb-1-parking-lot 15:15:25 From Clayton Pannell : d'oh 15:16:05 From Nathan Jones : What is meant by "Don't forget to update CircularBuffer_Create() in setup()!" in CircularBufferTest.cpp? 15:16:14 From Stephane Boucher to Michael Kirkhart(Direct Message) : Michael, I just noticed your raised hand. Do you have a question or did you simply forget to bring your hand down? 15:16:17 From Leandro Pérez : Yes I know 15:16:26 From Leandro Pérez : Is my first time with TDD 15:17:07 From Scott K. : If the build env were a docker image, we could work on this on our own at our leisure. 15:17:07 From S : I DO like your book thus far...only part way in. I've been in test for about 10 years and this opened my eyes. Thank you! 15:17:19 From JackW : I especially appreciate that CPPuTest can detect memory corruption and leaks so effortlessly... I am only familiar with Ceedling/Unity and it doesn't have this functionality 15:19:19 From Juan : James, in your book you use Unity and CppUnit, would you have picked those today? 15:22:07 From James Grenning : https://wingman-sw.com/exercises/emb2021-debrief 15:22:15 From Ben Sweet : What is the difference between "checks" and "tests"? "checks" is always one greater than "tests" (when all tests pass.) 15:23:12 From Frederic : google docs is blocked by firewall 15:23:22 From Tony Arkles : yeah I’m encountering that too 15:23:31 From Stefan Petersen : The tests are number of TEST and checks are CHECK* 15:24:26 From James Grenning : if you cannot get to the google doc, add a postit, what did you like? what concerns you? 15:25:03 From Scott K. : What/where is the parking lot? 15:25:34 From James Grenning : https://linoit.com/users/jwgrenning/canvases/emb-1-parking-lot 15:25:46 From James Grenning : https://wingman-sw.com/exercises/emb2021-debrief 15:28:00 From Ben Sweet : "Sorry about that Chief!" 15:28:49 From Kurtovic Tarik, Omerbegovic Adna (1.59) : the message "You got ahead of your tests" is cute :D 15:30:03 From Marinna Martini : Ahhh - the error messages instruct you how to write the code. 15:31:43 From patelk5 : Well done presentation! 15:36:41 From Jeremy Overesch : CppUTest does work on most ARM based systems. I've been using it on a range of STM32 processors. 15:37:38 From afwaanquadri : What are your suggestions about mocks and fakes? 15:39:38 From Yan S. : Compare to Boost test CPP test , which is better? 15:43:15 From Ben Sweet : In "Test-Driven Development for Embedded C" you mention both CppUTest and Unity. Aside from CppUTest being applicable to both C and C++, are there other advantages of CppUTest in general? 15:44:28 From Miehl : https://martinfowler.com/articles/is-quality-worth-cost.html 15:44:39 From Jeremy Overesch : @Ben, I'm unsure about Unity, but CppUTest can be run on actual hardware. I'm using it on multiple STM32 cores right now. 15:44:57 From Jeremy Overesch : with IAR 15:47:06 From Peter Sik : How would you go about adding tests to a legacy codebase without them? Start from beginning or adding them gradually? 15:47:42 From Miehl : James wrote an article on this topic: https://wingman-sw.com/articles/tdd-legacy-c 15:48:29 From Miehl : I am collecting information like that in this Telegram channel: https://t.me/embedded_sw_quality 15:48:39 From Piotr Zdunek : How long will the server be up for us to play around? 15:50:28 From Frederic : thanks a lot, it was great! 15:50:30 From Tom.Davies : Thanks James 15:50:33 From Jason Cose : Thanks! 15:50:35 From Piotr Zdunek : Thanks! 15:50:35 From Andrew Murray : Thank James :) 15:50:36 From Rocco Brandi : thank you very much! 15:50:37 From Brian : Thank you! 15:50:38 From Jeremy Schreiber : Thank you!! 15:50:38 From Carlos : Thank you! 15:50:39 From James G : thank you! 15:50:39 From Arjun N A : Thank you 15:50:39 From dayolawa : Thanks you! 15:50:40 From Grant : Thanks! 15:50:43 From Gerhard : Thanks! 15:50:43 From Peter Sik : Thank you! 15:50:43 From JackW : thanks! 15:50:44 From Iván GB : Thanks 15:50:44 From Tony Arkles : thanks! yeah that was awesome! 15:50:44 From S : than kyou 15:50:46 From Stefan Petersen : Thank you! 15:50:46 From Jón Hákon Richter : Thanks for the lecture! 15:50:48 From Leandro Pérez : Thanks 15:50:49 From René Andrés Ayoroa : Thank you! 15:50:49 From navin : Thanks James! 15:50:49 From Yuriy Kozhynov : Thanks 15:50:49 From Douglas UTFPR : thanks a lot 15:50:52 From Mark J : Thank you 15:50:52 From Ben Sweet : Thanks for the great TDD experience! 15:50:55 From Steve Wheeler : Thank you. Very informative. 15:50:55 From Sergii Akhinko : Thanks a lot it was very nice ! 15:50:56 From sleung : Thanks again! Awesome. 15:50:57 From Aditya S : Thank you very much, this was an interesting intro 15:51:01 From HarriR : Thank you James! 15:51:01 From Miehl : Thank you - especially for your book! 15:51:06 From Peter Jamrozinski : Thank you! 15:51:07 From Dale Walter : Thank you! 15:51:12 From Thomas : Thanks - bye 15:51:14 From ITP1CA : Thanks everyone! 15:51:17 From Mustafa Caliskan : Thanks
Hello James,
I have one question for you that I was not able to ask in the workshop.
I work in a IoT company as an embedded programmer, we manly write code for Zephyr and NRF5 SDK based products. We are usually dealing with trackers and systems that have BLE, LoRa, LTE, GPS connectivity, plus usually tons of sensors.
With my coworkers we were watching your last years talk. Our major concern is that faking (through the mocks) all the connectivity part of the products would be slow and would add an overhead which would put us behind in the deadlines. Plus they did not like the steps of the mini test cycle, which I can understand as they could not see the full benefit from ouor short presentation. Can you give some thoughts on mocking hardware and networking depended parts of the ssystems?