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
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
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 case... How do you want to present the information to
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
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
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?
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 =)
This post was originally posted on my site bhserna.com, if you find it useful and you want to keep learning about this approach, you can signup to early access and updates to a guide to help you with your TDD =)