{"id":915,"date":"2025-10-22T09:00:00","date_gmt":"2025-10-21T22:00:00","guid":{"rendered":"https:\/\/jm.armijo.au\/dev\/?p=915"},"modified":"2025-10-21T19:32:45","modified_gmt":"2025-10-21T08:32:45","slug":"refactoring-safely-with-tests","status":"publish","type":"post","link":"https:\/\/jm.armijo.au\/dev\/blog\/2025\/10\/22\/refactoring-safely-with-tests\/","title":{"rendered":"Refactoring Safely With Tests"},"content":{"rendered":"\n<p>I&#8217;ve recently been working on adding a new feature that, for many reasons, requires a great deal of refactoring to our existing codebase.<\/p>\n\n\n\n<p>I&#8217;ve done code refactoring for most of my career, and I&#8217;ll do it many more times until the day I retire. When I started, though, things were a bit different from what they are now. I didn&#8217;t know about the concept of unit testing, and the companies I worked for were not interested in or didn&#8217;t know about this concept either. As a result, I relied on manual verification tests to confirm that everything was fine. Many times they were not, and I would just find my bugs when they were already in production.<\/p>\n\n\n\n<p>The introduction of automated testing, particularly unit and integration tests, was a game changer. Many time, when I write a new feature, it takes me way more time to write automated tests than to write the actual code for the feature! But despite this, I keep writing them every time because I know how useful they are.<\/p>\n\n\n\n<p>When we already have automated tests for a feature, doing a refactor is usually as simple as just changing the code, and running the tests. That only works if we already have a good test coverage though.<\/p>\n\n\n\n<p>The area that I am touching has an uneven test coverage, so, before refactoring the code, I need to write the missing tests so I can validate how the feature works. A few times I have even found bugs in production code by doing this. Only once I have improved the test coverage I move to changing the code.<\/p>\n\n\n\n<p>It&#8217;s important to remember that automated tests are not perfect. They cannot test every scenario, and we&#8217;ll likely forget to add some (I&#8217;ve been guilty of this a few times during this refactor). As Dijkstra said [1]:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Program testing can be used to show the presence of bugs, but never to show their absence!<\/p>\n<\/blockquote>\n\n\n\n<p>But even considering that, aiming for a high coverage that follows a good test design gives us way more confidence than having no tests at all.<\/p>\n\n\n\n<p>Happy coding!<br>Jos\u00e9 Miguel<\/p>\n\n\n\n<p><em>Share if you find this content useful, and Follow me on&nbsp;<a href=\"http:\/\/www.linkedin.com\/comm\/mynetwork\/discovery-see-all?usecase=PEOPLE_FOLLOWS&amp;followMember=jmarmijo\">LinkedIn<\/a>&nbsp;to be notified of new articles.<\/em><\/p>\n\n\n\n<p>[1] <a href=\"https:\/\/www.cs.utexas.edu\/~EWD\/transcriptions\/EWD02xx\/EWD249\/EWD249.html\">Notes on Structured Programming, Prof. dr. Edsger W. Dijkstra<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve recently been working on adding a new feature that, for many reasons, requires a great deal of refactoring to our existing codebase. I&#8217;ve done code refactoring for most of my career, and I&#8217;ll do it many more times until the day I retire. When I started, though, things were a bit different from what [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":922,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-915","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/posts\/915","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/comments?post=915"}],"version-history":[{"count":8,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/posts\/915\/revisions"}],"predecessor-version":[{"id":926,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/posts\/915\/revisions\/926"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/media\/922"}],"wp:attachment":[{"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/media?parent=915"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/categories?post=915"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jm.armijo.au\/dev\/wp-json\/wp\/v2\/tags?post=915"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}