Arlo | Refactoring with Depth

Share this post
Making tests your PO can read
digdeeproots.substack.com

Making tests your PO can read

Are your tests "glanceable?"

Dig Deep Roots, LLC
Jun 14
2
2
Share this post
Making tests your PO can read
digdeeproots.substack.com

Ready for another whiskey moment with Arlo? This month he’s talking about why acceptance tests should not be separate from unit tests. The blog will tell you how!

Subscribe to YouTube Whiskey Talks

If you’d like to chat with Arlo and fellow menders, register for our next virtual Ask Me Anything on August 25 or join our Code by Refactoring slack channel.

Slack Channel

Are you tired of stories bouncing back when you get to acceptance testing? Are you tired of “what about [insert unmentioned request here]?” Or, you are already using acceptance testing tool like Cucumber but tests breaks easily, or slow, or you spend a lot of time writing fixtures and adaptors? That’s not even mentioning tests not supporting refactoring.

Unit tests are easy to maintain, fast to run, quick to write, and don’t break. They have great traits! However, they are typically written using developer language and representing all the details. The PO cares deeply about 5% of it, and usually can’t sort through it. This is why acceptance tests were created; the 5%. But they don’t match the design of the code, so they run slowly, break frequently, and require developers to write adaptors.

We’re going to ignore the default solution because it’s cumbersome, error prone, duplicative, and impedes communication. We know that the real (#impossible) solution is making each test both a good unit test and a good acceptance test. Let’s discuss how we can do that.

Scenario

A recent client had a system covered by decent acceptance tests, but they were not good unit tests. They provided reasonable protection. However, they caused a set of a problems while not providing other benefits that a good unit test suite would provide. Here is one example test.

Sample “unit” test that is fragile and hard to read.

Let’s walk through the series of improvements that we applied.

Minor modifications included to protect client IP.

Extraction | Hide irrelevant information

The test above contained a lot of information that is required to satisfy the computer’s ability to execute the system, but is not relevant to the reader or the purpose of the test.

Lines 5-26 is now represented in lines 6-7, which is what’s left after we extracted the irrelevant information.

Test after we hide irrelevant information

Since we need the information for the computer, we extracted it a couple of helper methods.

Extraction | Use custom and fluent assertions

Now the biggest wall of text left in the test is the block of assertions in lines 13-20.

It’s hard to tell what the test is actually attempting to verify. It is sufficient for a computer, but a human reader gets no value from this. We need clear intentions. Talk to your PO to understand the intention of the test! Then you can extract a custom assertion to make your intention clear, as we did on lines 12-14.

The assertions are now so clear that we don’t need a comment introducing the block.

Intent-revealing custom assertions make the test’s purpose obvious

So now we have clear intentions, and, since we simply extracted them, the computer still has it’s definitions to verify … thankfully in a place that doesn’t distract the human reader.

Extraction | Use arbitrary constants

Each of the places boxed in red (below) used to have concrete value. For example, Arbitrary.DateTime() had May 15. While the computer needs to verify against a specific data value, such as May 15, the concrete value of May 15 is actually irrelevant to a human’s understanding. For this test, the only things humans care about is that the sighting had a date (line 6), and that the report’s filter range went from before that date to after that date (lines 12-13).

Arbitrary constants replace overly-specific values to make intention clear

Rename | Have a clear test subject

The test at it’s current state (above) is now clear about purpose and context, but it’s unclear what part of the code we’re actually trying to test, and what part is just required context. So we identify the object or method we are trying to test. In this case, it is the variable on line 8. We name it testSubject to make it obvious.

Each test has exactly one test subject. Everything else is just support.

Apply Design Pattern | Use builders for starting state

Now our test is looking pretty good. Stepping back a minute though, we have a lot of test helper code that is setting up the context. Test helpers like this indicate a design flaw in our production code. It is hard to construct and working with it requires many extraneous details. Talk to your PO to figure out which construction details are essential customer information, and which ones are noise.

Diving in for a second, the solution we chose for this case is to use the builder pattern. Lines 4-6 call the test helper method that we want to simplify. We extracted a builder from those helper methods and in-lined it back to this test. That created the new lines 5-8.

Replacing data setup helper methods with builders makes intention clear and hides construction complexity

Rename | Name test for PO discovery

The current test is one detail among thousands. We need to determine if a PO cares about this particular detail, and if so, when. Most tests will be computer level details that the PO will never care about. Hide these in a developer only section.

Lift the others to a namespace and call it spec. Then organize your spec namespace into sub-namespaces by epics, features, and stories that the PO cares about. Do this with your PO!

Summary

This is a great opportunity to get on a similar technical page with your PO. Forward this to them! Even better, do an example test and talk to them about it. Additionally, if you’d like your PO to welcome refactoring, have them register for our June class that addresses the business value of refactoring!


Become an Agile Developer

Master Extreme Programming practices like TDD and refactoring while becoming a Certified Scrum Developer in one of David Bernstein's online classes:

  • June 20 – 24, 2022 (full-days)— Scrum Developer Certification (SDC)

  • June 28 – July 1, 2022 (half-days) — Certified Scrum Developer (CSD)

  • July 13 – 14, 2022 (full-days) — Certified Scrum Developer (CSD)

Sign up for one of David's classes!


Deep Roots Events

June 23 | Business Value of Refactoring

Would you like your PO to be on the same refactoring page as you and your team? Have your PO register for our June class that addresses the business value of refactoring. Give them a 50% discount code: “newsletter”.

July 11 - 22 | Refactoring Well with Naming as a Process (NaaP)

Ready to up-level your refactoring skills with Arlo? Join our July workshop! Early bird pricing available through June 30. Limited seating.

Missed CRAFTcon?

Marian, learner designer and Arlo-brain-translator for Deep Roots, refactored a legal contract using Naming as a Process (NaaP). She showed how to refactor for readability in a safe way. Check out the slide deck and other resources!

2
Share this post
Making tests your PO can read
digdeeproots.substack.com
2 Comments

Create your profile

0 subscriptions will be displayed on your profile (edit)

Skip for now

Only paid subscribers can comment on this post

Already a paid subscriber? Sign in

Check your email

For your security, we need to re-authenticate you.

Click the link we sent to , or click here to sign in.

Kevin Rutherford
Writes Habitable Code Jul 14Liked by Dig Deep Roots, LLC

I love this approach Arlo -- so much more productive than using an extra layer of indirection such as Cucumber.

I also really liked your use of an Arbitrary namespace to make it clear what's inessential gubbins just to make the test compile.

And finally I like your use of images for the code snippets, instead of Substack's terrible code blocks. I'm definitely going to steal that idea 🙂

Expand full comment
ReplyCollapse
author
Dig Deep Roots, LLC
Jul 17Author

Awesome and thanks so much for this feedback! Agreed that Substack's code blocks are pretty terrible - glad to inspire :)

Expand full comment
ReplyCollapse
TopNewCommunity

No posts

Ready for more?

© 2022 Dig Deep Roots, LLC
Privacy ∙ Terms ∙ Collection notice
Publish on Substack Get the app
Substack is the home for great writing