DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
Building Scalable Real-Time Apps with AstraDB and Vaadin
Register Now

Trending

  • Redefining DevOps: The Transformative Power of Containerization
  • Using Render Log Streams to Log to Papertrail
  • Building and Deploying Microservices With Spring Boot and Docker
  • Demystifying SPF Record Limitations

Trending

  • Redefining DevOps: The Transformative Power of Containerization
  • Using Render Log Streams to Log to Papertrail
  • Building and Deploying Microservices With Spring Boot and Docker
  • Demystifying SPF Record Limitations
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Testing, Tools, and Frameworks
  4. TDD and Code Quality

TDD and Code Quality

TDD can make your code better, but there’s a ton of ways to do it wrong. To take full advantage of it, you need to understand those pitfalls and learn how to avoid them.

Grzegorz Ziemoński user avatar by
Grzegorz Ziemoński
·
Feb. 06, 17 · Opinion
Like (11)
Save
Tweet
Share
10.35K Views

Join the DZone community and get the full member experience.

Join For Free

Every time I see an article claiming that TDD improves code quality, a part of me cries. It’s not that I don’t think it can be true. It’s because it’s not necessarily true, and those articles rarely bother to provide a satisfying explanation. Here’s my try.

TDD and Better Design

There’s a lot of talking about TDD making your codebase more modular and less coupled, and making the designs you produce being better in general. I think this might be true, mainly because of two factors: the act of design and characteristics of testable code.

The Act of Design

A lot of people (judging mostly by comments sections on dev portals) tend to skip the design part of software development and jump straight into coding. They try to get a rough implementation working, then refactor it a little and write the tests in the end. While this approach can succeed, it gives a lot of attention to just making it work and little to no attention to representing end-user or domain models that lie at the heart of object orientation.

In my understanding of TDD, before I even sit down to start coding I need to know (at least) the starting point. Especially when going the inside-out way, I need to first think of the objects and their behavior necessary to solve the given problem. Given I’m a homo-sapiens and not a code-o-sapiens, I will get those objects from the end-user or someone’s domain knowledge and thus ensure that the code does not diverge from the root of requirements. This is what I called “the act of design.”

How Could It Go Wrong?

Well, it happens that even when doing TDD people forget the design or do it without due diligence. They just go and test drive the first idea that comes to their mind and then bend it until it works for all test cases. Such approach, although not meant by TDD pioneers, happens and can be actually detrimental to the design produced.

Avoiding the Pitfalls

Pay attention to the design process. Before you start coding, make sure you understand the underlying domain and/or technical concepts. If you find yourself implementing an “awkward” design, don’t be afraid to take a step back and figure out what’s missing. TDD by Example has some good insights into how flexible we should be with deleting the code and trying different approaches during TDD.

Characteristics of Testable Code

When you’re focused on making it work and not thinking about the test, there’s a chance that the code that you’ll produce will be to some degree untestable. In the best case, you’ll notice the flaw and correct it; in the bad case, you’ll hack here and there to make the test pass and in the worst case, you won’t test it at all. When doing TDD, you start from a test, from your dream vision of how the test would look like. Again, given you’re a homo-sapiens, you won’t make things worse unless you’re forced to and thus the code produced will be testable.

Testability itself is by most considered a sign of good design. However, it often happens to bring you some other design benefits “in the package.” I think the most popular design benefit associated with TDD is lower coupling. In my experience, this might actually be true — code that can be tested without excessive mocking and complex object initialization (most likely) isn’t highly coupled to the rest of the system.

How Could It Go Wrong?

Well, I’ve seen a lot of people that just “mock all the things” and don’t care about the size of the test setup (you can always create a base class or an util), and the testability benefit is gone. Obviously, other characteristics of code written like this won’t be perfect either.

Avoiding the Pitfalls

Treat testability seriously. Do the minimum amount of setup and mocking required to test a functionality and strive not to change it during actual implementation. Follow other good unit testing practices.

TDD and Simpler Solutions

Some say that TDD leads to simpler solutions than other approaches. This is because in TDD, you should never write more production code than it is necessary to pass the currently failing unit test. This has profound implications. You no longer think about the whole implementation upfront. You let the tests guide you. It might happen that complex algorithms, extra methods, classes, or other constructs that you initially thought were necessary weren’t actually needed. If test case by test case you arrived at a solution without those, then you have saved yourself some accidental complexity — good for you!

How Could It Go Wrong?

Supposedly you did no design or lousy design up front and you’re going inside out. Then, there’s no way that TDD saves you from unnecessary classes and such. Another common scenario is to write a single test or even all the author can think off, and then spin off the entire implementation as you imagined it. Simplicity? Doubt it.

Avoiding the Pitfalls

Again, pay attention to the design. Don’t break the TDD rules — have at most one failing test at a time and produce just enough implementation to make it work. At every point of the process, do the simplest thing that could possibly work. Switch between the modes of TDD to adjust the steps you’re making to the complexity of the problem you’re dealing with.

TDD and Better Tests

The last claim that I wanted to discuss is how TDD can make your tests better. Better in this context means mostly that the tests are less coupled to the internals of production code. The reason for this would be that the production code did not exist at the time of writing the test. From my own experience, I can say that this can work very well. At the same time…

How Could It Go Wrong?

Well, in most code bases that I’ve seen, it actually went wrong. People are so used to mocking everything around that they often develop their mock-TDD approach. Like, you write a failing unit test that the code will hit the mock and implement it. Then, they add another one for another mock and so on. In the end, when all mocks are in place and verified, they check that the tested method actually returns the correct result. I would not consider such a test loosely coupled to the production code.

Avoiding the Pitfalls

Take the time to understand the differences between different types of test doubles and between state and interaction testing. Always focus on the outcomes of the functionality and not on the details of its implementation. Consider driving the functionality with a more coarse-grained test if you feel that unit testing would barely test that the compiler works and you’ve set up all mocks correctly.

Conclusion

TDD can make your code better, but there’s a ton of ways to do it wrong (trust me; I listed only a few). Take your time to understand the underlying dynamics and improving your skills. And when it comes to improvement, don’t just read and talk — practice, practice, practice!

code style unit test Design Software development

Published at DZone with permission of Grzegorz Ziemoński, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Trending

  • Redefining DevOps: The Transformative Power of Containerization
  • Using Render Log Streams to Log to Papertrail
  • Building and Deploying Microservices With Spring Boot and Docker
  • Demystifying SPF Record Limitations

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com

Let's be friends: