This Is Why You Suck At Unit Testing

  Рет қаралды 6,328

Cody Engel

Cody Engel

Күн бұрын

In this video, I'm going to show you 4 common mistakes that software engineers make when it comes to unit testing. By understanding and avoiding these mistakes, you'll be on the road to success in your programming career!
Unit testing is one of the most important aspects of software development. It allows you to catch mistakes before they make it into your production code, and it can save you a lot of time and hassle down the road. In this video, I'm going to share with you some of the most common unit testing mistakes that software engineers make. By avoiding these mistakes, you'll be on your way to successful unit testing!
🚶‍♂️ FOLLOW ME 🚶‍♂️
Join Our Discord - / discord
Twitter - / codyengeltweets
TikTok - / codyengeltalks
Medium - / membership
Subscribe To My Newsletter - www.engel.dev/
💡Get 20% Off Of Brilliant - brilliant.sjv....
🎥 My KZbin Gear - kit.co/CodyEng...
🖥 My Desk Gear - kit.co/CodyEng...
🎵 My Background Audio - www.epidemicso...
*The above links are affiliate links.
#softwareengineer #programming #vlog

Пікірлер: 34
@CrookedCCez
@CrookedCCez Жыл бұрын
0:27 - testing the implementation and not the behaviour 2:00 - your tests never fail 3:20 - your tests aren't clear 6:25 - not running your tests as part of a build process
@CodyEngelCodes
@CodyEngelCodes Жыл бұрын
Doing gods work 🙏
@ezekieloruven
@ezekieloruven 10 ай бұрын
The biggest observation that got me to use TDD mostly is the realization that TDD is always what you are doing, just that if you don't have a formal test, your "test" is the object's use in your code itself. So if you find you need another object, there WILL be tests and an expected interface, just those tests are now embedded in your code, and you can only know it works with your specific code and specific situation, not in all conditions you will inevitably end up changing your code into. Separated unit tests ensure your object works as expected in all conditions it should face, and having those tests make it so you can confidently optimize or enhance functionality without losing our breaking old functionality.
@CodyEngelCodes
@CodyEngelCodes 10 ай бұрын
Yesssss! I love this observation.
@geoffnelson429
@geoffnelson429 9 ай бұрын
Good takes, would love to see solid code examples that aren't contrived "shape" classes or reading a character string and making sure it isn't a number. That's what I'm always looking for on KZbin with coding. Good code that makes me think differently about how I implement/approach problems. :)
@calebkrauter4027
@calebkrauter4027 Жыл бұрын
Great video! Thank you for sharing.
@CodyEngelCodes
@CodyEngelCodes Жыл бұрын
Thanks for watching!
@saritsotangkur2438
@saritsotangkur2438 Жыл бұрын
Mocking is not bad. If you already have good unit tests for some functions, you will sometimes want to assert that those functions were called with certain parameters in the functions that call them. Otherwise you’d get a combinatorial explosion of cases you should test.
@SaifurRahman92
@SaifurRahman92 Жыл бұрын
How should we test functions that return void?
@CodyEngelCodes
@CodyEngelCodes Жыл бұрын
You should rewrite those functions so they don't return void. If that's not possible then you'd want to validate whatever side effect the `void` function causes actually happens as expected.
@nicoqueijo
@nicoqueijo Жыл бұрын
@@CodyEngelCodes Ah looks like this might answer the comment I just wrote 😅
@CallousCoder
@CallousCoder Жыл бұрын
In programming there’s a distinction between functions and procedures. Some languages (like pascal) actually have those keywords. A void (aka a procedure) just executed a set of commands and changes the state of the system. This per definition means it’s not a single unit of work and thus not a unit test. It’s potentially a candidate for a integration- or end to end test. This is why I’m more in favor of integration and end2end tests as it will implicit with also test your small functions. A function is not supposed to change the state of your system. It merely performs logic on variables and therefor doesn’t change the state of the system. I like that very strict difference, I don’t know why that separation became less and less clear as program languages got younger - well I do know just don’t really approve. As I tend to really hold firm to these two principles: A void changes my system a function merely changes program data. A void used functions to achieve that system change, a function only contributes the variables for that. So for example updating a file where you’ll remove say or Unix and for windows. You will have a function returning either or depending on the OS. You pass that in as a variable to a void (procedure) that opens the file reads the content and does the replacement and reads it back. That’s the way to separate the two. Now the astute among you will have seen immediately a little gap in that hard separation. What if you want to know if the procedure was successful? Or that opening that file was successful. You can (and should) check if the file exists and the rights are okay (two functions as they don’t change the state) but then there’s still runtime errors for example a disk failure. You could throw an error which is technically is not a return value, but ironically there was no try catch in pascal. And this is where the lines start to blur between the two. In C I tend to pass in a reference to a status variable and have that updated and checked. So it’s still a void but I have the status either in an int that I passed in or a pointer to status structure, which I update each step of the process, so that I also know and can report where a process (procedure failed). This very strict distinction I only hold dear on embedded systems as you have little to no means to actually check the state of the system and you simple have to trust that when you change an output pin or piece of hardware that it actually did that. With operating systems at the abstractions of file systems etc you can test this and I do use a return value in a “procedure” from time to time. But it’s a great practice to quickly see what changes the state of your system/program and what does not. But as with everything in CS there are edge cases that blur the edges.
@khatdubell
@khatdubell Жыл бұрын
Just a side note. Don't be afraid to write functions that return multiple values. Whatever you have to do to avoid "out parameters" (most often seen with functions that return void or bool) is _usually_ justified.
@CallousCoder
@CallousCoder Жыл бұрын
@@khatdubell I’m not a fan of returning more than one value. It is a better practice to then return a structure with the values in that structure. This also is far more portable to other languages, because most (sane) languages do not allow to return multiples values. And when you do it truly properly, aka in the C way. You allocate the structure outside of the function call and pass it in my reference and have the function update the values. But you can also return the same pointer. And of course free the pointer after your done. This is the reason to allocate it outside of the function. Because then you know you created it and you need to free it. The function can’t free it because then it’s out of scope. I’d it’s an object then it could be freed when the destructor is called but nobody knows if it is when it’s a library. And this is why I advocate first learning C and/or assembly because then you know what happens with memory management and you can make better judgement when using interpreted (ugghhhhhn) 🤮) languages.
@khatdubell
@khatdubell Жыл бұрын
Writing code without tests is a foreign concept to me at this point.
@CallousCoder
@CallousCoder Жыл бұрын
Try developing software that controls external resources like controlling cloud services or even more difficult, hardware like microcontrollers controlling AD/DA converters or i2c devices, motor controllers 😉You can’t write useful tests for that. Your mocks will be a “assumption” and thus useless. You can then only do end to end tests. But you can only write those when you’ve written the implementation 😄
@etorty_dev
@etorty_dev Жыл бұрын
The mocks won't be useless if they help test your assumptions of expected behavior and help your code robust.
@CallousCoder
@CallousCoder Жыл бұрын
@@etorty_dev assumption is the mother of all f-ups. You should develop against a test instance. That’s the only way to cover all basis. The devil is always in the details.
@real-cid-chan
@real-cid-chan Жыл бұрын
Interesting fact I have observed: If you test your initial version of your function, it is guaranteed to not work (unless it is a trivial function, in which case, testing that function might be overkill). So test that initial version, (which fails), and then start fixing it. P.S. by "initial" version of the function before you ever ran it ever.
@CodyEngelCodes
@CodyEngelCodes Жыл бұрын
Yep that's fantastic advice!
@bjk837
@bjk837 3 ай бұрын
How can you mock in a way that won’t break when you change internal implementation?
@dihakirah
@dihakirah Ай бұрын
Just avoid mocking everything
@nicoqueijo
@nicoqueijo Жыл бұрын
What about a scenario where the function that's being tested doesn't produce an output but does a side effect. Is it okay to use "verifys" there to ensure that when that function was called the code took a certain path in the function's logic?
@CodyEngelCodes
@CodyEngelCodes Жыл бұрын
You can, but if it's a side effect that's in the background it's important to ask why you're validating that it happens. If it's a side effect with no observable behavior then it may not be that important for the system to function and could just be removed. Or if it's only logging a message then it's good to ask if it's worth validating the log happened, sometimes it is important (say if it's logging an error or warning) other times it's not.
@armanmasangkay6513
@armanmasangkay6513 Жыл бұрын
Nice video. I'm curious, do you write test first or test after in your day job?
@CodyEngelCodes
@CodyEngelCodes Жыл бұрын
It depends but I almost always write the test first, then the code to satisfy the test, and then I repeat that until the task is done. For projects that are more in crunch mode I will forego writing tests but that code is really intended to only exist for a short period of time until we can go back and update it to satisfy technical requirements. I write the bare minimum required to get things to work so that ideally discourages folks from adding onto the ball of mud.
How To Write Unit Tests (The Right Way)
14:26
Cody Engel
Рет қаралды 40 М.
Agile Has Destroyed Programming - Here's How To Fix It
12:16
Cody Engel
Рет қаралды 50 М.
iPhone or Chocolate??
00:16
Hungry FAM
Рет қаралды 47 МЛН
Will A Guitar Boat Hold My Weight?
00:20
MrBeast
Рет қаралды 267 МЛН
Unit Testing Is The BARE MINIMUM
20:33
Continuous Delivery
Рет қаралды 32 М.
Theo Doesn't Write Unit Tests (This Is Why You Should)
13:01
Cody Engel
Рет қаралды 9 М.
The Lies Of 100% Code Coverage | Prime Reacts
21:42
ThePrimeTime
Рет қаралды 75 М.
I Quit My Job As An Engineering Manager (What I Learned)
8:03
Cody Engel
Рет қаралды 47 М.
Making testing fun | Andy Zaidman | TEDxDelft
10:30
TEDx Talks
Рет қаралды 38 М.
Effective Unit Testing by Eliotte Rusty Harold
48:10
Devoxx
Рет қаралды 103 М.
Thoughts About Unit Testing | Prime Reacts
11:21
ThePrimeTime
Рет қаралды 226 М.
My 25 Laws of Test Driven Development - Dennis Doomen - NDC Porto 2023
50:44
Don't Mock 3rd Party Code
19:56
Continuous Delivery
Рет қаралды 40 М.