When you talk about refactoring, I feel the same thing. I write my unit tests and my production code is covered. But, if I need to change a lot of things in Refactor step, probably my design is not well designed! In my opinion that is the point. Martin Fowler said, "TDD is a tool, and people should learn how to use it well." And it's true. TDD is just a technique, but it won't take any decisions for you. Damage is caused by people. With or without TDD, if you take good decisions, your design will be great but, if you make bad decisions, your design will be bad. Actually, I practice BDD and TDD and at the moment the experience is being great. When I need to change a lot of things in Refactor step, I try to learn what I could be done to avoid it. And to be honest, I feel very confident because the Integration and E2E test (BDD) ensure the behavior. Thank you for the talk. Cheers
nice thoughts, there is a talk from Sandro Mancuso (Does TDD lead to good design?) that complements your thoughts :D take a look, you might like it as well. Cheers
I strongly agree that outside-in testing does not mean GUI testing. Every time I mention BDD then people associate it with Selenium. Every time I mention unit testing then people associate it with the smallest of possible units which is a single class or a method. I believe the best bang for your buck lies in-between and that boundary is to be strategized per project. As I write my applications using semi-DDD and semi-CQRS then my B(T)DD boundary tends to be the execution of a command.
Thank god you're here. I've just started learning TDD recently, and I noticed about the "test every classes and methods". I felt something bad about this, but I didn't know how to fix that, I knew there's something wrong. Came your talk, you cleared my confusion and saved hairs on my head. Thank you very much!!!
Unit in unit testing means unit of functionality not unit of code. You should only test your public interface not every class / method. In other words, only test the functionality not the implementation. You end up covering a lot more with a lot less tests. And your tests tend to not break everytime you change the code.
Good talk but I think a lot of people misunderstand refactoring. Refactoring does not always mean modify existing code. The O in SOLID stands for "Open for extension, closed for modification". Once a piece of code is in production you shouldn't modify it. You can extend it or replace it, but not change it. This means new tests, new classes, and new methods. Quite often it also means new abstractions to make for a smoother transition to the new code. The temptation is to go in and simply change the existing implementation because you find some error, or the code is difficult to understand. This will often lead to failing tests so now there's a temptation to change the tests. None of that is advisable. Instead put your eye toward REPLACING the existing code with new code. It's cheap to do, you'll have more confidence in it, and it leads to more abstractions.
There's a drawback to abstraction: indirection and code clutter that makes code harder to understand. Instead of following SOLID completely, follow the Rule of Three: only refactor when you see three similar pieces of code, that way you allow some duplication in order to make sure you have a good, substitutable abstraction that has already been proven to be reused. Don't just create a 1:1 interface for every class; that's just speculative generality that you most often will never need or use. An interface should always have at least three implementors And you do need to refactor every now and then, even abstractions like renaming methods. As development continues, the design will get worse and worse. You can't just rely on upfront design as the upfront design is hardly ever right the first time. Thus, when you add a new feature but the codebase isn't convenient in a way that easily allows you to add functionality, you improve the design of the existing codebase to make it cleaner/easier to understand, and therefore making it faster and easier to implement the new feature.
I don't take the point about test coupling. Yes, it forces me to change tests when refactoring, but I think it's kinda normal. If you change "unit", you need to change "unit test". Otherwise, the unit test becomes integration test. As Uncle Bob says, TDD is a discipline, and there are some arbitrary boring rules in most disciplines. Also, when you remove test coupling, you trade understandability on flexibility.
Not sure why I was recommended this as it’s quite old. I’m trying to focus on the content but i keep giggling to myself like a ten year old as it somehow makes me think of General Grievous 🤪🤣
LOL that swallowing sounds...reminds me of that Silicon Valley episode..Im still convinced most software project failures are mainly just lack of domain knowledge. Without domain knowledge you'll never get it right. Because customers are horrible at explaining what they need in a form that a developer can understand.
I do not understand, why a controller test with a mocked service is useless. Matt says the controller does not contain logic. Sure, in this example it is trivial. But you write tests for designing a good Software architecture and for ensuring future changes do not break the rest of your logic. Furthermore, if the Controller does not contain logic, why do we need it to implement? Hence, Controller tests are useful. Especially if you want to test permissions, the correct URLs with HTTP verbs and the returned model structure including the potentially different status codes (404, 201, 204, 400,...).
Good lord!! Can we take it easy on new slang in programming for a while! Dummy, spy, stub, mock, fake, BDD, TDD, and on and on!! It is getting so damn ridiculous with all the crap we have!
My theory is that if it's obvious what your tests should be and they're simple to construct, use TDD. If they're non-obvious or a nightmare to construct, TDD might not be the way to go.
If you don't know what your tests should be, that means you don't know what your application should be. In that case, do a PoC, see if it is what you want, then erase that and do TDD the normal way.
ok, now show us a code example how to test behaviour instead of classes ... (he can't). Bad talk. He points out some problems with the TDD cargo cult, but proposes only very vague solutions.
I can't think of a better definition of "behavior" than a classes public methods, so I don't know what the solution to that could possibly be. Same with the mock of the service,it's either you're going to use the real service or your not, there isn't a middle ground
When you talk about refactoring, I feel the same thing. I write my unit tests and my production code is covered. But, if I need to change a lot of things in Refactor step, probably my design is not well designed! In my opinion that is the point. Martin Fowler said, "TDD is a tool, and people should learn how to use it well." And it's true.
TDD is just a technique, but it won't take any decisions for you. Damage is caused by people. With or without TDD, if you take good decisions, your design will be great but, if you make bad decisions, your design will be bad.
Actually, I practice BDD and TDD and at the moment the experience is being great. When I need to change a lot of things in Refactor step, I try to learn what I could be done to avoid it. And to be honest, I feel very confident because the Integration and E2E test (BDD) ensure the behavior.
Thank you for the talk. Cheers
nice thoughts, there is a talk from Sandro Mancuso (Does TDD lead to good design?) that complements your thoughts :D take a look, you might like it as well.
Cheers
when he said BDD i thought he meant Bug Driven Development, thats what i do.
peep 😂
That is not the worst Idea: Whenever you find a bug: Look for the systematic that has allowed it. Often they come by Design
Don't we all?
I strongly agree that outside-in testing does not mean GUI testing. Every time I mention BDD then people associate it with Selenium. Every time I mention unit testing then people associate it with the smallest of possible units which is a single class or a method. I believe the best bang for your buck lies in-between and that boundary is to be strategized per project. As I write my applications using semi-DDD and semi-CQRS then my B(T)DD boundary tends to be the execution of a command.
Thank god you're here.
I've just started learning TDD recently, and I noticed about the "test every classes and methods". I felt something bad about this, but I didn't know how to fix that, I knew there's something wrong. Came your talk, you cleared my confusion and saved hairs on my head. Thank you very much!!!
He lost his hair so you dont have to
Unit in unit testing means unit of functionality not unit of code. You should only test your public interface not every class / method. In other words, only test the functionality not the implementation. You end up covering a lot more with a lot less tests. And your tests tend to not break everytime you change the code.
Would really like to see some actual examples.
Good talk but I think a lot of people misunderstand refactoring. Refactoring does not always mean modify existing code. The O in SOLID stands for "Open for extension, closed for modification". Once a piece of code is in production you shouldn't modify it. You can extend it or replace it, but not change it. This means new tests, new classes, and new methods. Quite often it also means new abstractions to make for a smoother transition to the new code. The temptation is to go in and simply change the existing implementation because you find some error, or the code is difficult to understand. This will often lead to failing tests so now there's a temptation to change the tests. None of that is advisable. Instead put your eye toward REPLACING the existing code with new code. It's cheap to do, you'll have more confidence in it, and it leads to more abstractions.
There's a drawback to abstraction: indirection and code clutter that makes code harder to understand. Instead of following SOLID completely, follow the Rule of Three: only refactor when you see three similar pieces of code, that way you allow some duplication in order to make sure you have a good, substitutable abstraction that has already been proven to be reused. Don't just create a 1:1 interface for every class; that's just speculative generality that you most often will never need or use. An interface should always have at least three implementors
And you do need to refactor every now and then, even abstractions like renaming methods. As development continues, the design will get worse and worse. You can't just rely on upfront design as the upfront design is hardly ever right the first time. Thus, when you add a new feature but the codebase isn't convenient in a way that easily allows you to add functionality, you improve the design of the existing codebase to make it cleaner/easier to understand, and therefore making it faster and easier to implement the new feature.
Fantastic talk, every developer who makes tests should listen talks like this.
Awesome talk. Thanks. Especially the fact, that you see only the slides, so you can follow the topic.
Did I miss it, or did he never finished the story about the company and their unit tests? (outside of just saying they were still around).
Yup. He said "what went wrong? We'll come back to this as the end", and then... he only said they're still around.
This is a very good talk, all the principles talked here are to the point.
I don't take the point about test coupling. Yes, it forces me to change tests when refactoring, but I think it's kinda normal. If you change "unit", you need to change "unit test". Otherwise, the unit test becomes integration test. As Uncle Bob says, TDD is a discipline, and there are some arbitrary boring rules in most disciplines. Also, when you remove test coupling, you trade understandability on flexibility.
Not sure why I was recommended this as it’s quite old. I’m trying to focus on the content but i keep giggling to myself like a ten year old as it somehow makes me think of General Grievous 🤪🤣
I think at this time the definition should be changed to UTDD, U is for Unit, makes things less confusing
Great talk. Matt could you post a link to a TDD open source project you mentioned during questions?
A Ruby example: github.com/moonmaster9000/board_app
A Java example: github.com/moonmaster9000/RegisterApp
fantastic talk. Thanks for upload it
Strepsils... The main takeaway I got was Strepsils
This is more of bad practices in testing. how is it TDD related?
LOL that swallowing sounds...reminds me of that Silicon Valley episode..Im still convinced most software project failures are mainly just lack of domain knowledge. Without domain knowledge you'll never get it right. Because customers are horrible at explaining what they need in a form that a developer can understand.
Or developers are terrible at understanding the customers needs?
I do not understand, why a controller test with a mocked service is useless. Matt says the controller does not contain logic. Sure, in this example it is trivial. But you write tests for designing a good Software architecture and for ensuring future changes do not break the rest of your logic. Furthermore, if the Controller does not contain logic, why do we need it to implement?
Hence, Controller tests are useful. Especially if you want to test permissions, the correct URLs with HTTP verbs and the returned model structure including the potentially different status codes (404, 201, 204, 400,...).
Good lord!! Can we take it easy on new slang in programming for a while! Dummy, spy, stub, mock, fake, BDD, TDD, and on and on!! It is getting so damn ridiculous with all the crap we have!
Look outside of what you want to discover, is not form J. WILK. Is an Oriental common practice.
my suggestion is to always ask yourself: "how can i do this with less work"
My theory is that if it's obvious what your tests should be and they're simple to construct, use TDD. If they're non-obvious or a nightmare to construct, TDD might not be the way to go.
If you don't know what your tests should be, that means you don't know what your application should be. In that case, do a PoC, see if it is what you want, then erase that and do TDD the normal way.
ok, now show us a code example how to test behaviour instead of classes ... (he can't). Bad talk. He points out some problems with the TDD cargo cult, but proposes only very vague solutions.
I can't think of a better definition of "behavior" than a classes public methods, so I don't know what the solution to that could possibly be. Same with the mock of the service,it's either you're going to use the real service or your not, there isn't a middle ground
The coughing is REALLY offputting
Drinking noises are REALLY annoying in talks...
drinkin noises?
@@einfacherkerl3279
Yes, you know, noises that result from drinking loudly close a microphone