Benito Serna Tips and tools for Ruby on Rails developers

How organizing your code in use cases can help you to start your projects using TDD

October 10, 2018

After reading a lot of questions and answers on TDD and unit testing, are you still struggling to find the answer to… Where to start from?…

Sometimes when you and your team have already done a couple of projects adopting the use of unit testing, but coding first and then unit testing… After some point in the development process, it start to feel natural to write tests first and then the code, more in the TDD style.

But is normal to have problems to start a project using TDD from the beginning… Is this your case?

Are you struggling because…

You don’t know where to start from? Or… Which is the first test that you should write when you have no code at all?

Wouldn’t it be nice to just know how to start without thinking that much!!

Well, there are some ways, that’s why many people have found TDD very useful… But it takes time, practice and experimentation to find a way that works for you and your team.

One way that I have found useful, because it helps you describe the behavior of your application in clear way, is to start by testing through your use cases instead of your “entities/models”…

This is because when you are starting to code, you have an idea of what your application should do, but you don’t know how it should do it…

So let’s try to explain this with a little example…

Let’s say, that you are working in a web app about documents… And your first task is to create a page that list all documents metadata, stored somewhere (maybe a database table)… Which is the first test you should write?

If you are using ActiveRecord, maybe you are thinking in just use Document.all in your controller/routes… Should you test Document.all? Should you test the behavior through the controller?

Let’s pause a little and instead of thinking in technical stuff, let’s think about the use caseHow do you want to present the information to the user

Maybe you will need something like this (with some imagination)…

[icon] - Document_1.doc - by [photo] Benito Serna - uploaded 2 days ago.
[icon] - Document_2.xls - by [photo] Johh Smith - uploaded 4 days ago.
...

Mmmm… That’s not really a Document.all problem… We need to mix data from the user and maybe from a profile record…

What if instead of starting by thinking in database records, we start by thinking in how we can access the information in the client in an easy way, thinking that if we ask the system for “All documents” the system will return that expected data structure, no matter how the data is obtained (or if it changes later).

So… One option could be something like…

docs = Docs.all_documents(*some_args)

docs.each do |doc|
  doc.icon_type
  doc.file_name
  doc.file_url
  doc.uploader_photo_url
  doc.uploader_name
  doc.uploaded_at
end

Are these docs records, entities or models?… I don’t know, I just know that they respond to those methods. And to test them I should check if what those methods return is what I expect.

Now start thinking how you could structure your data source to be able to construct that result… Maybe something like…

store = store_with([
  document_with(
    file_url: "path/to_url/Document_1.doc",
    uploaded_at: 2.days.ago,
    uploader: user_with(
      name: "Benito Serna",
      photo_url: "path/to/user/1/photo.png"
    )
  )
  #...
])

docs = Docs.all_documents(store)

This is just an example… You can start with that or with other structure, but the important thing is that the output should be the same. Because that’s what your app should do…

… Now, what do you think?

If you had a function like Docs.all_documents

Would it be easier to know what your first test could be?
How hard would it be to test this function in isolation?
How hard could it be to implement the needed html?

Now…

Try to write your first tests for this function
Yes, really try it! It will help you to understand the concept =)

And if you want to know how I would do it, go to this link, but don’t fool yourself and do it after you have finished yours =)

Related articles

Weekly tips and tools for Ruby on Rails developers

I send an email each week, trying to share knowledge and fixes to common problems and struggles for ruby on rails developers, like How to fetch the latest-N-of-each record or How to test that an specific mail was sent or a Capybara cheatsheet. You can see more examples on Most recent posts or All post by topic.