Bryan Says...

Rants, opinions, and other stuff I find interesting.

About that first test…

Yesterday, I was having a discussion with a young, bright, aspiring developer about code, and the subject of tests came up. In the Ruby community these days, the assumption is that everyone tests their apps, so our conversation evolved to the actual testing practice. I appreciate the many approaches to testing, so I started quizzing him about his process.

The conversation moved along nicely until I asked him, “Say you have a new Rails project. What is the first test that you write?” He described that he would use the Rails generators to create a model and then start describing the behaviors for his first model. While not trying to sound rude, I probed if that was really the first test he should write? By generating a model and describing its behaviors, he was subconsciously making a few serious assertions about his application. How do you know you’ll need a relational database? Why would you pick any model over any other? How does that model even fit inside of your applications ecosystem?

Now, with a genuine fear of sounding overly pedantic, I’ve had great internal debates about The First Test. This single test sets the tone for your initial development session. To avoid wasting too much time, what test do you write first?

Today, I’ll try to explain how I write the first test. Maybe, someone can find great errors in my ways, and enlighten me to a better way. Maybe I’ll learn that I’ve been wasting my time, and should move on to more important problems.

My process is pretty simple. In my opinion, the first test is not a unit test. Without a test, those units have no reasons to exist. I start off by writing a higher level functional test. In my parlance, a functional test does not necessarily equate to a Rails functional test. A functional test simply verifies the behavior between objects in a system. Also, a unit test can only describe the behavior of a single unit in isolation in one or more circumstances. So, what’s the first test that I write? My first test describes the simplest assumption of my system. If I was writing a blog, describing the process of creating a new post might be my first task. The first test would most likely have some sort of mock implementation of a post that would naively say it saved itself when asked. Next, after I assured that my process for creating the post was correct, I would then move to implement some type of object to encapsulate a Post. 

I believe this method allows me to describe the system without concerning myself with details of how it works. Is this crazy? What say you?

  • http://ngauthier.com Nick Gauthier

    My first test (or tests, as I usually write a couple up front) are integration tests. I visit the root of the page, and then I do the stuff I want a user to be able to do. Sign in and see their name and picture from facebook.

    Or the admin signs in and creates some objects, then a user signs in and browses them.

    Stuff that doesn’t actually hit any code that I’ll write, just hit the site with a browser. Then I dive into the code I need to make it pass.

    Usually I assume I’ll need rails. But I could have started with sinatra, or webrick!

  • http://iain.nl iain

    My first test is always trivial. I want to make sure that everything is working. So I start with 1.should eq 2 quickly followed by 1.should be 1, or a cucumber step that does visit root_path; page.should have_content("hello"). Now I know my app is running and I have a place to start. Then it’s of to the first feature, like you described. After the first couple of features, I remove the old ones that were just there to help me get started.

    I have been wanting to try out the technique for swapping out business objects with the user interface, like Gary Bernhardt and the Cucumber book show, but I haven’t done any new projects lately. Scrap that, I’m starting one right now in Rails 4. :)

  • http://jackcanty.com jackdanger

    I do not have a good answer when someone asks me this. If it’s a Rails app I’ll probably build a controller’s unit test first. If it’s a library or a non-CRUD app I’ll start  integration testing at the outermost edges of the stack. It’s slow, but those tests seem to be the most worthwhile. I don’t start with mocks but it’d probably be much faster if I did.

  • http://solnic.eu/ solnic

    I write acceptance test first. When I have a prototype ready that passes the test I start diving deeper and deeper into implementation details and when I have a good understanding of the problem I’m solving I start writing detailed unit tests. This is when my code becomes more stable and better designed. Quite often I end up replacing the prototypical code with a new implementation.

  • Jim Menard

    I think one problem with this approach is that it assumes that you can’t plan ahead, and that you’ve never learned anything from any other program you’ve written or that your experience isn’t relevant. To me, TDD means “question everything” which implies “assume nothing”. Well, intelligence is all about making assumptions based on past experience. Of course, assumptions can be wrong, but hopefully those are in the minority.

  • Lukecartner

    The first test I write is aling these lines as well.
    Once I know the driving business need, my first test is does it appear to meet that need.
    I say appear as what it actually does often is a much longer conversation.
    But if it does meet the need but doesn’t appear to my solution probably is too complex anyways.
    well if it appears to, but doesn’t, the question around why it doesn’t is usually one that needed to be asked regardless.

  • http://smartic.us bryanl

    You can only write code one line at a time. TDD means you drive development through tests. It is a design tool. You can definitely have an idea of where the design is going to go, but when you skip ahead and don’t work through one behavior at a time, you really aren’t doing TDD. 

  • http://smartic.us bryanl

    To be honest, I don’t know Gary Bernhardt or the Cucumber book prescribe. I should definitely spend some time investigating.

  • http://twitter.com/RyanTownsend Ryan Townsend

    I generally write my first tests before even creating the Rails project – I’ll work on as much in pure Ruby as possible. You could find that you’re better off creating a gem (or a few gems) to be used in your Rails app rather than lumping it all together in one monolithic codebase.

    I generally only create my Rails app once persistance is required, or integration between two isolated services (or gems).

    Using Rails to begin with is (in my opinion) one of those “serious assumptions”.

  • http://twitter.com/RyanTownsend Ryan Townsend

    Gary Bernhardt runs Destroy All Software (https://www.destroyallsoftware.com/), his screencasts are no less than excellent every time. Think Railscasts, but more advanced and lower-level.

  • Kenton Newby

    My first test is usually an acceptance test using something like Cucumber, Turnip or RSpec/Capybara…something from the outside that describes the high-level functionality of whatever feature (or part of a feature) I’m working on. This helps me focus on the functionality I’m trying to create and allows me to move forward in small steps.

    More often than not, that initial test turns out to be some sort of authentication test if it’s a Rails app.  Or a test of whatever the “main” class is if it’s something in pure Ruby.

    That initial acceptance test will fail, but it should lead me down the path of what needs to be added in order to make the test pass.  

    e.g., …’undefined constant User’?  Okay, time to add a User class.  

    From there, I usually go into RSpec and start unit tests on that class, writing pending specs to describe how that class should function, as I’m thinking through the problem.  Then I drive out the class’s functionality in typical TDD style.  Once all unit tests pass, I re-run my acceptance test, which will either pass or will lead me to some other part of the system that needs attention next.  Maybe a route or controller if it’s a Rails app.

    Probably nothing new here.  Pretty much like what they talk about in the RSpec book, various talks, etc.

  • http://www.facebook.com/MarcRic Marcos Ricardo

    Well, in Rails universe there are two great development models as I see:
    Starting apps by their models, or starting apps by their views.

    The last one fits more closely to the process you describe in the last paragraph.

    There is a practice tip on this way here:

    http://speakerdeck.com/u/danielvlopes/p/melhores-softwares-atraves-da-interface

    Take a look from slide 64 on!

    I would like to know if there is a way to start an app this way only using test first.