 Welcome to Agile Roots 2010, sponsored by Version 1, Rally Software, Vario, Amirsis, Agile Alliance, and Xmission Internet. Alright, while Richard is getting hooked up, that gives me a chance to get us started. And I am Jean Johansson, and I am Richard Thompson, Richard Thompson is working with us. We are going to talk to you about legacy code. So first of all, who has written legacy code? What? Okay. The tester. So, alright. So everybody's worked on legacy code, they've written legacy code. Alright, just wanted to make sure that you're aware that sometimes you're writing legacy code. Our first slide, we had Richard and I had this debate about the next slide that you're going to see. Richard wanted to put, he wanted to put obfuscated C on it. And he's like, I don't like what you put up there, and you're going to see it in a second. I just said it's not scary. He said obfuscated code would be scary. I, on the other hand, wanted to teach you how to sign. I want you to, I want you to test. That's what I wanted to teach you how to sign. So, Richard got his way, I got my way. Alright? Did you want to say? Who's that guy? Actually, go back. I went too far. Oh! Actually, it looks like Richard and I both got what we wanted. I can read that code. That doesn't look very obfuscated. There's white space. There's carriage returns. So we let Jeff, we actually begged Jeff to help us out. And while we weren't looking, he snuck that piece of code in there. So, give a big hand for Jeff or else this wouldn't be possible. At least it's a macro. Thank you. Alright. So, Rich shared and said something yesterday morning about legacy code. What did he say? Does anybody remember? I saw a bunch of tweets on it. So if you're watching Twitter, he said there's a secret. The biggest secret in the last 20 years is automated unit testing. There we go. Thank you. And that got retweeted, so. And James Granting said if you're, what he said, testing, he said you're writing legacy code if you're not writing automated unit testing. So that's why. And everybody knows that because everybody in the room raised their hand. So that's not very interesting. Let's go. Next. Why didn't you walk? Yeah, who is this guy? Who is that guy? Anybody know who this is on the screen? If you can see it? This is Michael Feathers who wrote a nice little book, which our lovely Jean will be demonstrating to you right now. How to work effectively with legacy code. And I steal his definition of legacy code, which as we said is any code without tests. And he's going to explain to you in that book scenarios that will feel very, very familiar to you if you've ever worked on legacy code. I can't test this. This is awful. This guy is going crazy. And he shows you a bunch of techniques for how to deal with that code, which is what we're going to be blasting through in the second half of our talk. But first, let's talk about, let's talk about the legacy code. It's very smelly. Are you guys familiar with code smells from Fowler refactoring? Two couple hands. So smells are characteristics of code that are indicative of a potential problem. So legacy code tends to be pretty smelly. You have to do shotgun surgery through lots of places in the code to fix something or change something. You've got duplicate code. You've got inappropriate intimacy. This is where one class puts its hands into the pants of another class to get at something. Not really a good idea. Long switch statements, inheritance hierarchies that operate in parallel. So you add one class, one place, you've got to add a class in another place, but you didn't find that out until something broke. Long parameter lists. These are all examples of code smells. You can look at Martin Fowler's book on refactoring to get a longer list of code smells. And they don't necessarily indicate a problem. But they're, you know, good indicators. You want to do this one? No. Okay. He wants me to talk about this because this is my idea that legacy code is like a jigsaw puzzle. That there's all these pieces and some of them look similar, but none of them can be used in exactly the same place that another one is used. And they only fit together in exactly one way. And when you're trying to take a piece of legacy code and instantiate it in a unit test, you find out that you can't because it's only created in such a way that can only be used in one place in exactly one place only. So as soon as you try to use it in a second place, i.e. your unit test, you can't. So it's a big puzzle and you can't see what the pieces, you can't see the big picture until you study all of the pieces separately and then you kind of slowly form this big image of, oh, that's what that thing does. And it only does it in that one place over there. You can't use it anywhere else. So who recognizes this? Who recognizes this image? The Parthenon. Is the Parthenon worth saving? Yeah. Yeah. I mean, they spent millions of dollars, maybe, I don't know the numbers, but it's a huge amount to restore it. Some of our software, some of our legacy code is worth restoring. We got to know how. Okay, but the thing about legacy code is that, you know, it's this big jigsaw puzzle, but it is also fragile. It's dangerous to work on legacy code. By just virtually the fact that it's legacy and has no tests, we don't know when we change something. If we're going to, you know, it's like poking at a bullet jello. You poke here and it bulges out over there, except you don't find out that it bulged out over there until you shipped your fix to the customer and then they're like, no, my reports don't work. You know, and you're like, oh, crap. I didn't even think of testing reporting. It's totally unrelated to what I was changing. So legacy code, the place you have to start is to start with Safety First. You need to make a limited number of manual changes in a very safety-conscious manner so that you can then introduce some testing to give yourself a safety net. And all these techniques for taking legacy code and getting it under control, they're a book of recipes for these manual refactorings that you have to do very carefully. Did I miss anything? So, let's go on. Yeah, but you have to talk about this one. Okay. He zenized it to where I don't even remember now what this is supposed to represent to me. All right, so the jigsaw puzzle that he was talking about earlier starts to have mountain range metaphor snuck in. I mean, this is the Yellow Mountains, and it's full of people. And to get from one mountain to the other, you've got to build bridges. You've got to find a way to fit the test harness in. You've got to write covering tests around your framework. Otherwise, you're in trouble. So what we need to do with these dependency-breaking techniques is your legacy code, the reason it's fragile and brittle is that it is coupled to everything else in your legacy system. So all these things are highly intimately connected to each other, and you have to find a way to slip between the cracks and get in between these collaborating items so that you can get them in isolation and start getting them under test. If you notice here in this picture, you've got these mountain tops, and a lot of times when you're working on legacy code, you're standing at the top of one of these peaks and you say, I need to get to that other one, but I can't go up. If up is better code, sometimes my code has to get worse before it can get better. Anybody who's ever done any home remodeling is going to understand that living with the disaster until the project is done. So really with legacy code, the techniques that we're going to show you are atypical refactoring. Usually when you do a refactoring, your intent is to improve the design of existing code. But with these dependency-breaking techniques, these are careful refactoring that don't necessarily leave the design in a better place when you're done, but they do leave the code more testable when you're done. So we're making a conscious decision to trade some code ugliness for testability, because it's that testability that we need to give ourselves confidence that our changes aren't breaking things in the system. Okay, that's the demo part. So what we've got is we've got some code that can't possibly be tested. I mean, this can't possibly be tested. We've got an HTTP service request. We've got... What am I going to do with that, Richard? With this thing? Yeah. So how many of you have tried to write unit tests for legacy code and just said, I can't test this? This code's untestable. It's impossible to test this. I can't test user interface. I can't test interactions with the network or the database or the clock. Okay, this is coupling to the network. It's an explicit class from an API. It's not ours. We can't change it. We're stuck with it. But that doesn't mean we can't change all the stuff that's using it. So in this case, it's a problematic parameter to this method that we want to test. What we can do is adapt to this parameter so we can take this thing, create an interface that will be used in place of that type for this method, create a new implementer that will implement that interface and adapt it to this existing type, and then we can create a second implementer that will be a test double for this type in our test. So this is a dependency breaking technique called adapt parameter because we're going to take this parameter and adapt it to an interface. Richard, I don't know what you're talking about. Can you show me that? Yeah. We got one that we cooked earlier. We're going to pull that straight out of the oven. So here we've created an interface. Now we've called this parameter source instead of it was HTTP servlet parameter thing, right? What we're doing with this interface name is we're introducing a more explicit role for what that is doing in our code. It's a source for parameters in this method. So we've introduced an interface, changed the method to use the new interface, and now we're using this new method that we've put on the interface up here, and we named it get parameter for name. If you were paying attention before, it returned an array of strings, but we only cared about one, so we've made that method do exactly what we want and nothing more. So now it just returns a single string, and then otherwise the code is as before. Now we can write a test for this if we scroll down a little bit. Here's our fake that stands in for the real thing in the test, and here's the production code that implements that interface, and you notice that it has a constructor. If we look down a little farther, we'll see that it retains, it gets this array of strings and handles the collapsing of the array to the single value that we care about. So now using this code in production and the fake in the test, we've taken that code, decoupled it from this problematic parameter, and now we can write tests for that method. Okay, I'm starting to see this. I think this could work. I got some other code that's nasty that you can't possibly test. Bring it on. Okay. So we've got a mailer. We're going to send mail. I mean, if we test this, all my friends are going to be spammed, and I don't want that to happen. So we can't test this, Richard. Sure we can. The problem is that this constructor here has something inside it that we don't want to happen in our test. And so what we're going to do is we're going to take this thing, and instead of having it living directly in the body of this constructor, we'll introduce a new parameter, and then we'll use the parameter here in the constructor instead of this explicit new call. Now if this happens to be Java, so we can overload our constructors, so we can create a new constructor that takes the two arguments, the original constructor that takes the single argument will delegate to the new constructor with this new mail receiver as the new argument for the two-parameter constructor. And by doing that, we leave the rest of the production code that's calling new mail checker with a single argument. That code doesn't have to change. So we're preserving the signature of our existing legacy code. We're adding an overload with a new parameter that lets us test this stuff without this awful mail receiver right in there. What does Michael Feathers call that? This is called parameterized constructor. So we've taken the constructor. This was the signature of the original one. We've added a new parameter. Now in this particular case, we're assuming that we can make up mail receivers that are going to work okay in our test. If that was a problem, we could do that adapt parameter, just like we did before, and we could adapt this to an interface. But in our test, we can make a fake mail receiver, pass it in as this argument, and then this object will be constructed with our fake and it will collaborate with the fake instead of the explicitly constructed object. Pretty easy. That seems easy. It seems hard about that. That seems easy. Okay, I've got some more. This is just the beginning. These are the easy stuff. Yeah, okay. Bring it on, buddy. All right. So we've got this style master with some form styles. We couldn't possibly test that one. Oh, everything can be tested, John. You can test anything. The problem here is you've got this call on a static method from another class, and it's doing something in here that is problematic. But remember, we can, even if we can't modify style master, we can modify page layout. This belongs to us. We can take this expression. We can extract that expression into a new method and in our test code, we can subclass page layout and override that method to get rid of the problematic dependency. So here you've got a call that's giving you trouble. We can extract that call into a new method and then subclass page layout under test and override the new method that we've created. Before you do that, wouldn't that be slow? I mean, aren't you going to slow up my calls? That's an extra layer of indirection of pointer calls that's going to happen if I do that. I did this because it's faster. The production code will be making a method call on this class, and it's going to just delegate to this other static method, but most compilers these days are going to be able to inline a single line method like that, and you're not going to see any difference whatsoever. And even if it were a problem, there are other techniques that you can use to extract that out and separate it statically rather than dynamically. Okay, let's show me. I want to see my code. Here's where we've taken this... Hey, that doesn't look right. I think this code here is wrong. I think this should be a call to form styles without the style master in there. So that's a little typo, but what the intention is is to extract out this call into a local method on this class and then call the local method instead of this. I'm sorry for that typo there. Now, if we scroll down here, our testing page layout class is going to extend page layout and override that method with something that returns something that's going to be useful for our test instead of coupling us to this static method. But the production code will still call into this static method. Again, Richard? This is called extract and override call. We've extracted a problematic call into a new method, and then we override it in our test to change the behavior during test. I see how I can test that. I got another one for you. Okay, so I've got this global data, and everybody knows that legacy code is full of global data, and I didn't write it. I mean, I know better than to write the right global data, but it's there, and I don't know what to do with it, because it's all over the place. Quick survey, who's worked on code with more than 500 global variables? Nice. Nice. I've got an open-source project that had over 760 some global variables. So I've done this one a lot. The problem here is, in this case, the global is a reference to a global function. Now, a global function, it's still a dependency on a global thing, right? So how do you swap that out during test? In fact, let's look at... Can we look at the other source file? That's just a simple global variable. So here's the global variables. The method for applying it to a global function is very similar, but this one's probably going to be a little easier to grok. So we've got these global variables. We've got this controller class. It's got a suspend frame method where it's manipulating these globals. It's got a flush frame buffers where it's manipulating those globals again. And the idea here is, take these globals, and instead of making them global-free data, we will put them on a class, and then we will have a global instance of that class that the existing production code is going to use, and we will be able to supply a separate global instance of that class in our test. And you'll also find out, and this is a good example of this, that there tends to be clumps of global variables that always have to be manipulated together, like a flag in a list, or in this case, it's two arrays that always go together. So that's a good indication that these two things have a related responsibility, and by putting them on a class together, you can represent that design intent more clearly. So you put this stuff on a new class, you change these references to a new global instance of that new class, and we use a technique here called leaning on the compiler in a static language, you can use this, and that is where we, once we get rid of this global, and then we compile our code, the compiler is going to tell us all the places where, this is an undefined global reference, I don't know what this is, so that gives you a quick way to identify all the little places that you need to touch up, and then once we've got that on a new global class, we can write a test that is either passing in that, you can do that additional step of passing that dependency on that global class as a new argument, or you can just create a different global instance in your test code. So can we look at the test code now? Does that make sense, John? I'm starting to see that. Nope, this is the wrong one. Okay, so here we've created this global frame class that's going to encapsulate these globals, we've given that weird, you know, size for AGG 230, we've given that a more meaningful name of buffer size, and we've got the active buffer and the suspended buffer. Here's the new global instance, so we still have a global variable, but we've encapsulated these two globals into a global variable that is an instance of this class, and now the controller is taking, it has an instance variable representing that frame, and we've added a constructor so that we can supply a frame explicitly. If we don't provide a frame explicitly, it will default to the global instance. So this is going to end up being the constructor used in the production code, so it won't change, so we preserve the signatures of this AGG controller class, we preserve the signature of its constructor, but we've added an overload that lets us supply the particular frame it will interact with explicitly. And if we scroll down here, it will reference to the frame that it's going to use, and the suspend frame method now is referencing the instance data instead of the global, and in our test, we supply an instance we created for testing. I can see how that frame... That one actually hurt my head a little bit. It's a lot of steps. So I want to take a break. I want to give a book away. Yay! Who did not yet get a raffle ticket? Come up to the front No, it's free. Any guesses on what book we're going to give away? Yes. Now, can I get three more tickets? Just going to cycle back around. So let's give away a copy of Feather's book. I want to thank Pearson Publishing for providing us with the books that we're giving away. Okay, I have a number. It says 8 2 9 2 4 We have more books. Don't be disappointed. We also have a consolation prizes for anybody who doesn't get a book until we run out of them. Then we're really stuck. Alright, well now I'm ready to go back to looking at code. Here's one we can't test. You can never test GUIs. You can't test, especially... I don't know how to test a brush. It's a stroke. It's a line. How do I test the line? This is one we're not going to show you unless there's enough time. Alright, so again, when I email or when I send something over the net, I've got a packet. And packets go across networks and networks are often down or they're slow. So what am I going to do with the packet? I've got a packet. I can't test that. It'll be too slow and the network will be down. My tests will be broken. Yeah, this stuff in here, this is going to be problematic. So one technique is you notice here that we're using packet, which is a parameter and we're not using anything else. So this doesn't actually depend on any instance data in this class. Okay, I see that. With that observation, we can say, hey, you know what? We can just extract the body of this thing into a new static method and then we can write a test against that static method. We don't even have to instantiate this RSC workflow because it's doing other stuff here and up here that we don't want to do. So if we take this thing, this body, extract it into a new static method and the instance method delegate to the new static and again, the compiler is going to take care of that one line method so it's not going to be any kind of big problem with performance. Then we can write a new test against this that just deals with the input arguments. Can you say what he just said? Yeah, he just mentioned that this little dot dot dot here is indicating there's more code inside this block. Just trust me, the whole ugly thing only deals with distance data. If we showed you the code and it's full ugliness, you'd just be sweating bullets. Yeah, you wouldn't like that. So here's the after. We've created a new method called validate packet and we've used intention revealing names as best we can so that this thing is saying what it does and we've made this new method static. The old method body is now inside this new method. The existing method that we wanted to test but we're having a hard time instantiating this class is now delegating to the static method and we're good. Now we can write tests for this without instantiating this problematic class. And earlier Arlo showed us a mocking technique of how to actually test each one of those lines. Now yeah, remember these are all careful manual starting points to get tests in place so that once we've got tests in place we've got safety and then we can apply aggressive refactoring techniques with confidence. I do have another one. I've got another one that now we get to the draw because we've got a matrix. We want to test this draw but the lines... I can't test lines on a screen. I have to look at that. I've got to get some manual tester to look at that to make sure everything lines up. So the method's doing a lot. How am I going to do that? Do I do screen captures and do bit pixel stuff? How do I test this? I'm making sure we're in the right place. These long methods that do lots of stuff they're hard to test because too much is going on. It's in the context of this GDI brush class which just instantiating that in order to test this one method may do a whole lot of more stuff even more stuff that you don't want going on. So you take this thing and just move it to a new class and have it collaborate with GDI brush. That way we can remove it from this problematic context of this difficult class get it into a new context where it's easier for us to write a test against this method. We can if we need to reference stuff back in here from inside here like this draw point we can take this guy and pass it as a reference to the new class that does the work so that he can talk back to where the code used to be. So we're going to take this method and break it out into a new method object. That's what this approach is called. So you move all that problematic stuff in this case we're going to create an interface that represents our original guy that we saw that the draw method called back to draw point and because we're trying to decouple things here we're going to have a new interface that the old class will implement. So that's this new interface our new class is this renderer that does the draw he's the new method object and his signature of his constructor is the same as the arguments to the old method so we take the arguments for the old method and make those the arguments to the constructor of the new class and we do that by copy and paste to prevent typo errors because remember we're being very careful with manual editing here because we don't have tests in place yet we're doing very careful specific steps and this is one place where copy and paste is your friend because it's going to preserve those Actually didn't you want to say cut? No. You wanted to say copy? Yes. Okay. Because we're going to do this one step at a time so first we're going to get this class compiling now we're showing you the end result we're not showing you all the intermediate steps but when you get this class compiling you want to copy the arguments from the old place from the signature of the old method paste them as the signature of the new constructor for this new class and you'll initialize the instance variables that you've created you create one instance variable for each argument to the old method once you've got this compiling if it doesn't compile just based on the arguments to the method then that's telling you it's using instance data from the old class in which case you need to pass a reference to the old class and that point renderer is the new interface that we created for the old class so we've got a reference to the place where we came from passed into our new code here's the draw method that is now located here once you get the new class all compiling and you've got all the references that may be present to the old code working if we scroll down further then we can take GDI brush make it implement the new interface it still has a draw point but once we've got that new class compiling we can get rid of the implementation the old implementation of draw by having the new implementation instantiate our new class and then call draw on the new class now that we've got this problematic code for draw for the new class we can write tests for draw by testing against the new class the new class collaborates with the old one through an interface so we can fake that out with a test double this is another big big change in terms of the number of steps to go through so it's one you have to be careful doing so we don't have to test the lines we don't have to test the draw actually worked well when we test draw when draw can we switch back to the original implementation for a second so the old draw called draw point this was the thing that it processed a list and then boiled down to something that called draw point this is the thing that did the low level work now draw point will be called through an interface back to the original class so in our test double the implementation for I'm sorry in our test when we call draw point when we call draw in the new class in renderer it eventually will call back to draw point in GDI brush in the production code because it's passing this when it instantiates renderer so in the production code it will call back to GDI brush in our test so by using this as a reference to the GDI brush class we will have a fake that implements the point renderer interface and that's how we will sense that draw ended up calling draw point this seems like we just made our code a little bit uglier we did a lot of work and we just made our code a little uglier it's remodeling baby you gotta do some demolishing before you can build the new room oh yeah I remember you said that alright well I've got some more problems for you I'm starting to be convinced that you can actually solve this but I'm going to show it to you I'm not seeing this one we should be in pull up feature so it sounds like you got some new work you need to add in here some of this stuff you need to change because you've got features you want to add that's what I'm looking for lots of times you've got a class you need to add some functionality to it and there's a group of methods and a group of instance data that you need to change in order to make that new functionality and look at this thing it's doing all this get dead time and doing all kinds of things and this is really where we want to do some changing but this class is also doing all kinds of other stuff and it's making calls to the database who knows what else in here that's going on and you know it's problematic so just like we did with breakout the method into a method object we're going to take the group of stuff we care about the items and this other method that's down here if we can scroll down a little please this get dead time this is where we want to change we need to take this and the items it wants and we need to pull them some other place after we've got tests in place over the existing behavior so instead of doing breakout method object on this guy I mean he's referencing this other stuff and it could be you know a bit of a tangle to do breakout method object so what we can do is we can take this stuff that we want to change create a new super class of this existing class pull those instance data and methods that we want to change up to the new class now this method I believe there's also a call in here to validate no sorry it's calling get standard finish though you know if we pulled try to pull this out into another method we might have to pull out some way to call get standard finish but what we'll do is move this up to a new base a new super class of this class pull up the stuff we want to change that new super class will be abstract and the other dependencies on the other methods of this class that we're not going to change will be abstract methods on that new super class and then in our test we'll be able to create a subclass of the new super class that fills in the dependent methods with a stub and this is starting to make my eyes bled so why don't you show me some code pull the cake out of the oven let's see what it looks like when we're done so here's our new scheduling services base class I've pulled up the list of items I've pulled up some methods get standard finish get clock time not shared here's the place we want to make a change and if we keep going down we'll see our old class now extends that interface that we've created the abstract base class and his existing update schedule item stays in place this is the guy we weren't interested in changing and we weren't interested in changing validate if we keep going down so validate that database stuff is still there in our test we can extend our abstract base class fill in any of the abstract methods that we need in order to get our abstract base class as a full concrete implementation our an under test our well this is our test case and here's where we've got a little test for that where we're instantiating this new derived class from the new abstract base and then we're testing that class in here this get dead time now we've written covering tests to say what get time should do in the existing implementation before we make the change we'll be able to make it test driven because now we've got this method pulled out in such a way that we can test it that was just a lot of words I think we should give away another book or something I'm ready to give away another book who's going to draw this time I want some sleeper from the back row to come up here and draw the next number out you or you why don't you stand up no that's not going to work make sure he doesn't put anything in should be able to just read off the last three numbers but he knows because everybody's got a seven everybody's got an eight everybody's got a two everybody's got an eight no no there should be another eight and another eight eight the brother of the beast is not here bonus right in the front I'm feeling jolly let's give out another book since you have no motive there's no alternative motive alright so starting with seven eight two nine two four did I just read that one don't put him back in after you pull him out he stuck it in twice just blame somebody else blame the system I don't blame the system game the system alright so here we go seven eight two nine zero seven alright which book are we doing look see they're in the back and they stayed awake alright we have an agile product management with Scrum okay do you want to do one more we'll do one more seven eight two eight eight nine awesome practices for scaling lean agile development that's a big one that's a big book I want your ticket so I can put it back in two points that anybody can name that movie reference dirty Harry alright I'd like to see you got more challenges for me I'd like to get you a challenge that you can't fail at that's not seeming to work see that everybody knows these C classes we know where they come from yeah these things they can be a pain because you know you want to rate a test for one method and you end up dragging all the other junk along with it and it does all kinds of stuff you don't want going on so I mean you got any ideas I don't see it I couldn't test it no I can't so everybody who's fresh up on their C plus plus remembers that methods here are simply declared and they come from some other place at link time right oh yeah I remember a long time ago we don't even care what file they're in when they come from some place at link time we just have to make sure that we get one from somewhere so we're going to cheat and what we're going to do is we're going to take this stuff that's being a big pain in our backside and we're going to provide a definition remember in C plus plus there are declarations like what you see here and there's the one definition rule which is that everything is declared must be defined in exactly one place so we're going to set our monkey wrench and beat on our build system and we're going to change our build system when we build a test for this thing to not include the production definition for the things that are causing us trouble and we will supply our own definition in our test code separate make file you do some repackaging you put stuff and you make static libraries that don't include the definitions for this thing test links against the static library there's a lot of different ways you can package it but the key observation is that there's the one definition rule in C plus plus you provide one definition that is used in your production build and a separate definition that's used in your test build that stubs out this problematic stuff and if we can look at the one out of the oven we'll see here we included the header file which provides the declaration but no definition so if you have header files that include the definition directly as inline methods you have to do a little massaging to make sure that you move the definition from the header into a separate file so there's a lot of different ways you can do that but you must make sure that there's one definition provided for production and a separate definition provided for test so here what we've done is we've taken this stuff that's a big pain and stubbed it out and this thing it doesn't even do anything anymore just if you scroll over to the right little bit you see it's just returning a minus one cast it into a root ID and this thing does nothing at all anymore and here's our little test this one happens to be looking like a boost dot test unit test for C plus plus we instantiate a dependent parameter to the constructor of this class we're trying to test so we get that instance created and then we call the method we're trying to test and we do an assertion on the desired behavior so we're covering the existing behavior by stubbing out the problematic stuff and providing a separate definition this is called definition completion we complete the definition in the test code with a stub this doesn't seem like one I would want to use very often it's ugly it's problematic it's confusing but sometimes that's what you got to do to get stuff under test with legacy code we got to break some bones so we can reset the legs straight who's in C plus plus there's one now two okay there's an alternate for other languages this technique can be applicable really yeah because you can supply alternate packages in Java by adjusting your class path alright who's testing Java okay this is more applicable to our audience .net it's a little more problematic if you've got strong references to the assemblies you might have to do something else you know so these not all these techniques are applicable to all languages in all situations but fortunately you've got a big bag of tricks there's a bunch of techniques that are just covered in Feather's book that we haven't talked about good observation I would repeat that observation is in dynamic languages like Ruby or JavaScript you can just simply I guess Arlo referred to it as monkey patching you just shove the stub in over top of the thing that used to be there in JavaScript you can just replace any method definition with a new one in Ruby you can open up a class I think if Jeff will assist us there's a Ruby example if we open up the .rb file from the one folder so how many people program in JavaScript or in Ruby so who do you know monkey patchy if you do so here's one in Ruby here's the before there's stuff up here that's painful to us we want to write some tests for these things we don't want this stuff to run flip us to the next one if we look at the after so in Ruby this is the before show the test file in the after folder so sucked in the test framework open up the production code again null out the definition for the problematic method then write some tests for the stuff we want to test so here's an example in the dynamic language where you've got the ability to kind of just change stuff afterwards and it doesn't care so you can get on your way and write some tests so with that let's throw it open to any questions you have or observations work so the question was time like the network couldn't possibly that messes everything up yeah the call to like global time function to get the current time so we got a global and we've got system and we've got this delay how many people here show a message box through a static method call in some of their UI code right so you're probably thinking like how can I test code that calls messagebox.show if you're C sharp it's the same thing as testing against time and date and the trick that I've always used is extract those global dependencies either on the static method or the global function into an interface and have your class collaborate with the interface so you're taking static stuff or global functions wrapping them up in an interface then providing a production implementation of that interface that delegates right back to the static method or the global function but your code is all participating with the instance of the interface then in test you can implement that interface to be able to sense when you're calling to fake out what the time is fake out whether or not the message box was clicked okay or canceled so the core observation there is you've replaced something that was dependency on global with an interface and then that interface can be polymorphic in your test to a fake collaborator or in the production code it's going to be a delegating implementation that calls the old dependency and I've done that a lot with csharp code and message box.show it's one of the real ways you'll have all this application logic and in the middle there's a message box and if it weren't for that message box you could write a test for that application logic it's the message box that throws you for a loop now I can't write an automated test because the message box is going to come up in the middle so I'm going to have to click on it all the time so encapsulate that in an interface have your production implementation provide an implementation of the interface that delegates to the old static method or the old global function and then in your test you've got a fake that implements the same interface and a sensing or faking out the results of those calls well these code snippets that I'm showing here they are literally the code snippets taken from Michael Feather's book yeah I've got some code in the Internet user group that I can show you that for the time and date stuff I actually I wrote a recent blog post about doing test-driven PHP development and somebody said but how do I do for something that does the current time and I showed him exactly how to do that extract into an interface delegate in the production code and provide a fake it was in PHP but it's going to be very similar to Java or C-sharp any other stumbling blocks you know and whatever quiz me on things woohoo it's the other one clocks, network, database the three big offenders well UI might be number one same thing create an abstraction layer around your database and talk to your database through an abstraction that lets you polymorphically substitute in a fake database that's one way the important thing to remember about all these problems there's usually more than one way to skin any of these cats another way to get around database problems is to provide an in-memory database that you use in your tests so you're still talking to a real database as far I mean depending on what your frameworks provides in terms of database access you may be able to substitute an XML file database for your you know SQL or Microsoft SQL server whatever your database is your database infrastructure may already provide a certain degree of polymorphism that would let you substitute in something else that runs completely in memory and that you can easily configure XML files, comma separated value files those are common examples which language are you in so C-sharp are you using link so link has like when they do the translation link actually you can just take the table and fill it in and not even the database and you can do link against XML or arrays link is very flexible and what you can put on the back end for the storage I've done interfaces around my tables you know that I created by hand in C-sharp to abstract away my database some of the object relational mapping tools are providing the ability to be able to glue in a test double of the code that they generate okay so in Alan's case he's got code he has to test that creates a database and populates it now sometimes things are better done as a functional end to end kind of test so that might be an option for you that's still getting an automated test around is just not necessarily a unit test but again even if you're creating a database you make some API call to create a database you could interpose an abstraction there that's an interface that you've created and in the production code it just delegates to the real API call that does the operation of create database and same thing with inserting rows so you can always introduce your own abstraction layer but there's always as I say more than one way to test these things so you know not all situations are suited to unit testing some situations are suited more to kind of end to end functional testing which you could attack that with say fitness or any of these kind of other higher level testing frameworks but however you get your test your code covered with tests you have to get it covered with tests to get the confidence and the safety net to know that when you make changes you're not breaking the existing functionality and that's the key thing here we've got time for one more question is all that don't we have some more stuff to give away we do have more stuff to give away question asynchronous? so the question is what about interaction between asynchronous events I haven't done that one myself personally but again you're going to eventually boil down to you call into something that generates an event and then there's something that you do that is called when an event is received or explicitly asks is there an event available so again you can put interfaces around those you can have your test code explicitly generate the event that your production code is listening for so that's another way of doing things does that make sense? multi-threaded is hard but there are people that have tested that as well the part that's hard to test is doing things like simulating deadlock stuff like that so some of these things are easier than others but ultimately anything that you do in your own code that interacts with the execution of the hardware at some level has to go through some kind of mechanism and the common denominator and all these techniques that we showed was to introduce some level of interaction that lets you slide in between the jigsaw pieces sense that operation happening and detour it into the code that's providing the answer that you want to have happen under test so it's the old solve every problem is solved by an extra level of indirection in a certain sense so just some of these indirections are tricky like the link substitution one that's indirection but in a weird way it could get even crazier with manipulating the C preprocessor and you don't recommend that alright, thanks Jeff I think we've got, we gave out like three books so far we've got three more to go we should have 7, 8, 2, 8, 9, 5 is the box empty now? yeah we gotta choose and 7, 8, 2, 9, 1, 6 now for those of you that weren't lucky enough we've got a new book if you have a business card we can make your little pretty luggage tag over here on this table after the session is done and our final book would be 7, 8, 2, 9, 1, 8 sitting on the front row paid off alright so you said luggage tags, that's all we got we appreciate your staying for this it's late, the conference is over we're tired and I thank you for attending our session thank you very much