@@fabricatorzayac Grug's favorite way to improve his co-workers' productivity!
@limbo3545 Жыл бұрын
@@packediceisthebestminecraf9007 *grug tempted to reach for club*
@matroqueta6825 Жыл бұрын
Traumatized Developer Disorder
@oscareriksson9414 Жыл бұрын
Haha on point!
@limbo3545 Жыл бұрын
I do TDD when I know exactly what I need and how it has to work. That's not always the case. It's a tool like any other. No more, no less.
@ShadoFXPerino Жыл бұрын
The problem is that test coverage is a measurable stat, and bigger number better.
@limbo3545 Жыл бұрын
@@ShadoFXPerino It's a starting point and not an absolute. You can still do coverage afterwards and extend the tests. It's not set in stone.
@antdok9573 Жыл бұрын
TDD shouldn't focus on implementation detail. It should focus on creating a healthy design. I do agree, however, that it is a tool.
@isaacyonemoto Жыл бұрын
Huh. I only use TDD when I don't know what to do.
@banatibor83 Жыл бұрын
@humbei it is completely fine to start without test, but you soon fell into the tdd cycle and refactor your code driven by tests
@tribble1 Жыл бұрын
Far more common is technical debt driven development
@adama7752 Жыл бұрын
//TODO: complete this comment
@antdok9573 Жыл бұрын
@@adama7752 DO NOT TODO! At least don't commit it to your repo. TO DON'Ts as they're more commonly known :)
@freesoftwareextremist8119 Жыл бұрын
// TODO: 2008-04-23 Remove after other team gets their shit together
@TehKarmalizer Жыл бұрын
@@antdok9573agreed. Even throwing not implemented exceptions is something you won’t see until runtime. A comment easily goes under the radar.
@elcapitan61266 ай бұрын
tech debt is the reason we all remain employed 😂
@alichamas63 Жыл бұрын
What's worse than TDD is an extremely opinionated colleague who judges you by your lack of interest in TDD...yet production is full of their code with no TDD
@michaelthompson7217 Жыл бұрын
pretty sure the engineer you’re describing is Dave from Continuous Delivery
@skleon Жыл бұрын
For me the "problem" with TDD is that it amplifies the advantages and disadvantages of just testing. And there are MANY bad practices in tests. The most common one I see is testing implementation rather than behavior (that alone is the source of 90% of the pain of testing and refactoring). If you have bad testing practices, TDD will make everything worse, but if you have good testing practices, TDD will make things better.
@kelvinwalter8623 Жыл бұрын
What are some good testing practices?
@sqeaky8190 Жыл бұрын
@@kelvinwalter8623 Not testing the implementation. Trying to keep tests declarative. Covering boundaries of the inputs (test min/max and +1 beyond). Checking that failure states are predictable. Try to write tests somehow convey intent because code often can't.
@martinbecker1069 Жыл бұрын
This is why the person who came up with TDD hates it being called TDD, that it should be called BDD (Behaviour Driven Development).
@sqeaky8190 Жыл бұрын
@@martinbecker1069 And BDD got co-opted by the cucumber/gherkin people even though it doesn't need to be married to a silly requirements specification.
@martinbecker1069 Жыл бұрын
@@sqeaky8190 "requirements specification"?
@gavinh Жыл бұрын
He said “…if you can love a tool.” Not “…if you can love at all.”
@JD-mz1rl9 ай бұрын
So.... 1.25x was still too fast for him...
@Jak132619 Жыл бұрын
I'm in the TDD camp, and I rarely write unit tests. I feel like unit tests are a bit of a straw man here, they are a terrible candidate for TDD for the exact reasons you gave: when tests are small they are difficult to refactor. You are coupling tests to functions/files/classes and if you ever need to move logic out of these places then you also have to change the test file which slows you down. TDD is better when you're writing integration tests: all your test should care about is the inputs and the outputs, so you're free to design and change the code however you want during refactoring as long as it gives the correct output from the same input.
@JChen7 Жыл бұрын
What's your stance on mocking?
@Jak132619 Жыл бұрын
@@JChen7 I like mocking, but can understand why some people dislike it. It's a tool that's easy to abuse. If I want to write tests that test my whole application, but I don't want to test external dependencies (like database connections, s3, etc) I like using mocks. What's important is to mock as little code as possible so that you are only mocking the external dependency but are still testing all your own code, and you do this by pushing dependencies to the boundaries of your application. For example, if you make a database connection, make sure only the logic necessary to do that sits in one function and only mock that function in your test. A good way to practice doing this is to force yourself not to use mocking libraries, but instead abstract your dependencies behind an interface, and then create a service that implements that interface which you use in your tests instead of the real thing. When constraining yourself this way it is difficult to abuse mocks and can teach you good habits in pushing dependencies to your application's boundary, although It's important to be wary that you are adding extra abstractions which can create a different set of problems later down the line.
@Turalcar Жыл бұрын
The dude in the vid specifically mentions unit testing.
@Jak132619 Жыл бұрын
@@Turalcar Hence why I said he was straw-manning unit testing, did you not read my response?
@Turalcar Жыл бұрын
@@Jak132619 Not Primegen. The guy he was watching was suggesting unit testing
@onecrazygenius Жыл бұрын
The chatter who put "blue = rewrite everything (in rust)" is a based, high value programmer
@RenderingUser Жыл бұрын
but rust = red
@k98killer Жыл бұрын
I tend to write code twice: the first time, I just play around in a scratchpad repo with spaghetti; the second time, I structure the code more sanely and add tests. The second iteration can be TDD because by then I've figured out what I want the code to do.
@samjohns8381 Жыл бұрын
This is actually still TDD which is a big thing no one understands (since I don't think anyone actually reads anything about it). You are describing a "spike".
@k98killer Жыл бұрын
@@samjohns8381 yeah, I've never heard that term used in discussions about TDD
@edwardcullen1739 Жыл бұрын
You just described "requirements discovery"...
@samjohns8381 Жыл бұрын
@@edwardcullen1739 I described-well really OP described-figuring out how a requirement will be solved with code.
@jameswilkinson8940 Жыл бұрын
This 100%
@allalphazerobeta8643 Жыл бұрын
One thing I really hate. 19:00 Is when people call surveying or observational studies, Scientific. They are inherently not. Science needs a hypothesis and your test of the hypotheses can't have a pre-known outcome. This is really grinding my gears given that test driven development needs to have the test written first. Now, it's good to get collect data and to write it down even if you don't have a hypotheses and it can find truths. But it's not Science. Science doesn't equal getting data.
@NathanHedglin Жыл бұрын
but but it fits his narrative
@alfredomoreira6761 Жыл бұрын
Refactor part of TDD is also refactor of your design (not just implementation of your function). So yes, when doing TDD you throw away tests. Tests are a way for you to learn how to design, not just how to implement your function. This means, part of the work is throwing away all your code and your tests. Just like when you do it without TDD and you throwed your function away because you gained knowledge. Summary : Refactor = refactor implementation + refactor design Refactor X = create or update or delete
@sorcdk2880 Жыл бұрын
You know, to do refactoring efficiently, you want to have tests that you do not throw away, such that you are sure that things keep working and the steps you took worked out right. If you are throwing practically all those relevant tests out, then you are not so much refactoring as you are throwing out the old and starting almost from scratch again.
@alfredomoreira6761 Жыл бұрын
@@sorcdk2880 Someone removed my folloup comment. Just apply parrallel changes refactoring pattern. and once you are done, remove the old impl and tests.
@ryanbeatbox9 ай бұрын
@@sorcdk2880Well, you'd be doing that without TDD also. If you're throwing away full functionalities and moving away from the original specification, then with or without TDD, you're changing everything and essentially starting from scratch anyway. I think the issue here is the misuse of the term refactoring, if you're changing out everything then you're restructuring, not refactoring. No matter what you use or whatever your methodology is, you're changing out everything anyway. Throwing away useless tests at this point is irrelevant regardless of how you implemented them.
@sorcdk28809 ай бұрын
@@ryanbeatbox Not exactly, outside of TDD then the timing of it and the way tests are designed and their purpose makes it such that you can often get around this problem outside of TDD.
@TheBrazilRules6 ай бұрын
Oh, so now I have twice the garbage I wasted my time on to throw away. Does not sound like a good proposition...
@chip243 Жыл бұрын
Thinking about comment at 5:50, if refactoring your code causes your black box tests to break, are you sure you are testing a black box?
@ParkourGrip Жыл бұрын
I'm pritty sure that he thinks that when you have small unit tested units, the refactoring will almost always change the interface of multiple units and that will brake the tests for these units.
@BryonLape10 ай бұрын
Agreed. He is neither black box testing nor using Unit tests.
@fetherfulbiped Жыл бұрын
I think Ian Cooper's talk about TDD addresses most of the problems with TDD better than Dave's video and most of the points that Prime raises as well kzbin.info/www/bejne/e4uTZphterKCgq8&ab_channel=DevTernityConference. I personally do not like TDD that much, but I think it is extremely useful when you want to design an API/a tool that is supposed to provide some kind of a service to third parties/other services in-house because I find it easier to design the tool itself when I have to make black-box assertions about the tool's interface in a way that this tool's users would make, and it is really nice to have those assertions in the form of tests.
@RemyDuijkeren Жыл бұрын
I also dislike TDD, but this talk by Ian Cooper is the first one that explained the idea clearly and made me think about the usefulness. The main point is not doing it at the unit test level. That is too low, wrong, and not valuable. Prime you should see this talk!!!
@tomvahlman823511 ай бұрын
@fetherfulbiped Ian Cooper's talk about TDD is one of the best ones, addressing the problem that people think you should do TDD to test-drive class methods. Farley is repeating himself in many of his videos, due to commercial interests, however I think he is an excellent talker. Proven by this video which describes TDD very well. kzbin.info/www/bejne/op-XiKGujZKqqNk
@JD-mz1rl9 ай бұрын
I think if you have clearly defined requirements of what you're trying to create, then TDD makes sense. The problem with TDD when the above is not true, is that you spend time writing for something that actually isn't needed
@LordOfElm Жыл бұрын
When working on projects with other developers I'm significantly more concerned when JS/TS programmers import 600 moving target dependencies maintained by thousands of strangers than I am whether they wrote tests for their 20 line function.
@forbiddenera Жыл бұрын
Yep. It doesn't help when you import one or two things you actually need but those things import hundreds of modules.
@thekwoka470710 ай бұрын
This is not remotely limited to JS/TS. You see it in tons of stuff. Add one crate to your rust project, suddenly 300 download.
@josda1000 Жыл бұрын
Prime... I think a unit is meant to be a public function, or similar. A private is an implementation detail. If you think this way, then you can refactor any way you want, including breaking up into private functions or even a class. Doing this means you won't necessarily have to specifically test the newly created class, but of course you can.
@francoisconstant5986 Жыл бұрын
Exactly; a public function (for unit / integration tests) or a public feature (for functional tests). The tests you write should help you refactor; not slow you down.
@nerdycatgamer Жыл бұрын
I'm still in school and they don't really teach us about testing in class, so I don't have much knowledge or experience, but from my intuition this is what I assumed would be the case, so I've always been confused whenever Prime starts talking about testing and this sort of topic comes up.
@AnthonyBullard Жыл бұрын
A unit is publicly used member of a module.
@jeroen1473 Жыл бұрын
If it was a function test we would have called it a function test.
@manawardhana Жыл бұрын
Based on your statement, I think it is fair to say the unit, aka public function or like, has one or more supporting private functions/methods? So, if one private function involves complex logic, how do we test the private function independently? So, unit tests are some kind of integration tests as we test private functions through a proxy: public function?
@markonovakovic3838 Жыл бұрын
I'm doing TDD for 4 years and I love it. I absolutely love it. In process of adopting TDD into my workflow I was so frustrated. I dropped it 3 or 4 times before finally adopting it. There are a lot of gotchas and you are better getting a mentor to resolve the confusion instead of stumbling onto those by yourself.
@tongobong1 Жыл бұрын
You should know that TDD doesn't produce good designs only mediocre. To get to good designs you should redesign after every large increase of code size. Beside many "small" unit tests created by TDD are just useless and you should delete them.
@markonovakovic3838 Жыл бұрын
@@tongobong1 I agree with with everything except last sentence.
@tongobong1 Жыл бұрын
@@markonovakovic3838 The most overlooked advice about how to properly do the TDD is advice on deleting useless tests and I believe this is the main reason why TDD is just not that great in practice. Look what inventor of TDD Kent Beck did in his famous book. He deleted the testFrancMultiplication test because he wrote larger tests that fully covered the functionality of this smaller test. There is no proper TDD without deleting useless tests.
@vaisakh_km Жыл бұрын
0-test development is the best XD.... 1. i can ship project faster.. 2. I can get more money from client for fixing more bugs.... 3. but fixes create more bugs, means more money... and of course job security...
@NathanHedglin Жыл бұрын
tests don't prevent bugs. How does writing code to tests for bugs I can think of testing prevent bugs I didn't know to test for?
@vaisakh_km Жыл бұрын
@@NathanHedglin but testing prevent know edge cases right? we can avoid fixing that :)
@ronaldgipa873110 ай бұрын
@@NathanHedglin Not all bugs are new bugs. Some bugs are recurrent bugs that reoccur when you make changes. Some changes can affect other parts of the code
@EyalShalev Жыл бұрын
I think TDD forces you to write code that is easily testable. I've seen a lot of code written without testing in mind, which made it very hard to write good tests for it.
@wantedsavage7776 Жыл бұрын
That’s something new to me. But no one expressed such idea from both sides.
@njnjhjh8918 Жыл бұрын
Definitely true.
@streettrialsandstuff Жыл бұрын
Dependency injection and SOLID principles is enough to get testable code without writing tests first.
@d3stinYwOw Жыл бұрын
@@streettrialsandstuff It's not, really.
@mlntdrv Жыл бұрын
@@streettrialsandstuff that's only for being able to use test doubles. For making sure that your test is simple and relatively short, you have to write it together with the production code, otherwise you neglect your test code OR are a god.
@badunius_code Жыл бұрын
What does it mean if all tests are green? The only correct answer is "Nothing" it means literally nothing at all. It doesn't mean your code is good, or clean, or safe, scalabale/maintainable/whatever--none of this. It only mean it satisfying the current state of tests which itself is a subject to change.
@cheaterman49 Жыл бұрын
Also, RE: skill issue and/or it takes time to "click" and/or "you can't get it if someone simply forces you", when I started introducing TDD to my non-backend-lovers juniors they absolutely loved it almost instantly (beyond admittedly a bit of initial "seems tedious") ; the boost in confidence they get from not only testing their code but being relatively certain (since the test failed initially) that their test actually exercises their implementation (... and that they didn't break anything else) is massive!
@georgehelyar Жыл бұрын
Honestly I find it hard to even get people to write tests at all, if they have never written them before. There always seems to be a period of "why am I writing the code twice" or "this is just for a code coverage stat" before it really clicks that they should be testing for the behaviours that they want, rather than testing the code does what the code does. Once that clicks, writing tests is great, but I think it does take a bit of time before it clicks, and then TDD is even more difficult because you need to completely change how you write code, and if you've been writing code for a long time, that's hard to do.
@tanotive6182 Жыл бұрын
Front end TDD is the biggest ball ache though. We’re developing an app and are forced to do TDD. I’ve been doing it for a year now and it’s just a massive chain having to write the tests up front. Frequently we get feedback from marketing and users that they don’t like something when we initially send something through and have to completely change it. Also UI changes before feature deliveries are fairly common so all that work initially on writing those tests is a massive waste of time. Literally wanna tear my bloody hair out doing TDD for ui that can change frequently. Love testing but seriously hate TDD. I think it’s a waste of time to write your tests up front.
@cheaterman49 Жыл бұрын
@@tanotive6182 Yeah generally speaking I don't think I'll ever try to test frontend code ; that's a job for the QA team, aside from some very punctual (extremely rare) complex logic I might wanna unit test to get right. EDIT: OTOH I completely disagree with you about blaming TDD on this ; the blame falls squarely on TDD misuse - I don't really believe in testing frontend automatically as I said. (EDIT2: An extremely basic reason for this is that most UI testing tools will be able to click a 0.25x0.25 pixel button that would be entirely impossible for a human to do... I don't see the point)
@andave1 Жыл бұрын
@@tanotive6182it sounds to me like you're testing the UI at too low of a level, likely testing implementation rather than behavior (which is a common problem). For one, it sounds like your team has a problem with knowing what to actually build. The UI should usually be the first thing understood since it's where the testing should start whether it's TDD or not. Second, I'm struggling to see how the change is the core problem even if you're testing UI implementation. If you change from radio buttons to some kind of fancy collapsible selection, the level of abstraction should be the same so in the test you change "selectRadio(element)" to "selectFancy(element)". Unless you're talking about the difficulty of implementing "selectFancy()" compared to the radio version, I don't see how this is a testing problem, much less TDD. It sounds like a misuse problem, like others mentioned.
@trumpetpunk42 Жыл бұрын
@@georgehelyarI can't find the article, but I remember hearing this referred to as "flipping the bit" in your brain, regarding testing
@bangonkali Жыл бұрын
This is exactly why I always have 2 kinds of branches. 1 is for exploratory, experimental or prototypical stage (exp). Another for production code. These 2 are separate and have different goals but ultimately the end game is to deliver correct code. The exp branch is built in a fail fast manner to explore the problem space. It also includes exploration on how to implement potential solutions and how to test them. Sometimes we don't even know how to to build the test harness so this is the time to explore how one would go about it. The exp doesn't have to solve the problem to the end, it just has to establish the framework for means of solving the problem and the proof of concept on how tests might be written. Once a certain level of confidence has been established and presented to the group then we proceed to the next phase. The output of exp is then rewritten test first with tdd in mind in the production branches. The tests can be made in bulk at this time and one after another the implementation will follow. What's even funny is that sometimes QA team who works on test suites also have designed so many tests already that a separate team writes these tests in to code just to catch up with the amount of tests while implementation is ongoing. They are peer reviewed according to production quality standards. Sometimes the problem space is well known enough and the means to create test harness for them is well established don't need exp branches and can be worked on directly in tdd. So I would say we do xtdd approach. explore experiment or prototype when needed then do tdd for production code. One can then iterate features on production quality branches given the dev understands the problem space and the means to test well enough otherwise they need to explore first. For me I think it's about being practical and to actually give people the chance to understand before requiring rigid standards.
@suede__ Жыл бұрын
I don’t think I’ve ever had even 1/4 of the time for a feature that you seem to have to be able to do that.
@bangonkali Жыл бұрын
@@suede__ I totally agree with you sometimes projects do not have enough budget money, time or human resources and In those cases people left right and center will try to cut corners where they can to deliver something. How the quality is for the something with corners cut all over the place is another story. Sometimes you can get lucky and nothing bad happens but sometimes we can get unlucky and wrong dosage medicine is mixed killing patient, failed mishandled financial transactions, planes crashing, random acceleration in cars, gas pipelines pressure valves randomly closing or electrical grid failures. 😅 If you're working on another todo list then the consequences may not be as dire.
@yuriy53764 ай бұрын
Now get ready for Dave to get medieval on your arse about how how this goes against another one of his religions - trunk-based development 😂
@danidotexe_ Жыл бұрын
one thing i would say for everyone who, like me, finds TDD impractical, is that compiler errors are tests. if you're writing in a compiler that flags warnings as errors, those are tests.
@daltonj507 Жыл бұрын
Totally would have missed the "if you can love at all" and now I can't stop laughing LOL
@leviathan7477 Жыл бұрын
I like to think of tests and requirements as two sides of a coin. Each requirement _has_ to have an associated test (even if that's just an ad hoc demonstration of functionality). For the most important requirements, you create regression tests that can be run before each release. If the requirement changes, you need to change the test. You try your hardest using other techniques to make the tests so they don't care about the implementation -- only the requirement. In that sense I like the idea of TDD because it acknowledges that all you need to write tests is the requirements, and if you write the implementation first your tests are more likely to be contrived nightmares that test things that don't matter. That being said, it is often impractical to fully write tests before you start the implementation, but I think it's always good to keep in mind that they need to tie back to the requirements.
@streettrialsandstuff Жыл бұрын
Your implementation is a requirement, isn't it? Otherwise you wouldn't have any implementation 🤔
@anasouardini Жыл бұрын
TDD is good, you just have to write your code first in a scratch pad so it doesn't count and then write your test and copy your code to it.
@vukkulvar9769 Жыл бұрын
Tests must be about the interface, how you use the thing, not the inner workings, how the thing works. If you change the interface, you change the tests, if the interface does not change, the tests must not need change. If they need to change, it means the tests were bad in the first place.
@anarchoyeasty3908 Жыл бұрын
That's right. Although the tests can also be added to when fixing a bug, it doesn't have to be a bad test.
@vukkulvar9769 Жыл бұрын
@@anarchoyeasty3908 There is a case where a bug could mean a missing test, but then you keep the test. But adding a test is not the same as changing a test.
@Kojikeneda Жыл бұрын
It would be really cool to see you and Dave debate this on either of your channels.
@tongobong1 Жыл бұрын
I would love to see ThePrime debate Dave on mockist style unit tests. Mockist style unit tests are the biggest nonsense ever invented and quite often used on many projects.
@Stefan-qk8sw Жыл бұрын
"I'm doing it right and every one else is stupid."
@davideastman5806 Жыл бұрын
I think the strongest argument for TDD is that it aligns with how other engineering disciplines will create simulations and tests that ensure correct design before they begin construction. Of course software has more flexibility post-construction than other fields, but it still seems to point to its usefulness in principle
@marcs9451 Жыл бұрын
Except it doesn't, you simulate post initial design and iterate over it. TDD expects you to already know the tests before you code, anyone who says otherwise probably never read Kent Beck's works (daddy of TDD)
@davideastman5806 Жыл бұрын
@@marcs9451 I don't believe TDD expects you to know all the tests before you code. From what I understand, you start with one failing test, get it to pass, then refactor. Then add another test, and so on.
@kuhluhOG Жыл бұрын
other engineering disciplines have one big advantage over software development though (normally at least): they know exactly what they need to design and their requirements don't change stupidly often
@davideastman5806 Жыл бұрын
@@kuhluhOG That's a good point. And our software often integrates with other software that also is changing a lot, so the interfaces are constantly changing.
@markmywords3817 Жыл бұрын
Arguments via analogy sometimes make intuitive sense, but often fall apart in areas where the analogy doesn't make sense.
@NickSteffen Жыл бұрын
Yea, I typically end up rewriting code right away two or three times within a few minutes. Not just the the parts that would be inside the black box either but large swaths. TDD does make the first iteration better, but that’s really just polishing a turd. It also increases the cost of the subsequent iterations to the point where they often don’t get done which takes far more quality out of your code.
@cheaterman49 Жыл бұрын
GODDD you're so right that it IS the Rust argument ; I've been making it myself for years without realizing. "it's a bit costly upfront, gonna be a bit slower in the beginning, gonna have to change the way you think about things, but it TRULY pays off in that writing correct programs means less time spent debugging/fixing them". Very astute observation!!! EDIT: I hadn't even reached the part about "less bad habits to unlearn", this is a priceless analogy for sure!
@raenastra Жыл бұрын
You could say this is an argument for anything difficult, but arguably worth learning. Same argument people make for vim, changing keyboard layouts, etc
@GonziHere Жыл бұрын
The argument is sound for Rust. It can be annoying but it helps you in the long run... by literally preventing these types of bugs to happen. TDD doesn't do that. TDD only PROMISES that when you use it, it will help you, with the caveat that if it won't, you are doing it wrong... I mean, you could easily argue, that RUST "unit tests" your code. It tests your inputs and outputs, it tests that you use all code paths, that you don't ignore errors and so on... but it does it for you. Automagically.
@tb15900 Жыл бұрын
I find you necessarily need to write some code up front when there’s areas that you don’t quite understand. I call it discovery. Then I move into more formal design. There’s a habit in Python of thinking that public/private methods don’t matter, but I find they make it very obvious what needs to be tested and what shouldn’t be. Once my interface is designed, I write tests - no, they won’t always be perfect first time, but stopping to think about them does help me write better code I think. The two major keys are only test interface, not implementation and avoid mocking entirely if you can. Ian Cooper did an absolutely fantastic talk on TDD and I’ve found since watching it that my tests are far better and are far less likely to break as I change things. If you purely test the interface, then nothing should break unless you break the interface. However it can be a battle getting other devs to not test certain things that they deem important and so when working on shared code you can end up really fighting the tests every time you change something
@adhillA979 ай бұрын
31:20 The thing about a TODO test is that you don't disable it, and it fails when you run the test suite. So then if you forget to get around to fixing it, you get a reminder every time you run the tests, and anyone else who runs your tests can see that it's unfinished (and maybe they will decide to fix it). Then if the code breaks, you have a very good idea of where to start looking for bugs.
@ClaudioBrogliato Жыл бұрын
Lately there's been a lot of criticisms about Uncle Bob's predicaments. TDD, Clean code... all being rediscussed. That is interesting because in my country Clean Code, Agile and the likes are hot. Looking what's happening here is like having a look at what things will be in here in two or three years. Sometimes even 5.
@AnthonyBullard Жыл бұрын
Clean code is one of Bobs weakest contributions, though SOLID is a useful framework for thinking about design even in functional programming. Hopefully in your country Agile won't be ruined by certifications and consultants that turn it into waterfall with more ceremony
@tongobong1 Жыл бұрын
Great videos! We live in a crazy world where critical thinking like this is rare. Never trust anyone or anything that only lists the pros without the cons. I believe TDD is good BUT only in some specific cases like when you know exactly the inputs and outputs to a rather complex function. In many cases where you don't know what exactly you want and so you are exploring the possibilities or when output is random or when building GUI in code or when applying a boilerplate code you shouldn't waste your time on a silly unit test because usually there is no benefit of having such a test and even less of writing it before the production code.
@LusidDreaming Жыл бұрын
Did anyone else reach a point where they started writing unit tests because it was less tedious than reading console output? That was 100% what got me into testing.
@thekwoka470710 ай бұрын
well, you could use the debugger...
@LusidDreaming10 ай бұрын
@@thekwoka4707 for some reason, C/C++ are the only languages I ever debug. Not that it makes sense at all, but for some reason it just seems easier to set up tests in other languages (whereas unit testing in C/C++ is more tedious in my experience). The nice thing about tests too is that they stick around, whereas a debugger session is one time only. So its nice to be able to run my tests again if I make another change as opposed to having to step through the code again.
@pdougall1 Жыл бұрын
"No matter what, you aren't good enough" future AI
@pierrejoye Жыл бұрын
just watching it, when he mentioned the Devonshire report, he refers to the DORA Devops report. As stats or data based on surveys are to be taken with some salt, it does bring some data to backup his claims. Also, I think it is not understood (the blue part). Or the "you can't write bug free code", that's not really the point. But doing late testing ends too often in the situation you described during this part of the video.
@antdok9573 Жыл бұрын
All this stuff about him talking about not being able to test an interface that has multiple responsibilities is sort of a symptom of how TDD is not being followed correctly. I don't like the subjectivity of his "take" on TDD. Doing TDD with code that already exists is a greater challenge, but it works out if done iteratively in small steps. Many things in TDD can be subjective, since the cycle itself is pretty vague (how much refactoring? is my next failing test a new feature or a demonstration of an existing bug? etc). That said, there are some pretty clear rules as far as unit testing and the such that help clear up that confusion anyway.
@TomWorks8 ай бұрын
"How do you know when you're ready to write code?". -> Exploratory test (inline code logic in the test itself). Once green you can refactor and at that stage you started writing code (extracting into classes etc).
@johnpekkala6941 Жыл бұрын
I have tried TDD once and just like I heard in a blog before about TDD, a really big irritation moment for me is the fact that when writing the test code first before the main code I then get no help at all from say intellisense but it instead throws a ton of errors at me cause I try to call undefined functions and variables that i have not yet written in the main code and that the test code is trying to access. You are more or less therefore all on your own writing the test part and all the error messages makes it confusing and imposible to really see if you have even written the test code correct when all u see is errors. For simpler tests it might work fine but for more complicated test It will cause issues for sure.
@antdok9573 Жыл бұрын
Part of successfully writing a failing unit test is having your code compile. Step 0 in a way. People shouldn't really write much code that doesn't compile. I think that's an IDE issue, I don't have this problem with Jetbrains IDEs. To me it sounds like you need to iterate even smaller than you thought, and do it painfully, until you kind of get a Eureka moment as far as figuring out the sweet spot of writing your next feature without doing too large of a step.
@johnpekkala6941 Жыл бұрын
@@antdok9573 I just might need to give it some more tries maybe. No expert yet in TDD. As said I only tried it once and as they described it in the blog more or less. I however also might be a bit spoiled with intellisensee in that even if I know how to write the code in my head it is still a confirm from the computer that my code is correct and that I am on the right track so when its not working as expected, like when I wrote the test back then, I get a bit put off. It might also just be an IDE / code editor thing as u said.
@antdok9573 Жыл бұрын
@@johnpekkala6941 I rely on my PyCharm intellisense to suggest implementing missing functions/classes if they're not implemented in my unit tests. It will also just flat-out implement nulls/temporary values so that tests fail successfully. Yeah, up to you if you want to try TDD. I'm no expert, either, but I have reaped its benefits already. I don't have much experience implementing it in an existing codebase in an efficient manner quite yet. That's most certainly pro-level stuff if you want to become very quick/experienced at it.
@ToadalChaos Жыл бұрын
I agree that tests should be as large as possible, to decouple them from the implementation details. But the flipside is that when I'm building up a complex system, I need to be able to verify that each component is working correctly. If I only have one end-to-end test and it fails, how am I supposed to know which of the 30 functions involved is causing the error? Personally I struggle to see any way to build up a conplex system other than breaking it down into components and building each component one at a time, checking my work at each step. And to check my work I... Test it. So honestly I find myself doing TDD either way. The only difference is whether I keep the tests around or whether I chuck them out. But a lot of the time I prefer to eekp them around. Perhaps refactor them to be more abstract and generic. And yes, when I change a low-level interface, that may break a lot of tests. But then again I need to test the new implementation anyway, so as to make sure it has all the behaviours I expect it to. So I may as well do so by fixing the broken tests?
@jfftck Жыл бұрын
I was on a team that had gotten Agile development to work, but it isn’t enough for the team to go through the process, they have to believe in it. That is why I have only had one team that made it work, all other teams didn’t make the effort to dedicate time to the process. The biggest mistake has been the extremely groomed backlog and having a ratio of technical debt stories to feature stories, without that as a base, it is impossible for it to succeed. On this team the whole team was required to join the refinement meeting and we needed everyone understand the ask, even the QA team, and give their story points with justifications for why it would take that time. So, if you have a team doing this process very well, TDD won’t be as hard. My experience is poor user stories cause more rework than not following TDD. I have to deal with missed requirements all the time, because people using the system doesn’t know how to look for edge cases until the work had already started.
Жыл бұрын
“The team has to believe in the process” confront that to the part of the agile manifesto that says “Individuals and interactions over processes and tools”. There is a big misunderstanding in there somewhere.
@jfftck Жыл бұрын
@ What I am trying to say is, the process has to feel natural and not clinical. When done correctly, it feels like an extension to writing code and not checkboxes that must be completed to release. If you don’t feel that it’s guiding your work then you need to bring it up with the team for discussion, maybe you tweak your team’s process until it feels right. The fact remains that all teams have a process to follow, the goal is to make the least abrasive process.
@porky1118 Жыл бұрын
40:52 When I write a Rust library, I sometimes write test for the API, but only when I realize it doesn't work properly, or when I write documentation, so I decide to write documentation tests.
@BenVisness Жыл бұрын
I love that he claims this applies to game dev. “Instead of iterating on the design of your game, you should just design the entire game up front, write an test suite describing the entire game, and then the rest is just an implementation detail.” TDD = waterfall, change my mind
@TCH534 Жыл бұрын
In TDD you don’t write ALL your tests to front in a test suite. You only write one.
@anarchoyeasty3908 Жыл бұрын
This is the perfect comment that sums up how I feel about primes audience, even though I am a member of it. So many people on the chat go off confidently about things they are extremely wrong about. TDD is a tight loop. You write A test, you implement the test, you write the next test. It is a mindshift change where before you implement the functionality, you think first about what the outcome is. So if I am writing functionality where a move_unit command when given a new position and a entity, instead of jumping in immediately and implementing it I first think about what the desired outcome of this command is. For the sake of simplicity let's assume that this is a teleport/grid style move instead of a smooth one with physics, but you can do this with more complex logic too. Without knowing every little detail about how this will eventually work, what's one thing I can confidently say should happen. The position of the entity should be updated to the new position. Great, that's a test. In my test suite I create a new unit test and name it whatever. I prefer verbosity so that it acts as documentation when read. MoveUnit_Should_Update_A_Entities_Position. In that test I create a entity, I perform a move_unit command, and I check and verify that the position of the entity was updated. It fails. Because you haven't written that logic yet. Then you go into your game code and you implement that little amount of logic. Now your test passes. Great, now we continue and decide that entity's should have a range that they can move in. Let's call it 3 tiles. Let's go back to the test we wrote, and update it to reflect the new development. Rename the title to MoveUnit_Should_Update_A_Entities_Position_Within_Range and make sure the new position you passed in is within 3 tiles. You haven't changed your code so it should still pass. You are simply updating the conditions to reflect the new intent. Let's think about what we want to do about what to do if it is outside of the range. For the sake of simplicity again lets assume we do not perform the move and instead return an error. But you can do this process with any complexity of logic. So let's name our test MoveUnit_Should_Return_OutOfRange_Error_When_Given_Position_Too_Far (again you can name things however you / your team likes. This is just how I like to write them because when I read the titles of my tests it describes perfectly the desired functionality of the code. It serves as documentation). In the test I create an entity, I provide a new position that is outside of the range, and verify that it returns the error. It fails. Because we haven't developed that code yet. Hop into code, add your invariant check and say if the range is too far, return the error. Now your test passes. Does the first test still pass? Great! You have confidence that your refactor did not break anything that you had written before. Does the first test fail? Great! Now you know before you ship it / get further in development. You can continue this process the entire process of programming a game. It is a slow process at first, breaking your usual flow of development. But it took me 3 days of doing this in my work to get in the flow of doing it. As you are developing you will come up with new requirements that break assumptions you made earlier in your tests. That's fine, your tests are not concrete they are a reflection of your intent. So go in, change the tests to reflect your new intent, then update your code and verify that the changes all pass. You don't need to update your tests when you change an entities range while tweaking the data files for your game. But when your underlying systems need to change (or be developed) you definitely can (and I believe should) do TDD
@antdok9573 Жыл бұрын
It's unit testing. You test a unit, not the whole game. Implement the behavior in an iterative way, and you likely will get an excellent design. You're right in that design upfront is not what you want and is one of the things TDD allows you to avoid. While TDD might not naturally have a test suite for some aspects of the game that deal with hardware input/output, you can focus instead on testing the design you make in the programming language you program in. For graphics and the such, if there's a specific behavior you're testing for, you'd have to have sympathy with the lower-level components that the code might work with in order to understand how to test it. This really doesn't apply to a lot of game developers, so there's likely much less coverage on how to handle tests for such scenarios. It is a great indicator of buggy code when you do not know how to create tests for it, i.e. the code is not easily testable.
@simitron1 Жыл бұрын
you do not write all tests up front you just write one interaction further in tests than you are in code, so you would normally just make sure your layers for example physics work independent of your player logic with unit tests so you can safely layer on top.
@antdok9573 Жыл бұрын
@@simitron1 That's a great example of TDD. That kind of abstraction can come naturally in TDD by separating your components like that nicely :)
@bbsara014610 ай бұрын
i feel like a lot of his arguments shame people by basically saying "oh you don't like TDD? I guess you suck at your job then"
@yuriy53764 ай бұрын
Yeah, just your average toxic gaslighting tech evangelist
@willemvdk4886 Жыл бұрын
I love the workflow of writing a test first, then the implementation. It forces you to think about the requirements of the unit you're writing, making implementing it easier, usually. Also, if you trust the fact that you wrote a good test, then it's also fairly easy to know when you're done. What I really DON'T like about TDD when you take it really literally is the fact that you're supposed to write just enough code to make you test(s) pass. And if you KNOW that, for instance, just returning "true" is not going to cut it, then you're supposed to write another test and then make that one pass again. It's extremely tedious and way too many iterations. It's dumb. It's stupid. I just write a few tests beforehand, checking the happy flow and some boundary cases or errors and then implement it in one go untill all tests pass and then I move on. Way better IMHO.
@thekwoka470710 ай бұрын
I think one of the issues with the "write test first" thing is that you will learn a lot about what it needs to do, when you try to do it...
@jiggasnap Жыл бұрын
So ironic to hear Dave Farley complain about people saying “it doesn’t work.” He does the same thing; he very often says “it doesn’t work” about stuff that real world companies use ubiquitously
@oumardicko5593 Жыл бұрын
The problem is not writing test but how you write it, i am working on a big java project right now and running a test take at least 2 min on my computer (yup). So running a test 30 times ,booms, 1 hour gone. I love writing tests, but i just wanna get the job done and i have zero patience for this BS.
@Notoriousjunior374 Жыл бұрын
Absolute bs
@oumardicko5593 Жыл бұрын
@@Notoriousjunior374 ?
@Notoriousjunior374 Жыл бұрын
@@oumardicko5593 tdd is absolute bs
@zaris959810 ай бұрын
Imho the confusion around 6:30 "don't like blue refactor part because of architectural changes"/ "have to change tests because requirements changes" is caused by the thought that TDD should be used from the start. In a recent talk on youtube it was suggested to make the architecture first (top down) and use TDD in the implementation (bottom up) parts after that and i think that's sounds better. For example a small calculator with addition, mail validator, quicksort, a data mapper or bigger algorithm like the simplex is pretty clear in its requirements and size and don't need "architectural refactoring" and only maybe renaming, method extraciton and so on. The blue refactor part is also very depending on the knowledge of the programmer. If you code down a problem with loops / if statements (for most people easier to understand) and after passing the green you recognize it could be done in a map / filter stream in a better / shorter way you rewrite it in a few minutes or even simpler replace a convoluted 5-7 lines IF ELSe with a 1 line ?: operator.
@himmelkami3308 Жыл бұрын
the thing of TDD is that it is not a golden rule. It is like writing books or novels, there are maybe some greatest authors tell you that you can first make the outline and all the plot-line to make your work easy or greater. But there are always different ways to for a novel to be great. So TDD is always a method, but should not be considered to be a rule for programming.
@pieflies Жыл бұрын
Pretty much anything you make into an unbreakable golden rule will become a pain in the ass.
@jacmkno501911 ай бұрын
The real problem with TDD for me is that I don't know what I want to do before I start looking at a prototype of it so it's more like a prototype driven development. The problem here is he wants you to go and really think in the architecture of the thing before you build it. But I find impossible with so many moving parts and alternatives on today's production environments. Makes mucho more sense to build small prototypes and iterate over them.
@htomar_dev Жыл бұрын
tomato driven development
@Caboose2563 Жыл бұрын
🍅
@antdok9573 Жыл бұрын
Mr. Pomodoro would like to have a word with you.
@georged8644 Жыл бұрын
I literally burst out laughing when said "TDD is used to develop some of the best software in the world" followed by showing a picture of a Tesla Bugmobile!!
@yannick5099 Жыл бұрын
The only time I do some kind of TDD is when a problem is very well specified in advance, something like writing/porting a data structure or hash function. Other than that I find it slows everything down, especially at the start of a project where many things are not even decided/specified yet or the customers change their mind very often.
@ryshask Жыл бұрын
That's not really TDD if the code already exists in some form... That's just a test harness to ensure your new code behaves like the old. Your assessment regarding new projects is 100% accurate.
@cabanford7 ай бұрын
SNL: What is Love. Don't hurt me know more.
@bike4aday Жыл бұрын
I think the only way to get TDD to work is to sandwich vertical slice architecture between two fat layers whos interfaces never change and then your units start and end with the top and bottom layers. This way the fat layers will be rigid as not to require changes to our tests during refactoring, but the middle layers will be flexible to change so we can make them as simple or complex as necessary to accomplish the goal. The problem again is that the fat layers need to be perfectly designed and unchanging, so if it's not a type of application you've made before, then you likely will not know what those interfaces will be, thus the problem returns. EDIT: Yes this is more similar to BDD or integration tests, as Prime said, and yes the entire IO layer will need to be faked/dummied/mocked, so it'll probably be a third fat layer layer that is tested outside of TDD. This means that if all your program does is take some input and save it to a file then your unit test basically tests nothing because there's no business or domain logic in the middle. It would just be a bread sandwich, no BLT.
@antdok9573 Жыл бұрын
I think the only way to get TDD working is to think of TDD as a "design by test first." Otherwise, yeah, you do end up in a vicious cycle. There's tons more to TDD than just that, but at its core, Dave wants us to think about developing behaviors (less so testing individual functions, as Primagen states) for our code based on the tests we're creating. I re-call him wanting to rename it to Test Driven Design. It's ok to break out of the cycle of TDD to do exploratory code when you actually have zero clue of how to write the unit test as he mentions at 6:00.
@elyeserr.4002 Жыл бұрын
Pk😢re 0:22 o ko😊 0:22 u
@elyeserr.4002 Жыл бұрын
Pk😢re 0:22 o ko😊 0:22 u u😮 0:22 ih😮 0:22
@elyeserr.4002 Жыл бұрын
0:22
@niuniuch Жыл бұрын
BDD started as an idea on how to teach people to do TDD properly. Only after some time it got overrun by tools and technologies, as most good ideas in SE do.
@user-sw1wq8lh2w Жыл бұрын
22:00 You're soooooooooo right. I worked on the vanilla JS front end for a malicious USB implant device (O.MG Cable), I tried for a long time to speed up my dev process by creating automated tests for packet responses from our server over a websocket. It was working pretty good, but in the end was an entire nightmare. I'd mocked out the responses from the embeded C code in a simple node server that mocked the cable over the websocket. It got out of sync rapidly and we had massive amounts of false positives once the embedded C had been changed and my mock server was based on absolutely nothing. It helped me rapidly prototype some stuff and get some work done, but we HAD to test across the cable manually to test, there was just no other way. We even looked into using raspberry pi to automate flashing the firmware and simulating a hardware connection and disconnection of a physical USB, including an actual physical disconnect. This was just nearly impossible to actually build using TDD.
@toopkarcher Жыл бұрын
A point of praise for TDD is making things more testable because it'll naturally make you write more functions/more classes so that you can test it. But imo you've sort of just forced yourself to break up something which was naturally 1 unit into a bunch of non-reusable puzzle pieces
@username7763 Жыл бұрын
Yes, very true. While poorly designed code is often hard to test. Just because code is designed to be testable doesn't make it well designed. Often time designing for a test makes it harder to understand and more complex.
@toopkarcher Жыл бұрын
@@username7763 and then there are a shit ton of depencies everywhere are the set up for tests are a nightmare. Here comes mocking....
@sorcdk2880 Жыл бұрын
I would argue that imposing the requirement that things must be very testable actually makes it more likely that the code becomes poorly designed. While a lot of good designs happen to be very testable, counting those are actually a bit of a moot point, because the programmer who was capable of finding those good designs would usually have used them regardless of that requirement, for the simple reason that they are good in the first place, so imposing the requirement of high testability does not actually change much in terms of more use of those good designs (aside from serving as one of the reasons why those designs are good in the first place). What we instead get are those cases that have varying degree of how well designed they are, which then gets imposed an additional requirement on how the design should be. Since such things, especially those of less than great designs, makes it harder to solve the same problem because of the complexity from how to handle the new requirement, and as a rule of thumb design quality is inversely proportional to how much over their heads the designer is, and more complexity can certainly cause this. It should be noted that sometimes the most appropriate thing is not to do classical automated testing for something, but instead something else. This is especially important when the main source of failure is conflicts with forreign interfaces, which classical automated testing would often need to mock out. An example of this would be testing interaction with persistent systems that you do not want to damage, though some of these can be handled with special testing enviroments, but these enviroments are often way too heavy for the kind of automated testing needed for TDD. That also brings us to another point, which is that while it technically possible to test a lot of weird things like those mentioned in a video game, those things often require a lot of skill and effort to set such tests up for, often far in excess of their value, and TDD is definitely not enough of a miracle that it is worth doing at any cost.
@FinnGamble Жыл бұрын
With TDD, you are supposed to test at a pretty high level. If you find that TDD requires you to change how you structure your implementation, you are probably testing too low. (Yes, many tutorials get this wrong, too!)
@AK-vx4dy Жыл бұрын
@45:57 Not 100% coverage. Loop will be desugared to if and you don't visit the path when body is not entered ;) If you done TDD you write your first test and wonder what are predconditions for function with such signature to work properly and add test with parameters braking this preconditions. Also you would thnik what colud hapen in this case then: exception or coerce to table length.
@schizomaru Жыл бұрын
In my experience, yeah, TDD sometimes fails and you need to throw everything out, but, those times are exceptions, not the rule. I think it is not fair to take a exception that not work, to say "this not work". I agree with "you haven´t done enough". Yeah, sometimes you right code just to see what happen and thats fine, but, once you figure it out, now you should know what you need to do, there for, you know what test you should create. I will say, sometimes I hate doing TDD, but saying "i hate doing this" and "this do not work" are not the same thing.
@animanaut Жыл бұрын
thunderdome driven development == two arguments go in, one result comes out. make the result optional if both arguments perform a doublekill
@antdok9573 Жыл бұрын
Martin Fowler has written about the saying, "If it hurts, do it more often" as it pertains to activities like deployments and integration. The same applies to TDD.
@NathanHedglin Жыл бұрын
TDD doesn't fix many of the issues that people say it does though. Code coverage is a worthless metric.
@antdok9573 Жыл бұрын
@@NathanHedglin Code coverage is not TDD.
@godeketime Жыл бұрын
Having worked on systems in "hard requirements" engineering, TDD works very well. After all, the laws of physics don't change on Tuesday. However, prototyping business systems and doing rapid delivery is antithetical to TDD approaches. I *have* had the entire business change focus on Tuesdays. Tests are great, when you build them depends on the level of chaos the requirements are in.
@michaelslattery3050 Жыл бұрын
TDD works if you just test the highest level API. Often that means writing a test for a service or controller only. Somehow everyone got the idea that good TDD is about testing every function. It's the opposite. You just translate the high level use case (e.g. delete a record) into a test, and that's the only test you need to write. You don't need to write tests all the way down the stack. As a side note, IMO a unit is a unit of functionality.
@anarchoyeasty3908 Жыл бұрын
It sounds like you are describing the highest level API as in what the consumer uses. And that is not at all when TDD works best. TDD serves as documentations of intent of your code. If your code has a class that has logic in it, it should be tested as part of TDD. You only need to test and document the public functions. How the code get's there (the implementation and private functions) is it's own business. But your TDD tests should cover the public api of the class. When Method A is given parameters B and C result D should occur. Or Error F should be thrown. That way when something breaks because of a change in the code either in this function or in a function that this function relies on your tests will fail exactly where the error occurs and you can fix it.
@rallokkcaz Жыл бұрын
That's integration tests, a unit is a single piece of functionality. With a web app and CRUD, there's tons of layers between the request and the database getting a record entered into it or removed.
@antdok9573 Жыл бұрын
A unit of behavior. A unit test is still small generally though, so you probably don't want to go up to the API level. That's integration testing. Hardware input/output shouldn't really happen in many of these test cases.
@CYXXYC Жыл бұрын
I try to write declarative code as much as possible, and logic (aka spaghetti) as little as possible, because then compile time checks like type systems and such don't let me compile wrong code. The code turns out very testable, but often the tests would just replicate 1:1 the resulting declarative code in some shape or another, which is not very useful, because at that point you can just look at the code to confirm that it is correct, without tests. If you write declarative code, your code turns into these bricks, that you can replace, reorder (in some cases), move out into functions or own libs (makes it easier to open source), they are easier to read, to write, to edit (I often come back to my old spaghetti logic and can barely understand it, I often come back to my declarative code and can pretty much continue where I left off). Builder/Stream (Iterator) APIs, patterns/algebraic types, aggregation (components in many frameworks, Leptos' , etc), sending messages (reducers, channels, etc) are all your friends. The fact that most loops can be replaced by streams also makes me think that they are pretty much declarative in their own right, just written slightly differently. When you do your types, give them more meaning, make their meaning be your logic - instead of checking for nulls, numbers in ranges, etc. make your functions accept only correct inputs already. In the same fashion, the most correct return type would also limit possibility of wrong outputs (since function logic has to match output type), as well as make sure units glue together better. Often your logic that was like `assert check_a(value); assert check_b(value); ...do_something_to_value(value)...` would turn into `A a = a(value); B b = b(a); ...do_something_to_b(b)...`. As an example, function that outputs Days and function that takes in Seconds would need a conversion in between them; function that outputs u64 and function that takes in u64 are prone to rather silly mistakes. Bonus example, currently on implicit-clone crate of yew stack, I was thinking whether we should be adding methods like `.push(item)` to our immutable arrays that would clone before adding an item. Some sort of result type that tells user that the array has been cloned and they should consider the ramifications (mainly performance) of that seems reasonable. Rust API does this with `[T].repeat(n)`, which returns `Vec` rather than another `[T]`.
@user-qr4jf4tv2x Жыл бұрын
this video is cut i guess prime is still ranting to this day.
@ThePrimeTimeagen Жыл бұрын
legend goes he is still ranting as we speak
@SArthur221 Жыл бұрын
12:19 Yes. Literally. In this scenario, the borrow checker is an implicit test. You can use unwrap() to get it green, and then refactor it out in the blue phase.
@botbeamer Жыл бұрын
I need to write a TDD framework for my TDD framework
@jimigrunge Жыл бұрын
I do TDD at my current job only because it's required. That being said, one time I do find it very useful is when I'm fixing a bug. Write a test to replicate the bug and then fix the code to make it work properly. This ensures that the bug will not return if someone later on chages something that would reintroduce the bug. My butt is covered "Hey if already fixed it and here is the test in the git history"
@ReneHartmann Жыл бұрын
One problem with TDD is that during refactoring, you may want to change the interface too because, well, you came up with a better interface. But this means you have to rewrite all your tests. This is not only expensive, but it also means that you may introduce a bug into your tests, which means your tests don't provide the sort of 'safety net' during refactoring TDD promises to provide.
@alanonym8972 Жыл бұрын
I mean, at the moment where you are refactoring you are risking to introduce some bugs. And yet you want to be able to refactor because your code is bound to be tech debt a few years from now. And the less you have to change the test for that refactoring, the better. For a specific piece of code, the further you are testing, the less likely you are to have change the test while refactoring, because it won't be bound to implementation. The only way to have change-free tests, is to not write them in the first place
@liquidcode1704 Жыл бұрын
what is testing...baby dont code me, dont code me... no morreee
@CRBarchager Жыл бұрын
16:30 This is one thing that sets seniors apart from juniors. Knowing what kind of errors can happenn and writing code to defend against that. You will not write code defending agaist a null if you don't know that a value can end with having a null value. When you know this is the case you code habbits while chance accordingly. Simply experience with developing will make this happen with time. You can read about it and watch videos about it but untill you get to try it and experience the errors you will not know how to fix them.
@doublepipe. Жыл бұрын
Haven't watched yet; answer is clearly "yes"
@kevinfleischer20499 ай бұрын
24:20: You go step by step. You figure out whats the most basic case and code that. than you go to the next more interesting case and implement that. it is not forbidden to do some research in the code or Db or whatever you want to integrate to get an idea what to do next. Kent Beck writes about this in his book Test Driven Development: By Example.
@MartynPS Жыл бұрын
I think Dave's definition of a unit test scales a lot more than Primes... Tests for CRUD are just as valid as tests on functions. I think the only rule is that the tests should be small, so you would me more likely to use stubs rather than real services where services reach out elsewhere.
@sanjayidpuganti Жыл бұрын
Why the hell do you Unit test CRUD ?
@MartynPS Жыл бұрын
@@sanjayidpuganti I have a published interface spec and don't want to have to spin up an entire test environment to test my implementation. Each endpoint is small and simple to test - so why not... Integration tests would probably need artificial inputs to touch all code paths right now.
@Surefire99 Жыл бұрын
His argument ignores the fact that sometimes the goal is very well defined loosely, but there are no limits on the specifics. For example, when cleaning user data. The goal is to strip out any malicious code, but there is no limit on what that input could look like. So no matter how many tests you write, the coverage still approaches 0%.
@livioribeiro Жыл бұрын
I am surprised this guy didn't say we should write tests before speaking to the client
@craigyoung800810 ай бұрын
42:07 if your mocks are in any way being tested, or if there’s anything “testable” about your mocks, then they’re *NOT* mocks. A true mock simply returns predetermined values as and when desired for the purpose of your test. Changes to your mocks should be approximately equivalent to changing the constants in your test function that are being passed into your code under test. If you find yourself doing large amounts of “fixing mocks” as a result of a change, then some likely mistakes you’ve made include: - mocks doing too much work - refactoring includes interface changes (resulting in simultaneous changes up&down stream of the interface change) - original interface likely reflects implementation details and would have benefited from thinking about how to use/call it *before* considering implementation (I.e. correct TDD) - excessive tests An important thing to remember is that whenever you change an interface, doing so carefully and thoroughly is *always* going to be a lot more work than changes that don’t impact an interface. This is irrespective of whether you also have a lot of tests using that interface. So yes, all your test failures that crop up as a result of the change highlight a significant amount of work required. But surely that’s better than only addressing a portion of the places impacted by your change, and releasing with a large number of new latent defects that could have been avoided?
@sacredgeometry Жыл бұрын
If it improved code quality I would be happy to do it. Everywhere I have worked where TDD is the norm has had some of the worst code quality I have ever seen. One companies was so bad I chose to quit rather than stay and have to sort it out. TDD is in practice just a heuristic or andragogical approach. It is training wheels for people that struggle to think in code and for anyone with even a modicum of an acumen the benefits are non existent and the detriments are ubiquitous.
@cabanford7 ай бұрын
"A wicked Problem" - is a problem you have to solve, before you can solve it. Software in a nutshell.
@SiasMey Жыл бұрын
I think you nailed it at the start Prime. If your units are tiny, the value is negligible. Tdd seems to work best when you approach it like mocked integration tests. Test everything through the stack, from fake input, to fake output. Then you can refactor to hell in the middle without affecting your public api. If you apply it to the level of a single function you couple tests to too small of a unit, which means refactoring screws up the tests. You actually write most of your shell scripts this way, give it input, run it, check the output. But there are also certainly places where tdd does not make sense. Lots of small abstraction packages just don't make sense to develop using tdd.
@robertluong3024 Жыл бұрын
Thank you! I thought unit tests were just that they didn't cross a port. Unit tests that are too tight are bad TDD to me. It's why BDD came about. To be fair though, I am not a fan of TDD.
@Tkdestroyer1 Жыл бұрын
@@robertluong3024 I feel like I'm not really understanding something. How can you have a test that's too tight? Or are you testing private methods?
@SiasMey Жыл бұрын
@@Tkdestroyer1At a single function level you it's very difficult to differentiate between implementation and behaviour. Too tight basically means the code under test is so simple that it only had a single behaviour, and if you want to move that behaviour, you have to update the test. Think unit testing a class, then deciding that class needs to be split into two, now all the tests and setup and teardown needs to be updated. If you instead target your tests at the public api of your system, you can split and recombine the individual classes underneath as much as you want and nothing needs to change. Integration tests is a terrible name, cause to some people it means spin up the dB and the Internet and test for real, and to others it means test the integration between the internal modules but still isolated from io dependencies. That second one is the golden path for Tdd.
@truffaldiino4951 Жыл бұрын
It is fun to see how so many programmers have taken "unit" to mean "function" or "class" when in its originality it means rather a "funtional unit of the application" and in the terms of viewing your application as a black box that "functional unit" actually equates to "functional requirement" and therefore is equivalent to a end-to-end integration test. The interface is the functional requirement that is derived from analysis and therefore the underlying implementation can change however much as necessary and the test will remain stable unless the actual functional requirement of the application changes. That change may be due to later on clarifying with more detail what the original requirement was suppose to be or it may be removed/replaced entirely during product life when that requirement no longer serves a purpose. I urge programmers to try and use "unit" in terms of "functional requirement" when talking about TDD as this helps understand the concept better. If you really want to drive the tests down till actual single functions/classes then you can do that as well but you have to realize then that the "black box" you are testing the "functional requirements" for is that class/function and when that class/function no longer is required by it's caller those tests are no longer useful in the wider scope of the application. Similarly as the end-to-end tests would not be meaningful when the application is deprecated/discarded. In terms of developing you start from the outside in in terms of TDD. First tests for the application as a black box. Then during refactoring of your code you will have a better understanding of how you want to organize the internals of the application (which at that point already works since the outermost tests are green and thus refactoring is easier since you have guide rails to indicate when something broke) and thus you can start defining the "functional requirements" of some internal components and write tests for those and refactor the code to move those implementations into those modules/components. With every level of depth you increase the chance that that implementation will become deprecated and those tests will therefore get discarded. Do with that assumption what you will.
@manawardhana Жыл бұрын
My main problem with TDD is, it doesn't respect the cognitive process of complex problem-solving. My development flow is, I make it work, then I improve the quality. And I never get the idea OOP and TDD can live in harmony. In the OOP world, it is ridiculous how people have gone far to make it is working (take the implementation and API of Mockito as an example). So you better familiarize yourself know the difference between Mock, Stub, Fake, and Spy before the next interview? And if you are familiar, you spend your cognitive energy in a paradox of choice situation wondering what to use? In FP, you can unit tests just with the core language (libs could be nicer though). I don't know how anyone justifies the high amount of investment (time, effort) to the little benefits TDD brings. I'm not against applying TDD for the correct situation. In some situations, that's the best way forward. But TDD camp doesn't tell that. The say if you are not doing it all the time, you are a "cheater". Great job @ThePrimeTime on reacting to the video. Some of your points are gold!
@antdok9573 Жыл бұрын
Eventually, TDD has almost no overhead. This has been the case for me in my code base. This took me about one to two weeks or so and mostly involved me exploring what the hell I was supposed to be doing in the code in the first place. Once I actually figured out what I wanted to do, the TDD cycle now takes me 15m-2hrs, depending on the feature, and it remains that way as I sparingly re-visit the code from time to time to make new changes. Most of the time I wasted in that 1-2 week period was not because I was re-writing tests, but because my understanding of how I was working with some frontend/backend technologies had changed entirely. Regarding your question about the different testing terminology, as far as I know, generally, you should do something other than mock things out. That is a last resort, in my view. Most of all create a working interface. You know, perhaps if I've explained myself enough, in a way that you can run your unit tests with the fake sort of objects that are simulated in-memory and that same test would work when you use the actual implementation that uses a database/internet instead of something in-memory. At that point you're testing an interface and that's going to be a lot of test coverage and quicker dev time. That's a big reason why I enjoy Python's duck-typing and TDD.
@rban123 Жыл бұрын
This entire video is just him saying “it works, trust me. You’re wrong!!” Over and over lol
@heater5979 Жыл бұрын
I reason about it like this: 1) You can't write code until you have a complete, rigorous and unambiguous Detailed Design Specification (DDS). That is detail down to the "unit", define it as you will, function, module, class, Down to the API, function parameters etc. Whatever. 2) You can't write tests until you have a complete, rigorous and unambiguous DDS. As above. 3) It follows then that it does not matter if you write the tests first or the code. Because they both derive from the same document. At the end of the day they have to match up but they do not depend on each other. 4) Tests should be written by different people that those who write the code. Thus greatly reducing the chance that bake in the same misunderstandings of the requirements/design. 5) For extra reliability tests and code should be reviewed against the DDS by yet other different people. Someone please tell me if and where the above logic is faulty. That is how things were done back in the day when spent far too many years on test teams for Boing 777 flight controls and such things. Now, I can well imagine that in the modern world many do not have that rigorous DDS document. What with being all "agile" instead of "waterfall". Seems to me then that the tests in TDD are bing hoisted to the front of development as a replacement for that DDS document. Well, if you want to churn out buggy code that is the way to go I guess :) It also seems to be that a lot of development forgoes the DDS and goes straight into code. Exploration is done. You don't know what you want until you have done it. Things may change along the way, functions, parameters, API's, protocols, whatever. It's right when it is right. Demanding tests be done upfront and then having to constantly change them to keep up with the exploration is just a daft waste of effort. Having said all that, I would have more sympathy for TDD if it was ever said that the people writing the tests should should be other than those writing the code. Satisfying 5) above in the absence of a design spec. God I hate all these self proclaimed software gurus who constantly advise us how to work, and then say "You were doing it wrong" when everything goes to shit.
@ja31ya Жыл бұрын
If I ever have the privilege of working on a team, I will be taking all of this to heart. That being said, for my larger projects I do write up a pseudo-DDS which does greatly speed up my development.
@heater5979 Жыл бұрын
@@ja31ya I wish you well on your journey . Working with teams can be a joyful and educational experience. When the team comprises people of like mind and know what they are doing and have a passion for the project. It can also be miserable. When nobody is enthusiastic, only in it for the money, communications is terrible and it's not possible to trust everyone is on the same page.
@rommellagera854310 ай бұрын
Software gurus who no longer write code tells you how to write code True you need a viable design before starting work, since I work alone my design is informal but takes a lot of time before any meaningful work begins, it seems I am a dumb person because I spend a lot of time thinking about the design, even in the middle of the project when I see major flaws in the design, I stop dev effort and concentratre in design again I don't know how Agile address the need for viable design and importantly stop when the design is flawed, adjust the design and throw away some sprints in the process
@craigyoung800810 ай бұрын
23:32 here I take a slightly different approach to Dave. Rather than considering “what I’d like my code to do”, I prefer to focus on “how I want to use my code”. That’s the bedrock of the test cases. And far less likely to change if you’ve imagined a simple enough interface. Whereas thinking about what it’s supposed to do can inadvertently lead to considering implementation details in a way that corrupts the simplicity of the interface.
@noext7001 Жыл бұрын
16:31 that the biggest argument against tdd, you can have a 100% coverage project and still encounter bugs
@mbunkus Жыл бұрын
No, that's just wrong. No one claims their favorite development method achieves bug-free code. We all know that's impossible, including the people advocating for whatever development/test method. The goals are usually to reduce the number of bugs, or to make code easier to maintain in the long run & similar claims.
@anlumo1 Жыл бұрын
I've yet to see anybody explaining how TDD is supposed to work for UI development. Am I supposed to compare the image output to Figma screenshots?
@GoddamnAxl Жыл бұрын
I feel like TDD might be useful for those heavily spec’d technologies. Or in a sense you can call TDD spec driven development. I think some mature blockchains such as ethereum can benefit from TDD as the specs are always heavily thought through, and won’t change easily.
@alanonym8972 Жыл бұрын
Dave on his channel uses a term often: "behavior driven development". I don't think most software change easily their specifications (once the core of the system works). Yes, you add features, but the core of the systems rarely change radically to the user's viewpoint. And if you do your tests in a TDD way, then the tests will be much easier to re-do once the specifications change, because it was made to favorize tests creation in the first place
@nickwitha_k Жыл бұрын
Eh. As I've mentioned on another video, I find myself using my interpretation of TDD a lot in Go. I think of a unit test like a TODO and consider tests disposable and try to keep them as terse as possible. Where it helps me is making sure that I am taking smaller bites, have an easier time debugging, and when taking the wrong approach, generally I'm able to bail out and start over sooner. When I don't write tests as I'm going, I frequently find debug to take far, far longer. Do I still write bugs? Oh yeah. Generally, however, it makes them easier to locate. Also, I'm but 100% strict - sometimes it really makes more sense to test after.
@max_ishere Жыл бұрын
I dunno about you but I feel so much easier with tdd. All I have to do is add a test see it pass and request a review.
@cheaterman49 Жыл бұрын
I really like TDD, but I only write integration tests ; I feel like there's largely no point testing internals of how your machine works if it's not observable by the user, so I test the borders - eg just pretend to make a request, observe side effects ; 75% of it is "did I get the right error" and the remaining 25% is the happy path (more or less) - was a record inserted into DB that corresponds to the payload, was email sent, etc (obviously the email sender is setup in a way that it doesn't actually hit network, and the DB stuff occurs inside nested transactions I rollback after each test). If some unit is indeed too complex for me to design/test by hand, I'll use tests to guide the implementation, mostly checking common pitfalls etc to help whoever has to refactor it later avoid making the same mistakes, but not otherwise making the implementation details exceedingly static. You mentioned in another video that you'll often delete those tests afterwards, but I personally feel like it might be disservice to the next person in line (including future self).
@ANONAAAAAAAAA Жыл бұрын
You can use unit tests for testing business logics. Yes, you can use integration tests for the same purpose but integration tests are more costly to setup. >75% of it is "did I get the right error" I personally prefer to do this in unit tests and integration tests are only for very common scenarios.
@cheaterman49 Жыл бұрын
@@ANONAAAAAAAAA While I guess that's totally fair, one thing my setup allows me to do is 1°) test DB migrations at all and 2°) test them against the staging setup which is fairly close to guaranteeing their viability in production. If you're gonna check for errors anyway, why not also cover the way these errors are reported to the user at the same time? IMHO it actually takes less time ; sure an integration test harness might take a bit longer to write initially but you're truly exercising your whole system at once and can be reasonably sure to not break anything. What I will grant you however, is that once things do break, having unit tests for complex parts of the code is useful (and might even be essential in bigger systems) to be quickly able to pinpoint where/how things failed.
@ANONAAAAAAAAA Жыл бұрын
If you are making yourself do TDD, something is wrong. TDD is just one of the ways of writing codes you naturally do in some situations. More specifically, I write tests codes first when the codes I want to write are clear and obvious while tests codes are not. In such cases, I write tests codes first to consolidate the strategy of how to test the codes.
@StrengthOfADragon138 ай бұрын
I'm curious what the primeagens take on the studies that show TDD to be more efficient over time is. I appreciate the clarification that it assumes your tests are less likely to be buggy than your code. I guess I haven't been in the industry long enough to experience logic heavy tests
@anarchoyeasty3908 Жыл бұрын
I love TDD and I'm proud. It's a fantastic method for developing software and think almost every rebuttal people give for why TDD is bad is almost always a misunderstanding of how to write good tests.
@anarchoyeasty3908 Жыл бұрын
But I'm also a communist who says the USSR just didn't do it right so.
@anarchoyeasty3908 Жыл бұрын
Prime's point about tests not catching every bug. That's fine. That's not a fault of TDD. When a bug occurs that you didn't catch at first, before you fix the bug make a test that describes what your ideal output is given the state and input necesarry to create the bug, and verify that your assumption that the bug occurs when the state and input are X actually fails. And then fix it so it doesn't fail. This isn't a crime against TDD it's how TDD handles doing bugs. Now, you know that one bug will never come back. Because if it does your tests will catch it because it looks for that situation. If it fails another way then repeat the process.
@anarchoyeasty3908 Жыл бұрын
Where did this insane idea that tests are written in stone and can never be updated or deleted or changed. That is not true. TDD is about documenting the intent of your code. If you no longer need the code, or if your test is no longer correct you can throw it away and change it. Just like we do to code. Imagine someone complaining that the requirements changed and now they need to change their code. It happens. Change the code.
@antdok9573 Жыл бұрын
@@anarchoyeasty3908 About making a new failing unit test that describes the bug, bingo. I think it also helps if you consider that you don't want to overcomplicate any single test either. Having two asserts in your test case versus one, just to catch that bug you didn't earlier isn't great design of a unit test.
@Wyklepheph9 ай бұрын
I used TDD to develop stuff that’s easy to break. Like writing functions to read bytes and determine a variable length quantity for the midi spec. Just an easy way to verify it’s working. It makes send that nasa needs those types of tests for their calculations. TDD is a tool that can help when engineering things that are prone to breaking, but likely won’t need major refactoring. Like prime said, black box function testing makes tons of sense
@alanhoff89 Жыл бұрын
Tests don't add value to the product
@ExdeathZ9 ай бұрын
The thing I hate about TDD is just that it is a *lot* more work. Not only do I need to code the thing, but I also need to code a thing that defines what the thing should do given a certain set of circumstances. plus, some tests are just objectively harder to code than others. Testing if a function added two numbers together is WAY easier than testing to make sure resizing the browser window moved the elements to the exact spots they are supposed to be. Sometimes you have to do a lot of extra work just to even test the damn thing did what it is supposed to, sometime it can take many times more lines of code just to check all the edge cases. Plus, you have to test all the fail states failed in the way that you want the code to fail. It is a lot if you want your tests to be any good later when you are making changes to your code and the tests tell you exactly where and what you messed up. Otherwise, what are you doing all this extra code writing for?
@Mish84420 күн бұрын
so you hate longterm perspective cuse more work? Not to mention that you seem to hate not just TDD, but tests in general. And with that mindset, either you will those tests now, someone will cry in the future. Hopefully you, cuse if you're the kind of person that due to laziness creates more workload for others in the future, then I don't like you
@ExdeathZ17 күн бұрын
@Mish844 im not strictly saying that tests are all bad, my comment mostly laments that driving your development on tests makes making the product very significantly more labor. Plus, since garbage in garbage out, if your tests are wrong at any point, they can lead to you either making the wrong product, or you can end up with more surface area to write in mistakes. With TDD, the whole point is that your tests are supposed to drive the development, so it is not much of a stretch to say that the tests describe the thing you are building. But if you are adding a feature and an older test fails, without any other context, you cannot know if the assumptions made when that test was written are still valid in the face of the changes that you made. So if you change the test to meet your new assumptions, you are now violating the description of the product that test was supposed to represent which theoretically undermines the point of having written the test in the first place. If you rigidly adhere to the test, you may not be able to add the feature, or you may need to integrate it in some convoluted way which can lead to greater code complexity and/or poor performance. These are the negative side effects that you get from TDD. Done well though, TDD gives you peace of mind that you didn't catastrophically violate the expectations of some other code that is well distanced from yours. Not all projects and teams are suitable for TDD. There is a very real cost to using it and it is very easy to use it wrong. I'm not saying "don't", but it isn't a magic solution. It takes work and discipline from everyone involved.
@shapelessed Жыл бұрын
All I was hearing throughout all this thing was "Use this, if you don't you're a dumbass"
@Ronsteri1 Жыл бұрын
This reminded me of a case in one of my jobs, where I found a really critical bug in our tests that was basically making almost half of the code base tests fail after fixing the bug. (This is because for some reason, tests were written by running the program and then asserting on those values to get passing tests...) I was told by my manager that we cannot merge the PR with the bug fix because it "makes our tests fail" :)