The red, green, refactor approach helps streamline testing and development processes, improve code quality, and foster collaboration. It promotes a disciplined and iterative approach to software development, resulting in more reliable and maintainable systems. Join us in this captivating episode as we explore this mysterious testing approach that transforms software development. Discover the art of writing failing tests, the magical moment of turning red to green, and the hidden power of code refinement. Learn the potential of the many approach and hear how frequent commits help weave a web of progress. Find out why only necessary code should thrive, how to enhance code quality and maintainability, and much more. Tune in to unravel the secrets of the red, green, refactor test, and discover the steps to better test coverage and code readability.
[EPISODE]
[00:00:01] MN: Hello, welcome to The Rabbit Hole: The Definitive Developers Podcast, living large in New York, I am your host Michael Nuñez, and today, we'll be talking about testing Tango, red, green, refactor, and why it's important to follow those steps.
In the last episode, I talked about the Arrange, Act, and Assert, which is a way to structure your code when it comes to testing. Today, the red, green, refactor will be more about the behaviors that one would have when you are writing tests. We'll go over red, green refactor. I imagine most of you know. If you don't, then stick around, tune in, and we'll just dive right into it.
First thing, I do find it really interesting that first red that we would write, because different programming languages will give you a red in different ways. If you're writing in Java, and you're creating a brand-new function for the first time, when you write that test, and you try to call this function, your test will not even compile. It'll just complain. “Hey, that function doesn't exist. What are you trying to do? Stop that.” As opposed in JavaScript, well, you could call that function, and you'll get undefined is not a function, right? Because it just doesn't exist. Then, you would then write – you would have to still type out the name of the function, and then it will error out because you're probably returning null. Then, you have it return whatever the thing that you are expecting.
One thing to think about when you're writing tests, I think I learned this from a fellow colleague of mine. If you’re unsure what to write the tests, or what kind of tests you want to write, always try – you start with just 0, 1, many, right? The idea being that, like, “Oh, I want to find a list of user IDs, and I have a function that will help me do that.” That first test that you write, write a list that returns blank. A blank list. Blank ArrayList. That'll get you to write the name of the function to call that function. Again, in Java, it'll just complain, like, “Hey, could you instantiate that function, please? Okay, thanks.” JavaScript will let you run the test and have it fail, because it's JavaScript, and it's the wild, wild west.
But then, you would have it return your zero or none expected outcome. Then, you can write the next test as like, “Okay, I expect it to return one user ID.” Say, for example, you had a database that was looking up people, and you wanted to figure out the age of someone, and it's like, “Oh, less than 25.” If you had one person who was under the age of 25, then that one person would appear, and you write that test. Then, that will get you to a way where your previous test was green, you made a pass, but now your next test is failing. If you try to hard code it with a user ID of that user, you're expecting, then that first test will fail for sure.
Always be mindful of that. You have zero and then one. Then, you now have two green tests, right? You have a situation where it would return nothing, and you have a situation where it returns one. Then, the idea being that this is a list, and it can return many as opposed as was, there are multiple people under the age of 25, then you would have it returned that particular criteria. I imagine that in going through that exercise, you will write enough tests to ensure that like, “Hey, the name is good. You're calling the right function. It's doing what you expect it to do.”
Each one of those steps, I'll go back to pretend like we are back at the zero in this example. You write that red test, function doesn’t exist. You write the function name. You have it return an empty list. Boom, now your test is green. The next question in the Tango, if you will, is to refactor. But given that this is the first piece of code that you wrote, chances are you may not need to refactor.
I will say that often people can. We've seen that in the workplace where people will add an additional step. This is like the Tango plus. I don't know Tango is three steps, I believe, and I'll use Bachata for example. That's a Dominican style of dancing that requires four steps. This is like the testing Bachata episode, I guess. The fourth thing that one would do is to actually make a commit. You write your commit message that says, “Hey, implements this particular function, when it does not have any records, for example.” Boom, done. I see that as a benefit and me personally, trying to get into that habit of adding the commit every so often.
Because we find ourselves like as we're iterating through writing another red test, then making a green. There's a point in time where you may have written a test and then like, all of your other tests break, when you try to make that one test pass. It's always good to just get checkout dot right back to where you knew that it was working. I imagine if you're not committing often, you don't have that luxury, so you might need to Command Z, or use your IDE to remember a particular point in time in which you remember that things were working. Always save yourself and look into making commits. I don't mean to switch up the Tango to another dance here, but just keep that in mind.
But the main three are definitely red, green, refactor. Going back to our example, you write another test that finds one user, and you do whatever lookup necessary to do that. Obviously, you're going to change the fact that it doesn't return an empty list, but that it looks up that particular person, and given that first test, it may not have any records in the database, so it should return nothing as the one that has one user will return one person. Finally, in the many cases, you will then ensure that you're iterating through a list, whether it's like a database list or whatnot, and be able to return those, the criteria of the test. I'm using user IDs as an example.
Always make sure, you look at the test, see what could be a refactor, what could change. You want to make sure that you make changes, not to the business case, but to the code itself, so that it represents the same business logic, but not — making it more readable and extensible if you will. I don't think that after every test you need to think really hard and break everything down. But definitely, be mindful when it comes to doing those refactors and ensure that you are making commits after every refactor. Because again, a refactor could lead to a point in time where things are broken. I can't remember when it worked. Command Z can help you but that gets really annoying really fast. I think it's important to follow those steps of red, green, refactor, because you will only write the code that you need to write to make your function work. You're not being savvy and pulling other code in.
I have this one module that kind of does this and you bring it all over, and it doesn't. It does everything right, and then some, and it's too bloated. To understand the business case, so only writing the code that you need to write is part of the reason why red, green, refactor is important, because you're just writing the tests necessary to make your test pass. If there are any additional implementation, your tests should always be written so that it is red, and then you make that implementation pass. Some people again, after making a pass will commit before they do the refactor. Again, I'm not here to tell you how to live your life. But I do think that maybe you can do a refactor. Or rather, maybe you can do a commit after you've refactored given that, like you've answered and got that test to pass, so then you can do the refactor to make sure they all do. But if you find that, like the refactor looks a little troublesome, just make the commit before and you can always amend it so that your git history is clean. But use those times to commit to your advantage so that you're not having to sift through history in time finding out when was the best time that things were working. I hope that this was useful in the idea of using red, green, refactor. Please, please use this as often as possible, as it will increase your code quality as you're writing the things necessary to make the user happy and that user story you're working on.
[OUTRO]
[00:09:20] MN: Follow us now on Twitter @radiofreerabbit so we can keep the conversation going. Like what you hear, give us a five-star review and help developers just you find their way into the rabbit hole. Never miss an episode. Subscribe now, however you listen to your favorite podcast. On behalf of our producer extraordinaire, William Jeffries and my amazing co-host Dave Anderson, and me your host Michael Nunez. Thanks for listening to The Rabbit Hole.
[END]