I don't think it's taught in academia. This is only anecdotal, but I ask our summer interns about TDD. None of them know about it. I interview candidates, both interns and full time employees. Rarely do any of them know about it. I don't think I've ever interviewed someone who says they practice it. It's not valued because it's seen as code that's not part of the final shipped product. I understand this from the customer. I somewhat understand it from management. But it saddens me when developers feel this way. Our CI/CD pipeline has code coverage thresholds to try and force better unit tests. But developers still don't practice TDD. I can't tell you how many times I've heard Scrum status with, "Yesterday I implemented the feature. Today I'm going to write the unit tests." Incentives also cause this. Writing unit tests take time. Refactoring takes time. We're all under time pressure. Developers will cut corners and deliver un-tested and un-refactored code, because it's faster in the short term, but it causes massive problems in the long term. Projects die the death of a thousand cut corners.
Yes, I find the same thing and it does sadden me. I think that TDD is one of the most significant advances in SW dev since I started. It is CERTAINLY more important than the differences between languages and frameworks. I have often heard the "but we don't have time to write tests" argument. To me this sounds like "But I don't have time to put petrol in my car". Just dumb!
For those of us who are old enough to have lived through times where the simple concept of testing wasn't around, seeing the benefits that testing methodologies brought to the software industry it's kind of easy. But for those that just started in this industry when testing methodologies already existed, it became just another thing they have to do. I often think it's "our" fault that we didn't get the right message passed into the new generations... The biggest issue I see being raised against testing (in general, but unit testing in particular), usually from managers, is that it's too time-consuming. Strangely enough, they don't think it's time-consuming to be doing bureaucratic work. ¯\_(ツ)_/¯ Anyway, your work on these videos is absolutely amazing! I'm rerally learning with you! Well done Sir! 👏
I feel almost as if TDD is sort of like having a conversation about your code’s purpose with the codebase. It is a sort of “talking in the mirror” exercise and so in a way, it is sort of like pair programming. You are explaining to someone what the code does and making sure the explanation is solid. And then, you are building what you explained. I see now that this is a very fundamental feedback loop in all of reality. It is what businesses do all day and it is the purpose of communication itself. We are constantly hearing ideas, converting them into explanations, and then executing what we explained. And after that, refactor aka reflect and refine your processes.
I think your refactoring is risky because you start with the code and adjust the test to match the code. Shouldn't it be the other way round? For me refactoring is meant not to break any tests (ideally)
That's not exactly what's happening. The red stage is intentional failure to ensure no false positives. Green is a passing test made on viable code. Refactor is self-explanatory. You aren't adjusting the test to match the code after the green stage, but you are refactoring the test to be as efficient as easily readable as possible.
Well there are two answers to that. Run the test once it is written and see if it fails in the way that you expect. If it doesn't, it is probably testing the wrong things. This "tests the test", but my guess is that you mean something else. I think that maybe you mean "how can I write a test, for code when I don't know how that code works". The trick is to split "what" from "how", if you are about to write code, then you have some idea of the problem that you are going to solve. That is the "what" and that should be the focus of your test. A good test is only focussed on "what" your code needs to do, while saying as little as possible about "how" it does it. That means that not only *can* you write the test before you have figured out how to solve the problem, but you *should*, because then your tests are decoupled from your code and so your code can change without breaking the test. If you can't think of what test to write then, it probably means you don't yet know "what" the problem that you are trying to solve is, and you really should have an idea about that before writing the code.
This example fails to prove the point of TDD, because you can't reasonably think you would do anything like this in a real project, and here is why. The RED part fails where you're supposed to design the interface of what you will implement. But what kind of real-world design would expect a string out of an operation with fractions? You don't separate concerns right from the start in the interface, right in the design, where calculation is mixed up with formatting. So you do all this unneeded work in the GREEN part where the REFACTORING part fixes RED's costly failure that could have been prevented. I understand that sometimes your implementation does not end up looking clean, but this is a trivial interface! If we cannot get such things right in the interface, how are we supposed to believe that TDD is useful? (Yes, sometimes we end up refactoring for interfaces for ISP and other reasons, but that's different, because the system already became complex, and sometimes you don't foresee things.) Also, if we truly want to follow TDD, then we don't even create classes. We don't do GREEN's work in RED's phase. We just let the code not compile. If you really want to be able to add fractions together, the simplest thing to do is store all data as fractions, not string. Noone talked about formatting! I refuse to believe that we can allow ourselves to be this sloppy in the RED part. We're not supposed to create problems, we're supposed to solve them. Yes in order to see why REFACTOR is meaningful, you will have to do more iterations. The first few steps of TDD will be trivial in kata coding examples, with rarely any refactoring needs.
@@hunahpuyamamoto3964 I understand that, but my point is that TDD is hard to do right, and when it's applied incorrectly, some people will blame TDD for their lost time and money, wanting to see it never again. The skeptical people won't let themselves fooled thus won't even try if they aren't concinved it will have a return of investment, and for that you need a well-founded example. And the learners of TDD are the ones who only scratched the surface of a new style of development, they need the solid grounds to be able to fight against these kinds of people. They are the ones who can easily be pushed into the "dark side" if the teaching is not effective.
@@nickschmitt8594 Sure, I can make a recommendation, but I don't know what the best sources are. If you allow me to suggest a paid one: the Clean Coders video series ("Fundamentals" and "Advanced TDD") by Robert C. Martin. While I agree with several things he teaches, and they helped me a lot, it's important to keep an open eye that no teaching may be 100% suitable all the time in every scenario.
Yes, and the first "solve" should be return "7"; Since that is the least possible effort to make the test pass. Secondly, TDD (Uncle Bob Martin variant) "demands" that the Test must be added/changed first, so the Refactoring stage should have modified the assertEquals() before tackling the implementation... IMHO (as fairly experience (25 years) Java developer), TDD "courses" teaches a very naive path that has practically no path in real world circumstances. a) Always touching on problems that has known solutions, e.g. "I need Fractions" in the video whereas perhaps "I actually don't know what I will need". b) Never intermingled with libraries that must be used, or external systems that form an integral part of the solution. c) Assumes that software is built from bottom up, and if that is the approach, then TDD's "API design" has value, since you don't yet know the use case. BUT if you do top down, then you start out with main() and don't have any testable units for quite some time, how do I write a test for "public static void main(String[] args)" ? d) Assumes that we fully understands the inputs. Most my bugs revolves around unspecified acceptable inputs and I made incorrect assumptions. Tests won't help with that and might slow me down before I can get to "real world environments". I think most people easily subscribe to "the right tool for the job" and TDD is simply not the right tool at all times. BE WARY of Silver Bullet Sales People. Also, there is a "shaming" tactic present in the industry as well. Just because I oppose TDD at times, doesn't mean that I oppose tests. Again, right tool for the job, e.g. having detailed unit tests for implementation details can stifle large refactorings, whereas a suite of functional tests might not need to change much when replacing the implementation.
Why do you think TDD isn't as valued as it should be?
I don't think it's taught in academia. This is only anecdotal, but I ask our summer interns about TDD. None of them know about it. I interview candidates, both interns and full time employees. Rarely do any of them know about it. I don't think I've ever interviewed someone who says they practice it.
It's not valued because it's seen as code that's not part of the final shipped product. I understand this from the customer. I somewhat understand it from management. But it saddens me when developers feel this way. Our CI/CD pipeline has code coverage thresholds to try and force better unit tests. But developers still don't practice TDD. I can't tell you how many times I've heard Scrum status with, "Yesterday I implemented the feature. Today I'm going to write the unit tests."
Incentives also cause this. Writing unit tests take time. Refactoring takes time. We're all under time pressure. Developers will cut corners and deliver un-tested and un-refactored code, because it's faster in the short term, but it causes massive problems in the long term. Projects die the death of a thousand cut corners.
Yes, I find the same thing and it does sadden me. I think that TDD is one of the most significant advances in SW dev since I started. It is CERTAINLY more important than the differences between languages and frameworks.
I have often heard the "but we don't have time to write tests" argument. To me this sounds like "But I don't have time to put petrol in my car". Just dumb!
Socialism
For those of us who are old enough to have lived through times where the simple concept of testing wasn't around, seeing the benefits that testing methodologies brought to the software industry it's kind of easy. But for those that just started in this industry when testing methodologies already existed, it became just another thing they have to do. I often think it's "our" fault that we didn't get the right message passed into the new generations...
The biggest issue I see being raised against testing (in general, but unit testing in particular), usually from managers, is that it's too time-consuming. Strangely enough, they don't think it's time-consuming to be doing bureaucratic work. ¯\_(ツ)_/¯
Anyway, your work on these videos is absolutely amazing! I'm rerally learning with you! Well done Sir! 👏
Great video, looks like the aspect ratio is off when Dave is showing (squished slightly perhaps)?
I feel almost as if TDD is sort of like having a conversation about your code’s purpose with the codebase.
It is a sort of “talking in the mirror” exercise and so in a way, it is sort of like pair programming.
You are explaining to someone what the code does and making sure the explanation is solid. And then, you are building what you explained.
I see now that this is a very fundamental feedback loop in all of reality.
It is what businesses do all day and it is the purpose of communication itself.
We are constantly hearing ideas, converting them into explanations, and then executing what we explained. And after that, refactor aka reflect and refine your processes.
The content on this channel blows freecodecamp and the like out of the water. Great job!
Wow, thanks!
Thank you, Dave!
Great video thank you, it would be awesome if you could share your take on the London vs Detroit schools of TDD
Really love your channel.
I think your refactoring is risky because you start with the code and adjust the test to match the code. Shouldn't it be the other way round? For me refactoring is meant not to break any tests (ideally)
That's not exactly what's happening. The red stage is intentional failure to ensure no false positives. Green is a passing test made on viable code. Refactor is self-explanatory. You aren't adjusting the test to match the code after the green stage, but you are refactoring the test to be as efficient as easily readable as possible.
Insightful!!
My prob with writing tests first is. How do i know if my test is right?
Well there are two answers to that. Run the test once it is written and see if it fails in the way that you expect. If it doesn't, it is probably testing the wrong things. This "tests the test", but my guess is that you mean something else. I think that maybe you mean "how can I write a test, for code when I don't know how that code works". The trick is to split "what" from "how", if you are about to write code, then you have some idea of the problem that you are going to solve. That is the "what" and that should be the focus of your test. A good test is only focussed on "what" your code needs to do, while saying as little as possible about "how" it does it. That means that not only *can* you write the test before you have figured out how to solve the problem, but you *should*, because then your tests are decoupled from your code and so your code can change without breaking the test. If you can't think of what test to write then, it probably means you don't yet know "what" the problem that you are trying to solve is, and you really should have an idea about that before writing the code.
This example fails to prove the point of TDD, because you can't reasonably think you would do anything like this in a real project, and here is why. The RED part fails where you're supposed to design the interface of what you will implement. But what kind of real-world design would expect a string out of an operation with fractions? You don't separate concerns right from the start in the interface, right in the design, where calculation is mixed up with formatting. So you do all this unneeded work in the GREEN part where the REFACTORING part fixes RED's costly failure that could have been prevented. I understand that sometimes your implementation does not end up looking clean, but this is a trivial interface! If we cannot get such things right in the interface, how are we supposed to believe that TDD is useful? (Yes, sometimes we end up refactoring for interfaces for ISP and other reasons, but that's different, because the system already became complex, and sometimes you don't foresee things.) Also, if we truly want to follow TDD, then we don't even create classes. We don't do GREEN's work in RED's phase. We just let the code not compile. If you really want to be able to add fractions together, the simplest thing to do is store all data as fractions, not string. Noone talked about formatting! I refuse to believe that we can allow ourselves to be this sloppy in the RED part. We're not supposed to create problems, we're supposed to solve them. Yes in order to see why REFACTOR is meaningful, you will have to do more iterations. The first few steps of TDD will be trivial in kata coding examples, with rarely any refactoring needs.
@@hunahpuyamamoto3964 I understand that, but my point is that TDD is hard to do right, and when it's applied incorrectly, some people will blame TDD for their lost time and money, wanting to see it never again. The skeptical people won't let themselves fooled thus won't even try if they aren't concinved it will have a return of investment, and for that you need a well-founded example. And the learners of TDD are the ones who only scratched the surface of a new style of development, they need the solid grounds to be able to fight against these kinds of people. They are the ones who can easily be pushed into the "dark side" if the teaching is not effective.
@@SirWolf2018 What resources would suggest for an education in TDD?
@@nickschmitt8594 Sure, I can make a recommendation, but I don't know what the best sources are. If you allow me to suggest a paid one: the Clean Coders video series ("Fundamentals" and "Advanced TDD") by Robert C. Martin. While I agree with several things he teaches, and they helped me a lot, it's important to keep an open eye that no teaching may be 100% suitable all the time in every scenario.
@@SirWolf2018 Thanks
Yes, and the first "solve" should be
return "7";
Since that is the least possible effort to make the test pass. Secondly, TDD (Uncle Bob Martin variant) "demands" that the Test must be added/changed first, so the Refactoring stage should have modified the assertEquals() before tackling the implementation...
IMHO (as fairly experience (25 years) Java developer), TDD "courses" teaches a very naive path that has practically no path in real world circumstances.
a) Always touching on problems that has known solutions, e.g. "I need Fractions" in the video whereas perhaps "I actually don't know what I will need".
b) Never intermingled with libraries that must be used, or external systems that form an integral part of the solution.
c) Assumes that software is built from bottom up, and if that is the approach, then TDD's "API design" has value, since you don't yet know the use case. BUT if you do top down, then you start out with main() and don't have any testable units for quite some time, how do I write a test for "public static void main(String[] args)" ?
d) Assumes that we fully understands the inputs. Most my bugs revolves around unspecified acceptable inputs and I made incorrect assumptions. Tests won't help with that and might slow me down before I can get to "real world environments".
I think most people easily subscribe to "the right tool for the job" and TDD is simply not the right tool at all times. BE WARY of Silver Bullet Sales People.
Also, there is a "shaming" tactic present in the industry as well. Just because I oppose TDD at times, doesn't mean that I oppose tests. Again, right tool for the job, e.g. having detailed unit tests for implementation details can stifle large refactorings, whereas a suite of functional tests might not need to change much when replacing the implementation.