Transcript from the "Test-Driven Development" Lesson
>> Kent C. Dodds: Okay, so right now, if you look at your post.todo file, not the test. But if you look at the bottom of my screen, it'll show you where I am servers/src/controllers/posts.todo. This is missing a critical feature. It is a delete post function, so we want to implement that function, because we are not Twitter.
[00:00:28] And actually no, that's the update posting. Twitter does let you delete tweets, but not update, that's super annoying. But yeah, we do want to allow people to delete posts if they decide they made a mistake or something. And so that's the feature we're going to develop. But we're going to do it with TDD fashion, test driven development.
[00:00:53] So that's what your exercise is going to be. Let me demo that by doing the user's version of this. I've got the same basic idea.
>> Kent C. Dodds: Let's see. Go to users.todo.
>> Kent C. Dodds: Okay, so this is the idea of Test Driven Development, right here. Red, Green, Refactor. The reason, or kind of, there are several reasons that you would use This test given development, which we'll talk about.
[00:01:28] But the red green refactor cycle basically indicates you write some code that in your test that fails and you write as little as possible just to get something failing and then you write as little source code as possible to make that test passing. Then you refactor your source code or your test to a nice state, so something that resembles something that is even potentially shippable.
[00:01:58] Then you continue on until you finish the feature that you're trying to build. So that's the Red, Green, Refractor cycle. It's a work flow technique, it's a mechanism for to enhance your workflow. So without test driven development. How would you build this? Well, you would try to write a whole bunch of source code.
[00:02:19] And then you would go to the app. And you would run through the process of deleting a post or something. Which you would actually have to write the client side code for that before you could even test that or you would have to do Postman and all that stuff.
[00:02:33] So the test driven development allows you to automate that process of validation that what you're writing is actually what you expect and so it's actually. Winds up being a lot faster generally. Even though you spend a fair amount more time coding. And the cool thing about it is when you're all done you have a suite of tests that you can commit to your project and can continue to give you confidence.
[00:03:02] Sometimes the test that you create out of test driven development can be not really great for building confidence, may be you're marking a whole bunch of stuff and it's not giving you a lot of confidence it was just kind of helping you along the way of developing the software.
[00:03:17] So it's totally cool to just do with those test may be rewrite them from scratch now you'll have a working implementation and write a test that's a little bit better. But yeah often the test you develop during test driven development are actually useful and you'll come in those along with your source code.
[00:03:34] Any questions about that? Yeah?
>> Speaker 2: Do you have any thoughts on kind of what would be a good target for TDD and what where would TDD not be appropriate?
>> Kent C. Dodds: Yeah, good question. So Test Driven Development has a pretty good place in the world of pure functions. That's just anything, it's easier to test pure functions.
[00:04:03] And so yeah. Especially we had with it, is password allowed? We could just, here's a list of allowed things, here's a list of not allowed. And then just add password after password to those as we go. Just more use cases to help develop that function. Places where and in this situation we're adding a new feature, this delete, post delete user, that's a pretty good place for it as well.
[00:04:35] Places where it doesn't really work very well are UI where the, that's not entirely true. But in general it's a little bit harder, a little bit more tricky especially by taking a step back, in general, if you aren't certain what you want things to look like when you are all done, then that's a place where you can't really use TDD.
[00:04:58] Because the idea behind TDD is, I know what I want this to look like so I'm going to write out some code that resembles how I want it to behave. But if you're just experimenting and you're not sure how you want it to behave, then you can't really use TDD there.
[00:05:15] That said, you could experiment with different APIs. And I think I want it to look like this. But yeah, I struggle sometimes with TDD. On a personal level, I don't actually use TDD a ton. I do have some situations where I use TDD. I also use RDD, which is read-me driven development.
[00:05:34] Where I'll document what I want first. This is what I want it to look like. Then I'll write the test to validate that this thing works like that. And then I'll write the implementation. That actually is really awesome. It's a lot of fun when I have a clear enough vision of what I want this to look like to write some documentation for it.
[00:05:51] But yeah. TDD is something that you kind of develop an intuition for. And especially at the beginning when you're not used to it. It's something that you kinda need to force yourself to do. And then over time, you kind of develop this intuition and it's enhanced work flow experience.
[00:06:12] Cuz it really can enhance your workflow.
>> Speaker 2: So why don't you use it often?
>> Kent C. Dodds: Why don't I? I feel the type of code that I write is often experimental code, at least recently. I'm building a lot of tools and stuff like that for PayPal. And so when I was doing product stuff, and generally, TDD made a little bit more sense.
[00:06:35] I had a better idea of what I was building. But also, I was doing more UI stuff, [COUGH]. And the tools that we had when I was doing product stuff for testing UI we're generally not super well suited for TDD. Now, if you come to the workshop tomorrow about testing react, I actually created my own library that you can very, pretty easily test using TDD, test UI with TDD.
>> Speaker 2: [LAUGH]
>> Kent C. Dodds: But part of the reason it ended up being terrible was because I went with TDD so hard that I actually skipped the refactor step. So maybe it wasn't really TDD.
[00:07:45] But I was, okay so these are all the things I want it to do. And then I just coded it out. And I never stopped to think, is this code maintainable? And it wasn't, as it turns out. But it's still being run on probably thousands of production apps today cuz it was a dependency of a library that thousands of people use.
[00:08:03] So you know you're not supposed to use it in production but probably are. So yeah, just make sure you don't skip that refactor step because you could windup with something that's not very maintainable. The cool thing about TDD though is you can feel pretty safe with the refactoring step because if you break something in the process of refactoring then you can go ahead and fix it.
>> Speaker 3: How closely should your code follow testing? In other words, is it better to write a test and then code or write a bunch of tests and then write the code?
>> Kent C. Dodds: Great! So, that's a good question, there are actually a couple camps in this. There's people who are very much TDD, write as minimal code as possible in your test.
[00:08:50] Write as minimal code as possible in your source just to make that test go green and then keep going. And that's kind of how I'm gonna try and show it here. It takes a certain amount of discipline to do that. And sometimes you just have such a really perfect picture of what you're trying to develop that you could write a full script of test and then write the full implementation, and that'd be fine.
[00:09:15] By keeping things tight in that feedback loop and it kinda helps you check yourself as you go because if you write this big suit of task. Then you could find yourself making a couple of assumptions about what's possible or what it makes sense about the implementation and then you get to implementing and you realize ooh wait no i cant do that.
[00:09:37] Then you have this, a bunch of text that you have to pick and choose which ones are relevant still and so, by keeping it tighter, you can make sure to avoid situations like that. Also I sometimes, [COUGH] you could find that there are situations where you´re at a test for code that actually doesn't need to exist, like for an API that you don't need.
[00:10:05] So by focusing on one little thing at a time, you can force yourself to ask question, do I really need this? Is this necessary because the implementation? Or maybe I could change the implementation so I don't have to even have this. So generally, it's better to keep it a little tighter.
[00:10:23] But if you have a really good idea of what you want this to look like and how the implementation is gonna work, then you could try this suite of test, yeah. Clearly, I tried to be not dogmatic about any of this stuff. Lots of this is very loosey-goosey.