<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: M. Scott Ford</title>
    <description>The latest articles on DEV Community by M. Scott Ford (@mscottford).</description>
    <link>https://dev.to/mscottford</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F676%2F21340.jpeg</url>
      <title>DEV Community: M. Scott Ford</title>
      <link>https://dev.to/mscottford</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mscottford"/>
    <language>en</language>
    <item>
      <title>Announcing MenderCon</title>
      <dc:creator>M. Scott Ford</dc:creator>
      <pubDate>Thu, 07 May 2020 19:38:16 +0000</pubDate>
      <link>https://dev.to/corgibytes/announcing-mendercon-kk5</link>
      <guid>https://dev.to/corgibytes/announcing-mendercon-kk5</guid>
      <description>&lt;p&gt;I recently announced on a few different social platforms that Corgibytes and Legacy Code Rocks are hosting a conference.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1248725371043930114-296" src="https://platform.twitter.com/embed/Tweet.html?id=1248725371043930114"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1248725371043930114-296');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1248725371043930114&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2 id="qa"&gt;Q&amp;amp;A&lt;/h2&gt;

&lt;p&gt;Since I published the initial post, we’ve had a lot of interest, and with that interest has come some questions. In hopes that others might find it helpful, I’d like to take a few moments to answer most of those questions here.&lt;/p&gt;

&lt;h3 id="why-is-it-called-mendercon"&gt;Why is it called “MenderCon”?&lt;/h3&gt;

&lt;p&gt;The term &lt;em&gt;mender&lt;/em&gt; was coined by me and Andrea after I saw an ad for a Maker Fest event and I said “where’s the event for people who like to fix things?!”. That’s what I want this event to be. It’s an event for people who are passionate about mending software systems. I want to limit the use of the phrase “legacy code”. While we’re using that term to market the conference, I don’t want the phrase to be directly in the title. I’m also intentionally avoiding “virtual” in the event name. Again, that can be something that’s communicated when describing the event, but I don’t want it to be a defining feature. If the event happens again in the future, we might be able to run it as an in-person event. In that case, I don’t want to have to change the name.&lt;/p&gt;

&lt;h3 id="why-now"&gt;Why now?&lt;/h3&gt;

&lt;p&gt;I’ve been wanting to host a conference focused on modernizing software for years. It’s been on the Corgibytes’ wish list for at least 5 years. The logistics of an in-person conference seemed overwhelming, especially because we don’t really have anyone on our team with natural event organizing talents. Since we’re an all-remote company, more than one person has proposed over the years that we try to run an all-remote conference. But with so many great in-person conferences, I was nervous that an all-remote event would not be successful.&lt;/p&gt;

&lt;p&gt;Then COVID-19 hit. Now, all over the world, people are sheltering in place. Many in-person conferences have been canceled or indefinitely postponed. Many people are craving more opportunities for professional connection and learning. Many people are working from home for the first time.&lt;/p&gt;

&lt;p&gt;I figured if there was any time when an all-remote conference might have a chance it would be now, and frankly with all of the stress caused by the pandemic, I need something positive to look forward to. Organizing this event has been a welcome distraction from feeling helpless about the state of the world around me.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And&lt;/em&gt; I think it’s incredibly important, especially right now, that we talk more intentionally about the long term maintenance and nurturing of software systems. There have been numerous reports of neglected systems being unable to adapt to the changes that are required of them, either in terms of functionality or load.&lt;/p&gt;

&lt;h3 id="whats-an-un-conference"&gt;What’s an un-conference?&lt;/h3&gt;

&lt;p&gt;Simply put, an un-conference is a conference that does not have a predetermined set of speakers or talks. The people who show up to the event are the ones who decide what gets talked about.&lt;/p&gt;

&lt;p&gt;This approach eliminates a fair bit of overhead for organizing the event. We don’t need to put out a call for proposals. We don’t need to go through proposals and decide who gets to speak. We don’t have to verify that the people who submitted proposals are still available, and we don’t have to notify everyone who didn’t get selected.&lt;/p&gt;

&lt;p&gt;The un-conference format also creates an opportunity to elevate voices who are not normally heard from. At a traditional conference, the list of speakers and topics is curated in some form by the organizers. This can often lead to the conference schedule being dominated by people who are well known or people who have gotten practice speaking in the past. While we welcome people with speaking experience and notoriety, it’s important to me that we create a space to where those who are not normally selected have a chance to speak. In an un-conference format, anyone who wants to speak gets to speak.&lt;/p&gt;

&lt;p&gt;So, by going with this format, there’s less work on the people organizing the event, and there’s an opportunity for new people to be heard. I call that a win-win.&lt;/p&gt;

&lt;h3 id="why-are-you-doing-it-this-way"&gt;Why are you doing it this way?&lt;/h3&gt;

&lt;p&gt;In addition to creating the opportunity to see some good talks, I wanted to create a space for other kinds of sessions, particularly ones that require some level of participation or discussion. With so many people working from home because of COVID-19, there are many who are craving more human interaction. I want to have the conference be a space for that. So don’t be surprised to see someone pitch a session that is simply titled something like “Let’s chat about the unique challenges of refactoring PHP”, and when you get in the room there are no slides, just someone who wants to facilitate a conversation.&lt;/p&gt;

&lt;h3 id="what-do-i-need-to-prepare-to-organize-a-session"&gt;What do I need to prepare to organize a session?&lt;/h3&gt;

&lt;p&gt;This depends on the kind of session that you want to run. On the simplest end, you can just prepare a topic or idea that you’d like to explore. That would be perfect for a purely discussion format. On the more complicated end, you can craft a slide deck and presentation or walk through a live coding demo. Those might work well if you plan on doing most or all of the talking during the session. I predict that many sessions are going to mix some elements of each of these approaches.&lt;/p&gt;

&lt;h3 id="is-that-the-same-thing-as-an-open-space"&gt;Is that the same thing as an Open Space?&lt;/h3&gt;

&lt;p&gt;I didn’t call MenderCon an Open Space, because I’m nervous about how closely we’re following the typical rules for an event that bears that description. There is a vibrant community that’s really passionate about Open Space events, and the people in that community take pride in making sure that Open Space events are done right. There were a few decisions that I made about the schedule that I felt would make it not fit the full spirit of an Open Space event, specifically, kicking the event off with a keynote and having dedicated networking time. If we were to follow the Open Space format strictly, then the keynote and networking time would be sessions like any others.&lt;/p&gt;

&lt;h3 id="what-do-i-do-if-i-want-to-speak-is-there-a-cfp"&gt;What do I do if I want to speak? Is there a CFP?&lt;/h3&gt;

&lt;p&gt;There is no CFP. If you want to speak, make sure you come to the “Pitch Session”. At the “Pitch Session” we’ll invite anyone who wants to organize a session up onto the virtual stage. There, they’ll briefly announce their session title along with a short description and the time that the session’s scheduled to happen.&lt;/p&gt;

&lt;h3 id="what-do-i-do-if-im-not-sure-which-session-to-attend"&gt;What do I do if I’m not sure which session to attend?&lt;/h3&gt;

&lt;p&gt;During each of the session rounds, there are going to be several different sessions going on at a time, and it may be difficult to decide which session is the best one for you. The Open Space community employs the “Rule of Two Feet” to specify that you can leave a session at any time and join a session at any time. If you feel you’re in the wrong session, then switch to a different one. Don’t feel obligated to stay in a session for the full time just because you were there when it started. And similarly, don’t be afraid to join a session after it’s started.&lt;/p&gt;

&lt;h3 id="is-there-a-website"&gt;Is there a website?&lt;/h3&gt;

&lt;p&gt;Not yet. :) We’ve purchased &lt;a href="http://mendercon.com" rel="noopener noreferrer"&gt;&lt;code class="highlighter-rouge"&gt;mendercon.com&lt;/code&gt;&lt;/a&gt;, but we haven’t published anything there just yet. Once it does, most if not all of the Q&amp;amp;A here will also be published there.&lt;/p&gt;

&lt;h3 id="is-there-a-code-of-conduct"&gt;Is there a code of conduct?&lt;/h3&gt;

&lt;p&gt;Yes! This event will governed by a code of conduct based on the &lt;a href="https://www.contributor-covenant.org/version/2/0/code_of_conduct/" rel="noopener noreferrer"&gt;Contributor Covenant, version 2.0&lt;/a&gt; (&lt;em&gt;shout out to Legacy Code Rocks podcast guest &lt;a href="https://where.coraline.codes/" rel="noopener noreferrer"&gt;Coraline Ada Ehmke&lt;/a&gt; for the awesome work on this resource&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;The finalized code of conduct will be available from website once we have it published. The only difference between the reference version will be the instructs for reporting behavior that violates the code of conduct.&lt;/p&gt;

&lt;h3 id="will-my-session-be-recorded"&gt;Will my session be recorded?&lt;/h3&gt;

&lt;p&gt;With the platform that we’re using, this is something that is decided when the session is created. If the session’s organizer would like it to be recorded, then we leave that decision up to them. We can imagine it being useful to have conversations that are not being recorded. I plan on recording the keynote and the pitch session.&lt;/p&gt;

&lt;h3 id="what-platform-are-you-using-why"&gt;What platform are you using? Why?&lt;/h3&gt;

&lt;p&gt;I was originally going to use a combination of Zoom and Trello. I was really nervous about the logistics of doing so, because I wanted for it to be very easy for people to create sessions, attend sessions, and then move from one session to another if they didn’t like the one they found themselves in. But I was determined to make it work.&lt;/p&gt;

&lt;p&gt;Then I learned about &lt;a href="https://hopin.to" rel="noopener noreferrer"&gt;Hopin&lt;/a&gt;, and I felt like it was built for exactly the kind of event that I wanted to run. There were even features that I would have had a very difficult time replicating by just using Zoom and Trello, such as virtual vendor booths and randomized 1-on-1 networking sessions.&lt;/p&gt;

&lt;h3 id="how-can-i-help"&gt;How can I help?&lt;/h3&gt;

&lt;p&gt;I’ve had a lot of people reach out and ask how they can help. I could use some help standing up a super simple website (see above), and I’d like to have people around on the day of the event who can help with any logistical challenges that may arise. We’ll create a dedicated channel in the &lt;a href="http://slack.legacycode.rocks" rel="noopener noreferrer"&gt;Legacy Code Rocks slack team&lt;/a&gt; to coordinate those efforts. I’d also appreciate support promoting the event. I know there are many fantastic menders out there who would have a good time attending MenderCon.&lt;/p&gt;

&lt;h3 id="anything-else"&gt;Anything else?&lt;/h3&gt;

&lt;p&gt;I’ve tried to answer all of the questions that I’ve gotten so far, but I’m sure there’s going to be more. If I missed something please ask in the comments below.&lt;/p&gt;

&lt;p&gt;Note: this content originally appeared on the &lt;a href="https://corgibytes.com/blog/2020/04/20/announcing-mendercon-2020/" rel="noopener noreferrer"&gt;Corgibytes blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>virtualconference</category>
      <category>legacycode</category>
      <category>techdebt</category>
    </item>
    <item>
      <title>The Tightrope Walker: A Metaphor</title>
      <dc:creator>M. Scott Ford</dc:creator>
      <pubDate>Wed, 24 Jul 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/corgibytes/the-tightrope-walker-a-metaphor-2abi</link>
      <guid>https://dev.to/corgibytes/the-tightrope-walker-a-metaphor-2abi</guid>
      <description>&lt;p&gt;&lt;em&gt;“How did it get this bad?! How could anyone on my team have thought this was okay?”-Anonymized Client&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Over the years, at Corgibytes, we’ve seen a bunch of projects in different states of disrepair. We approach each one of these projects with the assumption that every person who touched it did their best at the time with their given constraints. This is the embodiment of our first &lt;a href="http://corgibytes.com/about/"&gt;core value&lt;/a&gt; “Act With Empathy.”&lt;/p&gt;

&lt;p&gt;Assuming the best intentions is something that comes naturally for us but it’s not always easy for our clients to do the same. After working with us for a little bit, many of them are only just beginning to understand the rough state that their project is in. This often comes as a shock, especially to the less technical people who are involved with the project.&lt;/p&gt;

&lt;p&gt;On a call a few months ago, a client was in despair, trying to understand how any reasonable team could have made the series of decisions that got their project to its current state. For that project, there was virtually no documentation: nothing to describe how to set up a development environment; not a single passing test; and commit history comprised of epically large sets of changes with very terse change descriptions. The client was extremely frustrated and expressed dismay while wondering aloud how the project had gotten so bad.&lt;/p&gt;

&lt;p&gt;We often &lt;a href="https://corgibytes.com/blog/2017/03/14/point-inspection-metaphor/"&gt;use metaphors&lt;/a&gt; to help people, especially those who don’t code very often, understand the context of a given situation. Metaphors can be a valuable tool for communicating abstract concepts. In this situation, and in others since, the metaphor of a tightrope walker has helped explain the complex nature of risk. Here’s how it goes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Nau1hMFC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://corgibytes.com/images/blog/Tightrope/walking-on-a-tight-rope.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Nau1hMFC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://corgibytes.com/images/blog/Tightrope/walking-on-a-tight-rope.jpg" alt="Image of Tightrope Walker"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imagine someone learning to walk a tightrope for the first time. The rope is kept low to the ground. This significantly reduces the risk of falling. The person on the rope simply puts a foot on the ground to regain their balance and keeps moving along the rope. They keep going back and forth and, eventually, they don’t need to put their foot down anymore. So, they feel more comfortable with the idea of raising the rope higher and higher. They know this rope really well by now. They can travel back and forth very quickly, and the few times that they do start to fall, they are able to catch themselves very quickly. Then one day someone who hasn’t watched this progression shows up and exclaims, “Where is your safety net!? You’re going to get yourself killed!”&lt;/p&gt;

&lt;p&gt;I think this is similar to what happens to new teams that build a project from scratch. Early on in the project, the most pressing thing on the team’s collective mind is to ship the next release, which, in the context of the metaphor, can be thought of as getting to the other side of the tightrope. It’s okay if the team stumbles along the way. The project is very young and the risks are very low. They are able to recover quickly, learn from each mistake and keep going. They keep pushing out releases all the while amassing a larger system with more users, more features, more revenue, and more risk.&lt;/p&gt;

&lt;p&gt;The team has been working without any safety nets. No project documentation to describe how to set up a development environment. No description of how to deploy the application to production. No automated test suite. No formal manual test plan.&lt;/p&gt;

&lt;p&gt;Over time, someone on the team may have asked, “Why is there no safety net?” Perhaps it was the newest team member wondering why it was so hard to get started on the project. Or maybe it was one of the more junior team members who discovered a blog post about Test Driven Development. Or, maybe it was a tech lead who keeps hearing about DevOps from friends on other projects.&lt;/p&gt;

&lt;p&gt;Regardless of who asks the question, the answer is always the same; “We don’t have time to stop and build a safety net. We have to hurry up and get to the other side.” The team is feeling so much pressure to get their next release out the door, they feel they don’t have the time to slow down and build some safety into their process.&lt;/p&gt;

&lt;p&gt;I find that less technical team members rarely understand why the team wants to slow down for a little bit. They don’t effectively understand the risks that the team is trying to address. So, they pressure the team to just go back to doing things the way they were doing them. My hope is that this metaphor can help those who are trying to avert disaster while also helping explain how reasonable team members could work for so long with a net to catch their inevitable fall.&lt;/p&gt;

&lt;p&gt;Do you have any similar metaphors that help you explain this situation? Have you heard anyone else use a good one? Please share them in the comments and let’s keep the conversation going.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(This article originally appeared on the &lt;a href="https://corgibytes.com/blog/"&gt;Corgibytes blog&lt;/a&gt;)&lt;/em&gt;&lt;br&gt;
&lt;em&gt;(Header photo credit: ©zhukovvvlad – stock.adobe.com)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>metaphor</category>
      <category>devtips</category>
      <category>teamcommunication</category>
    </item>
    <item>
      <title>Embracing the Red Bar: Safely Refactoring Tests</title>
      <dc:creator>M. Scott Ford</dc:creator>
      <pubDate>Mon, 05 Dec 2016 22:18:56 +0000</pubDate>
      <link>https://dev.to/corgibytes/embracing-the-red-bar-safely-refactoring-tests</link>
      <guid>https://dev.to/corgibytes/embracing-the-red-bar-safely-refactoring-tests</guid>
      <description>&lt;p&gt;Do you ever refactor your test code? If not, I hope you consider making this part of your normal practice. Test code is still code and should adhere to the same high standards as the code that's running directly in production.&lt;/p&gt;

&lt;p&gt;As important as it is, refactoring your test code is actually a little risky. It's very likely that you could turn a perfectly valid test into one that always passes, regardless of whether or not the code that it covers is correct. Let's explore a technique for protecting against that possibility.&lt;/p&gt;

&lt;p&gt;But before I dive into the nitty-gritty, let me tell you where I discovered this technique and why I feel it should be part of everyone's refactoring practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Backstory
&lt;/h2&gt;

&lt;p&gt;I first read about "Refactoring Against the Red Bar" years ago while subscribed to a blog that was published by Michael Feathers. The article is &lt;a href="http://butunclebob.com/ArticleS.MichaelFeathers.RefactoringAgainstTheRedBar"&gt;still available&lt;/a&gt;, which is good, because it turns out that Michael Feathers isn't the originator of this idea either. He discovered it while talking with Elizabeth Keogh at the XP2005 conference, and his article points his readers to an article that &lt;a href="http://sirenian.livejournal.com/21808.html"&gt;she wrote about the technique&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'm often guilty of assuming that because I've read something once, that everyone else already knows about it. And that happens with this technique as well. I was at the first &lt;a href="http://www.mobprogrammingconference.com/"&gt;Mob Programming conference held by Agile New England in Cambridge, MA&lt;/a&gt;, and I was participating in a mob where one of the members suggested refactoring the tests. I mentioned the risk of invalidating the tests by doing that and that we should refactor against the red bar to defend against it. The initial response was a mixture of blank stares and confused looks. Once I described the technique and demonstrated its merits by navigating the mob, people were very excited, and several asked why they'd never encountered the technique before. I mentioned its origin, and I was encouraged by the rest of the mob to promote the idea further.&lt;/p&gt;

&lt;p&gt;That lead to both this article and a talk that I'll be presenting at &lt;a href="http://agiledc.org/2016-schedule/"&gt;Agile DC 2016&lt;/a&gt;. And, that's also why I'm rehashing someone else's idea: it's a really good one, and more people need to hear about it. A big thanks to Elizabeth and Michael for their earlier work on this technique.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Makes TDD Work So Well?
&lt;/h2&gt;

&lt;p&gt;The short answer is that when you strictly follow the &lt;a href="http://martinfowler.com/bliki/TestDrivenDevelopment.html"&gt;TDD steps&lt;/a&gt;, you're guaranteed that your tests will fail if the implementation breaks. And that's the bedrock that makes it so safe to continue refactoring your code.&lt;/p&gt;

&lt;p&gt;In case that's not super clear:&lt;/p&gt;

&lt;p&gt;There are three simple steps to TDD which we continue to repeat until our application does everything that we want it to do.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Write a failing test&lt;/li&gt;
&lt;li&gt;Write the &lt;em&gt;simplest production code possible&lt;/em&gt; that will make it pass&lt;/li&gt;
&lt;li&gt;Refactor production code to make the implementation clean&lt;/li&gt;
&lt;li&gt;Do we need more tests? If 'yes' then start back at 1, if 'no' then we're done&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I kind of lied about there being only 3 steps. There's an important bit that the typical TDD process description glosses over. What often gets left out is a check step that I've included above as step number four.&lt;/p&gt;

&lt;p&gt;I find that to be a very important addition to the process. If you don't know that step is coming, you sometimes try to violate the most important clause of step 2: &lt;em&gt;the simplest production code possible&lt;/em&gt;. And I think this is worth demonstrating with a simple example.&lt;/p&gt;

&lt;h3&gt;
  
  
  TDD example: &lt;code&gt;Calculator.Add()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;My favorite kata to use to demonstrate this concept is building a simple calculator using TDD and starting with the addition function. Although, I'm using &lt;code&gt;ruby&lt;/code&gt; for the code samples, please remember that this technique is not language specific. I'll intentionally avoid any &lt;code&gt;ruby&lt;/code&gt; features that might not read well for those less familiar with the language.&lt;/p&gt;

&lt;p&gt;Here's what our first failing test might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'additon'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;specify&lt;/span&gt; &lt;span class="s1"&gt;'adding two numbers that result in 4'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;calculator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, what would be the simplest way to make that test pass? How about this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reaction I often hear at this point is: "But that's not complete. It's not going to work for 2+5!" That's when I remind people about the implicit step 4 that I outlined above: &lt;em&gt;Do we need more tests?&lt;/em&gt; It sounds like the answer is a resounding yes. At least if we want this calculator to be able to do more that just claim that any two numbers result in 4 when added together.&lt;/p&gt;

&lt;p&gt;Here's what the tests might look like now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'additon'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;specify&lt;/span&gt; &lt;span class="s1"&gt;'adding two numbers that result in 4'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;calculator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;specify&lt;/span&gt; &lt;span class="s1"&gt;'adding two numbers that result in 5'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;calculator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now we have a failing test which confirms the objection to the original implementation: just returning 4 isn't good enough.&lt;/p&gt;

&lt;p&gt;So what's the easiest way to make &lt;em&gt;just the new test&lt;/em&gt; pass? Well, that would be to return 5.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that will cause our new test to pass. But we've got a problem. Our previous test is now failing.&lt;/p&gt;

&lt;p&gt;So what's the easiest way to make them both pass? That would be to actually do the work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we have two tests that are working together to force our implementation to work the way we want it to. And it's by only having both tests that we're able to &lt;em&gt;safely&lt;/em&gt; refactor.&lt;/p&gt;

&lt;p&gt;That's how TDD is able to guarantee that our test suite is a complete description of our production code. But that guarantee gets invalidated as soon as we just simply refactor our test code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Is It Dangerous to Blindly Refactor Test Code?
&lt;/h2&gt;

&lt;p&gt;Strictly speaking refactoring should never result in a change in behavior. That would violate the definition of refactoring: &lt;a href="http://refactoring.com"&gt;&lt;em&gt;changing an implementation without changing its behavior&lt;/em&gt;&lt;/a&gt;. But mistakes sometimes happen, especially if you're working without an automated refactoring tool and you're applying the refactoring by hand. And keep in mind that a bug in your refactoring tool isn't likely, but &lt;a href="http://jbazuzicode.blogspot.com/2016/05/extract-method-introduces-bug-in-this.html"&gt;it's not impossible&lt;/a&gt;, either.&lt;/p&gt;

&lt;p&gt;Let's look at a hypothetical refactoring scenario where we attempt to remove some duplication in our test suite.&lt;/p&gt;

&lt;p&gt;We'll start with the test suite that we finished with earlier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'additon'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;specify&lt;/span&gt; &lt;span class="s1"&gt;'adding two numbers that result in 4'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;calculator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;specify&lt;/span&gt; &lt;span class="s1"&gt;'adding two numbers that result in 5'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;calculator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's refactor this to remove some of the duplication:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'additon'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;left: &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;right: &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;result: &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;left: &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;right: &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;result: &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;specify&lt;/span&gt; &lt;span class="s2"&gt;"adding two numbers that result in &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:result&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;calculator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
      &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:left&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:right&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we were to run that, it'll pass. But did you catch the mistake that was made during the refactoring? The assertion has been removed by accident. The code should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'additon'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;left: &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;right: &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;result: &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;left: &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;right: &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;result: &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;specify&lt;/span&gt; &lt;span class="s2"&gt;"adding two numbers that result in &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:result&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;calculator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:left&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:right&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:result&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How Do We Defend Against Breaking Our Tests When We Refactor Them?
&lt;/h2&gt;

&lt;p&gt;When we refactor our production code, it's the safety provided by our test suite that lets us safely refactor our production code. So how can we get that same safety when we need to refactor our test code? To do that, we have to break our production code in a way that will cause the tests we want to refactor to fail. If they don't fail, then we've got a problem. Either we didn't break the production code correctly, or our tests didn't work in the first place. If we can't force our tests to fail, then they're not doing us any good and that would need to be addressed before continuing any further.&lt;/p&gt;

&lt;p&gt;Once those tests fail correctly, we can refactor them. And after every tiny refactoring we do, the tests should &lt;em&gt;still fail&lt;/em&gt;. If any of those tests start to pass, then we've made a mistake in our refactoring somewhere. That's what would have happened with the mistake that was introduced in the example above.&lt;/p&gt;

&lt;p&gt;After we're done refactoring our tests, we can revert the changes we made to break our production code, and that should cause all of our refactored tests to start passing. If any of our tests still fail, then we've also made a mistake in our refactoring. But this time, instead of creating a test that always passes, we've created one that always fails.&lt;/p&gt;

&lt;p&gt;Before we walk through a couple of examples, let's simplify the workflow a little bit for review.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Break our production code to cause our test to fail&lt;/li&gt;
&lt;li&gt;Refactor our test code&lt;/li&gt;
&lt;li&gt;Ensure that our tests still fail&lt;/li&gt;
&lt;li&gt;Revert changes to production code&lt;/li&gt;
&lt;li&gt;Verify that tests once again pass&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  A red bar refactoring example
&lt;/h3&gt;

&lt;p&gt;Let's start with the example code that we created in the TDD example above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'additon'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;specify&lt;/span&gt; &lt;span class="s1"&gt;'adding two numbers that result in 4'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;calculator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;specify&lt;/span&gt; &lt;span class="s1"&gt;'adding two numbers that result in 5'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;calculator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here's the production code that makes those tests pass:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Time to refactor our tests. There's a little bit of duplication in there. Here's what I see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;Calculator&lt;/code&gt; class is instantiated by every test&lt;/li&gt;
&lt;li&gt;Each test just calls &lt;code&gt;add&lt;/code&gt; with different parameters and expects a different result&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's tackle just the first one while refactoring against the red bar.&lt;/p&gt;

&lt;p&gt;The first step is to force the tests we're changing to fail by intentionally breaking the production code. This should do that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We verify that by running our test suite and making sure that the tests that we want to change are failing. It's okay if more tests are failing, too. But it's super important that all of the tests that you intend to refactor are failing. If the tests that you want to refactor are not failing, then you need to keep changing your production code until they do. And if you're unable to make those tests fail, then you need to jump down to the "What if something goes wrong?" section.&lt;/p&gt;

&lt;p&gt;Now, we can safely extract the instantiation of the &lt;code&gt;Calculator&lt;/code&gt; class, which might look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'additon'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:calculator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;specify&lt;/span&gt; &lt;span class="s1"&gt;'adding two numbers that result in 4'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;specify&lt;/span&gt; &lt;span class="s1"&gt;'adding two numbers that result in 5'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the creation logic for building a proper &lt;code&gt;Calculator&lt;/code&gt; instance has been factored out into one spot.&lt;/p&gt;

&lt;p&gt;We need to re-run our test suite to make sure that we didn't make a mistake. Remember, though, we're actually expecting the tests to fail.&lt;/p&gt;

&lt;p&gt;In this case, our tests still fail in the way we expected them to. So we can now proceed by restoring the original implementation of our production code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we run our test suite to make sure that everything is passing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What If Something Goes Wrong?
&lt;/h2&gt;

&lt;p&gt;There are a few points during the red bar refactoring process where you might encounter a surprise. I mentioned these earlier, but I'm reiterating them for easy reference.&lt;/p&gt;

&lt;h3&gt;
  
  
  I'm changing my production code, but I can't make my tests fail!
&lt;/h3&gt;

&lt;p&gt;If you encounter this issue, then you already have a test that's producing a false positive. You've got a couple of options at this point.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;em&gt;Delete the test and treat the production code as untested, legacy code&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A test that always passes is providing just as much value as one that's always failing. At best, reading it will give you an indication about the test authors' original intent, but it's essentially documentation that's drifted out of sync with your implementation. Deleting the test is a perfectly acceptable option in this scenario. Your test suite will be no weaker without the false positive test than it was. Now that you've discovered the false positive, it's best to go ahead and write something that covers the production code the test was intending to run.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;em&gt;Review change history and try to restore a working version of the test&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Take a peek at the tests history in your change control system if you have that available. If you discover that you're looking at the first version of the test that was committed, then this test has &lt;em&gt;always&lt;/em&gt; been a false positive, and you'll need to follow the previous option instead. If there is history for the test that you're working on, then attempt to revert those changes while your production code is still modified to simulate a failure. If the older version of the test fails, then you can revert your production code modifications, and see if the test passes. If so, then you've found a valid version of the test. If that version still has some refactoring that you'd like to do, then you can go ahead and start the process over again.&lt;/p&gt;

&lt;h3&gt;
  
  
  I refactored my test, and the production code is broken, but now the test is passing!
&lt;/h3&gt;

&lt;p&gt;In this scenario, you've broken your test. The easiest way to see this is to remove a critical assertion that would otherwise force the test to fail, or perhaps a subtle change has been made to the way the test setup process was running. Revert the changes that you've made to your test and try again.&lt;/p&gt;

&lt;h3&gt;
  
  
  I've successfully refactored my test, and I've reverted my changes to the production code, but now the test is still failing!
&lt;/h3&gt;

&lt;p&gt;Take a close look at the reason that the test is failing. I've seen this scenario happen most often because of an invalid type reference or syntax error. Since you're refactoring against the red bar, those things can sometimes slip into your test as you're refactoring. In this case, fixing that error should make your tests pass again, but you'll want to repeat your production code changes to double-check that you haven't accidentally introduced a false positive while trying to get the test to pass again.&lt;/p&gt;

&lt;p&gt;It's also possible that you've added an assertion that the production code can't make pass or the test setup is different than it used to be, and the logic that used to be running no longer applies. If this is the case, then you'll need to revert the changes that you've made to your test and start over.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Have We Learned?
&lt;/h2&gt;

&lt;p&gt;Following this simple technique is a great way to safely ensure that your tests suite still correctly tests your production code while you're refactoring your test code. This is a practice that I follow anytime that I modify a test, and I've been doing so successfully for several years now. It's practically second nature at this point.&lt;/p&gt;

&lt;p&gt;I'd love to hear from others who are using this technique, and I'd also enjoy hearing from people who are starting to work this technique into their practice. Are there any challenges that you're encountering? Figured anything out that others should know about? Let me know!&lt;/p&gt;

</description>
      <category>refactoring</category>
      <category>tdd</category>
      <category>techniques</category>
    </item>
  </channel>
</rss>
