Paul Scarrone’s Post

View profile for Paul Scarrone, graphic

Practicing Crafter | DevEx Cheerleader | Master Dungeoneer

Alright, this is going to be a short discourse on TDD, Test-Driven Development. *Yawn*, but seriously, it's not as complex as it sounds. So here is an anecdote from chatting with another developer recently. The question was, "How do you do testing?" I am no genius and have no real idea what I am building before I build it. But I do think about the interface a lot, and one of the better ways to think about writing tests is to consider the normal and corner cases around the interface of what you build. The hard part is, let's all say it together, **NAMING**. When you write your test, you are working on something a priori. Or it feels like that. You are forcing yourself to know about your implementation before you have completed the deduction of what your implementation does. Don't sweat it, friend! Naming is actually easy. The Terms we define for our code are the easiest to change. Their signatures are less so, but there is a hack. Just make them generic, don't worry about it, and keep it simple. Start by assuming each module has a single entry point, just like those "Hello World" methods you wrote when you started coding. Name your entry point "call," "do," or "execute," and then decide what it will return. If it's going to be a gentle side effect like logging or mutating the database, think of it in terms of CQRS! Commands, Queries and procedural modules Orchestrators. It contains a sequence of Commands and Queries to create a "feature." So you should test each Command, Query, and Orchestrator at its entry point (call, do, etc.). That's my decision framework, and then we do the old-fashioned Red, Green, Refactor flow as written about by our friend Martin Fowler. https://lnkd.in/gNkqWPqR Next, I create a pyramid of tests, starting with the integration test—usually one at the beginning of the feature request. So, if you are working on a web app's back end, this might be the controller. On the front end, this might be the page's component container. This is likely also an Orchestrator, but that's not a guarantee. What this top-down approach offers you is a way to think about your work in terms of a contract. A contract is a simple communication agreement between producer and consumer. These happen each time we all use a method, dispatch an action, or make a web request. This is the best place to verify your feature works, and since it is unassuming about the how of your work, only what it accepts and produces. We have made this incredibly easy to reason about. Now, go build and refine your test. When your code becomes reasonably complex, it's time to write new modules and tests. Repeat this pattern for each module you create. Best of all you have those original tests to make sure you don't break any of your hard fought assumptions as your refactor. Boom you be testin'!

bliki: Test Driven Development

bliki: Test Driven Development

martinfowler.com

Michael Cain

Senior Software Engineer (Ruby on Rails | React)

9mo

I'm inclined to agree it's hard to freestyle tests without code. That said, I have gotten a lot of miles out of spec'ing out integration tests (for web development) with the stakeholders so everyone is aligned on what exactly we're building. I have found them to be valuable guides vis-a-vis data contracts, exception handling, etc.

Like
Reply

To view or add a comment, sign in

Explore topics