Search code examples
reactjsunit-testingtdd

How to apply TDD if one does not know how the code is supposed to work or be implemented?


First of all please do forgive me if my question is odd or its solution obvious. I have searched the internet for months for an appropriate reply and never found quite what I was looking for.

I have been practicing test driven development for over a year, always aiming to test behavior & not implementation.

Imagine the following scenario as a simple example, with a standard ReactJS app:

1. I want to create a 'photo-tagger', where a user clicks on an image & the app returns true if the click matches the coordinates of a specific person or object. Since I want to apply TDD, I am not supposed to write pseudocode and instead let my tests design the development.

2. I know that I'll probably have to play around with getBoundingClientRect, but I need actual practice to understand how this method works, because I've never used it before.

3. I am now in a situation where I am not allowed to write any code before writing a failing test first, but I have no idea what the test should consist of or how to validate my goal.

Browsing the internet, I've not seen many solutions to this, or perhaps I didn't understand how what I was reading related to my issue.

One post suggested to write the code first, then the test. I'd then commit the test first then the code manually, so the test appears to have been created first. This appears very hacky & dishonest to me.

Others suggested using TDD only in scenarios where you were sure of the testing approach, which seems to defeat the point of TDD.

I've come up with a couple of solutions myself but I'm not sure if they're appropriate in a work environment;

  • create a file called 'playground' separate from your project to experiment with stuff

  • create a branch called 'Experimenting with feature' and feel free to code without
    testing, then delete it when the code works, then test it and write it again in the main
    branch. Is this odd?

  • forget about TDD altogether for things I don't know how to code, write code then the
    test

  • write an empty test, have it fail at compilation time, write the code then come up with
    test contents later on

I'd appreciate any feedback on my ideas & especially your thoughts on the matter. I've been stuck in a loop of not daring to experiment with code out of fear it'd be inappropriate without writing a test first and being unable to write a test.


Solution

  • Your second suggestion is what I would recommend:

    create a branch called 'Experimenting with feature' and feel free to code without testing, then delete it when the code works, then test it and write it again in the main branch.

    In TDD circles this is called a "spike". That word is sometimes used in development with a slightly different meaning. But in a TDD sense a "spike" is code you write without tests to answer a question, such as "how does getBoundingClientRect work" or more generally "what could photo-tagging code look like?"

    If it feels strange to throw the code away and TDD it again, here are some reasons given in the article How to TDD the Unknown with a Spike Solution:

    • It frees you from any constraints to write clear code while you’re experimenting. Quick-and-dirty is the name of the game. Just hack.
    • It avoids creating production code not covered by unit tests. Once we have the answers we need from our spike, we can start the TDD cycle back in the real code, using what we learned.
    • It keeps you from writing tests that merely mimic the spiked code. As you build up tests and refactor, the production code may assume a radically different shape from the spike solution.