54 TMTC When to Stop Testing and Get Stuff Done
[powerpress] I got asked the question "When do I stop testing in order to get stuff done?" My answer was "I go faster doing TDD." Here's why I get more done with TDD. It forces me to think through the problem. This allows me to tackle the programming problem and solve it more quickly. I can define the behavior. I can determine the inputs and outputs and any other behavior related to the function I'm writing. I know it works when I'm done. I know when I'm done. (All the tests pass.) It provides a challenge I can focus on. I love a challenge and it gives me that sort of strong direction. If you have trouble getting things done and getting tests in, you need to practice. You need to get used to working with tests and testing frameworks. The more you do it the better you are and the more it becomes integrated into your routine. Learn your tool. The better you understand what it can and can't do, the better and quicker tests you'll write. Only test what you need to test. You don't need to cover the entire code stack. Just the limited set of code that solves your problem.
Teach Me to Code Episode 54 Hey everybody and welcome back to another Teach Me to Code podcast. This is your host, Charles Max Wood and this week I’m gonna be talking about, well I wanna answer a question that somebody post to me and I kinda going to enhashing out, what I think. But before I get started I want to acknowledge our sponsor. We have New Relic. New Relic is a super application management tool. They really do a good job by providing just some great information regarding what’s going on with your application, what exceptions are being thrown, what other problems, performance problems there are. Most of what I’ve used it for is actually either tracking down exceptions or working through and optimizing areas of the application that are slow. And they are so useful for that. Even their free version is actually pretty useful in just a couple of useful information you can get out of it. It’s really good, I highly suggest you go check ‘em out. You can do that by going to the website and clicking on the link on the right or you can go to newrelic.com. and just tell them that we sent you over. That would be great. Now, I’m gonna go ahead and jump into this topic. I’m trying to get some interviews lined up. I just haven’t spent the time to talk to people. I’ve had a few people say they’re willing, I just haven’t followed it up. So, I need to follow up and get some people on here and hopefully we can line up a few interviews here for the next few weeks. I’m thinking about changing the format of this a little bit, but I haven’t finalized what I’m thinking about so that’s just something to be aware of, that things may change within the next few podcast episodes. Alright, well let’s get into this question. So, I was chatting with a friend of mine and he asked me, cause he was facing a deadline. He said, “At one point, do you just give up on writing the test and just crank the code out because you need to get it done yesterday.” And it was interesting because I thought about it for a second and I realize that, writing the code without the test, like not doing TDD for me, actually it hampers me, and it hampers me in a lot of different ways. Mainly it’s just part of my workflow now. So, it’s kind of an interruption not to have TDD around. The other thing is it provides some real benefits to me as I’m coding that I think really make it worth the payoffs. So we’re gonna talk about those. The first thing that I think TDD really gives for you is that it allows you to think through the problem. So, you can quantify the behavior of whatever you’re testing. And even just a basic input-output kind of approach. So for example you say, “If I called this method with these arguments I should get these result”. And sometimes that’s enough. But the other thing is you also are then force to think about what other effects or behavior should come out of these. For example: should it save the record. In Rails that’s a relevant thing or should it save the object to the database or should it change certain attributes of my object or do this other things and so then you start running through the scenarios of: “Ok, so when I put this and I should get this back out and this object that I passed into it should now look like this.” And the nice thing is, once you have that in place, not only do you know what it’s supposed to do and know what you expect the behaviors of the other things that are being passed to it to be. But you’ll know when it’s done and you’ll know that it works when it’s done. Because you finished it off and you specified what it’s supposed to do. And so, you really get that benefit of knowing that, “Hey it works, and it works right and I’m done with this and I can move on to the next part”. The other thing is that, it forces me to think through the problem. Not just to codify, “Ok this is what it’s supposed to do and this is what supposed to go in and this is what suppose to come out.” But usually when I’m thinking that through I’m thinking: “Okay, so when I implement this, I’m probably gonna do something like X and Y and that would get me 90% of the way there or all the way there.” And it really just pays off. And so by the time you get around the coding and you work through the problem somewhat mentally because you wrote the test for it. The other thing that really pays off for me is that you wind up, for me I love having a challenge. So, you know, I get a puzzle and I solve the puzzle and if I’m working on a puzzle that’s interesting, I actually wind up getting really focus on the problem and try to solve it. And the test provides that for me. So when I write the test, I’m basically writing myself a puzzle or a challenge that I need to solve. And so I wind up going in and solving it. And I can focus on that for few hours and, you know, really wind up doing some interesting things. And so ultimately, I think it goes faster because in the end, you know that the thing works but you don’t wind up debugging this and that to try to figure out why it’s not working. You wind up doing a little bit of that sometimes but ultimately if you’re running into that, you can just write another test. “Okay, so let’s see. This test isn’t passing and this is what going on. So what if I assert that this other case is the case”. You know some intermediate step. Or you may find out that you need to pull part of your method or function out into another method or function that it calls into so you can test that one little piece. And what that does is it actually winds up cleaning up your code and forces you to re-factor things into a sane setup and ultimately makes you really think through the problem. And it gives you a framework to do that in because when you’re done all your tests will pass and you’ll know “Okay, not only have I covered what it suppose to do but I’ve also covered a few of the gotchas that is part of this algorithm.” Now when people ask me a question like this, and this is something that I really want to tear into. It usually comes down to, that they’re not as comfortable or committed to TDD. And ultimately, there are few reasons for this. One is it that they don’t see the importance of the test so they’re not committed to testing in general. And that’s a hard thing to solve because ultimately when you’re writing your code, if it works you don’t see the benefit of the test. But when you go back and you’ve had an experience where the test either told you that you broke something or the test told somebody else that they broke something you wrote or you’ve seen something like what we’ve just talk about TDD, where you wrote the test and it really payed off in the sense of “Hey, this worked you know, this worked, it‘s done.” And you’re like “Oh wow, that really worked out cause otherwise I would been sitting here trying to figure out whether or not it’s doing what it suppose to do.” And when you start getting those payoffs then you start to really get committed to testing. Before that I think it really just a matter of “Well this expert said that I should” or “My boss says that I need to” or “The senior developer that I’m working with does” or “Whatever the community in general thinks that a good idea”. Or “I read this book and this guy said that I oft to”. And so you start doing it and you know, if you don’t get that payoff pretty quick, then in a lot of cases people just don’t get committed to it. The other reason I’ve seen is that people start writing test and they realize real quick that: “I’m not really sure I’m doing here” or if their okay with the kind of the general “I need to write the test to make sure this functionality is in place.” Then what happens is they wind up not knowing their tool or, you know, some other thing kinda gets in the way and makes it hard for them to write the test and so they are like “Well, theoretically this is worth the effort but it’s a lot of work”. And it is upfront. It is, even if you understand the testing tool in general, you wind up seeing “Oh man, this is an interruption in the middle of my normal flow”. And when I first started doing TDD that was the way it was for me. I really felt like it was just getting in the way and causing me issues up front. But once I had fought my way through the test, writing the code was actually pretty easy. So, I highly recommend one that you try it for a while. It’s kinda like pairing in that sense, I’ve had a few people tell me that they want to start pairing with their development teams. And I usually tell them a couple of things I see. First off when you start out, don’t do it all the time but do it half the time. The other thing is, when you start pairing, you need to talk over how you wanna handle certain things like interruptions and things like that. And that’s how it go for pairing. Doesn’t apply too much to testing. However the last one is, you have to do it for at least a month. And for the last half of the month, you need to be doing it all the time. And the reason is because, once when you start, your productivity drops with pairing. It just, it does. I mean, your code quality goes up and there are certain benefits and payoffs. But ultimately your productivity goes down because you have two people that aren’t used to working together figuring that out along with figuring out the problems that they’re solving. But by the end, what you’ll see is that you usually get back to at least the productivity you had before with two people working on the code. And what you gain from that is a high level of communication and a better understanding between your team. And it’s the same thing for testing. So, ultimately, at first it is tedious, it gets in the way, it takes a while. It’s hard. “Do I test this? Do I not test this?” You know it’s really does get tricky. But if you give it at least a month, you will really become engrained. What you get out of it is it becomes a part of your flow so it’s not an interruption anymore and then what happens is you start to see these things pay off. And as soon as you see it starts to payoff then you really get committed to it. And that makes a huge difference. One other thing that I really want to tell you is, go learn your tool. So in ruby you have rspec and you have test unit. In other languages you have J unit or N unit. I don’t even know. I mean, there are dozens of them. If you’re writing for the web you can use selenium or water. You need to know what the tool is that you’re using. What it does well. What it doesn’t do well. What you can test with it. What the limitations are. And that will help you write better test. It will also help you work around some of the hairy issues because you’ll know how to hook into them with your tool because you understand it. I’m going through a little bit of a learning curve right now because I’ve been using cucumber for my integration test for a long time. And I’m always using it because a few people that I considered to be experts were saying “Use cucumber, it’s awesome!” And generally that’s true but the recent debate with David Heinemeir Hansson and a few other people regarding rspec versus test unit really made me think and I think this is really the thing that get out of it. Really made me think why am I using this tool. And it really occurred to me that the value of cucumber is so that somebody else can read my test. Well most of my project, nobody is looking at my tests. And the few people who are, are technical people like me. Ain’t gonna understand code just as easily as they can understand English. So there is no reason for me to be writing these English sentences and then figure how to parse them apart so that I can use webrep or capybara to hook into my website. So I am learning capybara and I’m just gonna hook it in to rspec. But that means I need to learn capybara instead of relying on the built in steps that come with cucumber than to use capybara. So in that case it was a simple translation to English and it was built-in that it would translate that to capybara but now I just want to use code I have to learn the library. Honestly it’s something I should have done before. I’ve used it before but it’s really something that I really want to do better. Now the last thing that I want to focus on is just test what you need to test. So for example, If you’re building Ruby on Rails applications, you don’t need to test the framework. You don’t. Unless you’re running into a problem where you think that the problem might be the framework. In which case then you’re write to test it to rule out the framework. But other than that, there’s just no reason to do it. The developers that are writing Ruby on Rails have, I think they have pretty good test coverage and hopefully the library will just work. It’s not your job to test somebody else’s library. But if you needed to work and it is the library, then maybe you need to. So again, it comes down to what you need to do. But testing, for example, if you’re writing a test for user class, you don’t need to go out and test the post class from the user class when you’re working with post on the blog. That doesn’t make any sense. You just need to test the user class and if it does have interaction with the post class then mock it out so you don’t have to worry about the post class and just assume that they behaves in a certain way. That it gives a certain result or whatever it is that you needed to do. And then make sure that your test of the post class guarantee that it has that behavior. If you can tears it apart that way, that keeps your test a whole lot cleaner, simpler and easier to write. Marking and stabbing is something that I think is essential for writing your test. But I’m not gonna go to it right now. Make sure though that you do have a good tool for any of this practices. So in Ruby on Rails, I typically use rspec. I typically use capybara, it’s what I’m using now for my integration test. I use flexmark for my marking and stabbing. I use Factory Girl to generate new objects that I need to operate on. Which Factory Girl is another thing that I wanna bring up. And this is a debate within the Ruby on Rails community. Ruby on Rails comes with a concept of fixtures which basically is a file that sets up several objects for you. And then you can operate on those objects. The problem with fixture is if you change a fixture that a test depends on, then it could break the test. So, I like instead to use factories and each test gets its own object. And this created when it runs. Factory Girl provide you with creating valid, consistent objects you can use across the board and you can customize them if you need. So it’s a nice way to just get a consistent result or a consistent baseline that you can run from. So I use a factory and I use marking and stabbing pretty frequently. And on occasion I use other tools like, I use selenium to test my java script on my pages which is kind of fun. I think it’s kind of fun to watch it run because it actually pops open Firefox and runs and then closes it again. So, anyway, those are just my thoughts there but ultimately, if you understand the tools, you know how to use them, you know how to interface with them, you can make it do what you need it to do and you just practice. You’ll get a whole lot better with TDD and ultimately you’ll find that it is an essential part of your workflow and it really does make your code better. So in general, you should be testing. If you want to write your test afterward, fine with me. TDD for me though is an integral part of the way I work. And in the end I get the added benefit of knowing that something broke or didn’t break. So anyway, I’m just gonna wrap this up. I do wanna again, acknowledge that New Relic is the sponsor of this podcast and I really appreciate them helping me out with it. I also want to just remind you that if you need help with your Ruby on Rails application, you can contact me. My phone number is 801-367-6164. I also restarted the Rails coach podcast and you’re maybe interested with that if you’re learning Ruby on Rails. I’ve changed tactics a little bit. I’m trying to cover concepts that will help you become a better Ruby on Rails developer. But I’m not gonna go into specific code implementations anymore. Mainly because I feel like that those are better covered on screencast rather than a podcast. And anyway, so if you’re learning Ruby on Rails that is a good place to go or you can just give me a call and we can set up a time where I can kinda help coach or mentor you. I generally do that for charge but if it is a 10, 15-minute thing I might just help you out for nothing. But I do wanna make sure that people are learning this and they are comfortable with it. I just, oh that was the other thing I wanna talk about. I gotten together with a few other people and we’re gonna start a new podcast. If you’re fan of Leo Laporte and Twit.tv, this is kind of the same style of podcast. We’re gonna be talking about issues, we’re not gonna talk about news. We’re gonna talk about issues surrounding ruby and ruby community. So for example, some of the topics that I’ve thought of that we could talk about are, whether or not it is worth using Rails over Senatra. Or some of the other frameworks that are out there. Things like that. Rspec vs test unit vs Emex. How to test java script. Whether or not to use jquery with your Rails applications. Just stuff like that, you know. We’re probably talk about the copy script debate that’s going over right now over the Rails 3.1 standard. Anyway, I have James Edward Gray, Peter Cooper, Aaron Patterson and David Brady that are all going to join me on the first episode of that podcast. It should be really fun. We haven’t nailed down what the topics are gonna be at but it should be really, really good. And if you’re wondering about any of those guys, just Google them and we’ll come out. I’m just gonna wrap this up and remind you that writing the code is the easy part.