Search code examples
phpunit-testingtddfunctional-testing

Which tests should get written first when following TDD for building a web app from the ground up?


My basic question boils down to: when starting a fresh project, should I start by writing a functional test for a feature and then writing unit tests as I try to get the functional test to pass? Or should I start by thinking about a smaller component of that feature and then writing a unit test for that (and then later a functional test for the feature)?

For example, say I want the ability to Sign In to my web app. Do I first write a functional test laying out the steps that occur during the Sign In process (User is on Sign In page, User fills out required fields, User clicks Sign In button, etc.)? Or is it preferred to write unit tests for, say, the validation rules for the form fields first? I've been doing the former and now I'm questioning whether my workflow is flawed and whether there's some better approach I'm not seeing.

As an aside, I have a feeling this might get flagged for "calling for an opinion", but I've tried looking and asking around elsewhere and haven't been able to find a clear answer so far. Thanks in advance for any responses.


Solution

  • Your first suggested approach: writing a functional test for the overall behavior, then writing unit tests to drive the little bits of functionality as you go, is my preference.

    Here's why. That first test describes the new behavior you want from the system. When it's passing, you can move on to the next feature. Until it's passing, you need to be adding functionality. So it's a good roadmap. As you add each new bit of functionality, you do so by first writing a failing test unit test which tests only that new bit. So it's a good, very specific test; it runs quickly and without dependence on other elements. That drives the development of that next bit, and the functional test keeps you on track, writing only bits that are needed for the new functionality. Your unit test focuses your attention on the immediate matter at hand; your previous, passing, unit tests let you know when you've broken existing behavior, and your functional test lets you know when you're done with the feature.