Paulo Ortins Paulo Ortins
Menu
Search
12 Lessons I learned using unit tests/TDD

Introduction

Two years ago, I was working in a project where our goal was to write a web excel-like application to calculate products/services prices. The team was split in 3 pieces, the development team, the requirement team and the QA team. This project became so big and we didn’t use any types of automated tests (our QA team was doing manual tests) that the project spent more time being tested than being developed. Each little change, the project spent hours, hours and hours with the QA team. One day I went to a developer meeting and talked about my problem with others programmers. They suggested to me learn about unit tests, acceptance tests and TDD.

Learned Lessons

The list below is a lessons list that I learned while applying unit tests/TDD since 2011.

1. Don’t try to apply TDD for the first time or teach TDD to your team in a real project. It won’t work. First is necessary to know how TDD’s flow works. How to mock up objects, how to mock up the framework internals, how organize tests and so on, if your team is not ready, it will slow down the development and you will miss some deadlines.

2. Coding Dojo is a good way to teach TDD. We do coding dojo sessions. It’s the best way we found to teach TDD to new developers and to keep our skills up-to-date.

3. Try to convince your whole team before applying TDD. There is nothing more frustrating than one or two developers ruining our test efforts, commenting code, trying to commit with failing tests and so on. I had bad experiences with non committed developers. Explain about the benefits, how tests keep our software bug-free, how we can refactor the code without worry about break the software and so on.

4. Write sufficient tests. Build a test suite is like to build a shield against bugs, the team should be able to fully trust in this shield when we are doing a refactoring or evolving the software. If this shield has gaps, we are increasing the risk to create unidentified bugs when we change the code. You don’t have to cover 100% of your code, it’s almost impossible and you will lose too much time but cover the majority of your code is perfectly achievable. A good rule is test everything that can possibly break.

5. Use a coverage tool. Coverage tools will report gaps in our test suite. With these tools, is easy to identify code that aren’t being tested. Most of these tools give to us a visual identification, coloring the lines that are being tested in blue/green and coloring in red the lines that are not being tested. If you are a .NET Programmer, the Visual Studio Ultimate comes with this feature or if you are a Java Programmer you can use the EclEmma.

6. Tests should be fast. Fast to run and fast to write. When we are building software we are always pursuing a deadline. Our tests have to help us to achieve this goal and not be a distraction or a delay.

If our tests take too much time to be written, the team will stop writing them when the deadlines become too tight.
If our tests take too much time to run, the team won’t run them everytime they change the code or they would decrease the team’s productivity.

7. Don’t comment or ignore failing tests. Once your team becomes comfortable with build failing due to 1 test, they will be comfortable with the build failing due to 2, 3, 4 tests and so on. At these times, the test suite feedback will be ignored and the tests won’t be helpful anymore.

8. Pair programming helps the team to adopt TDD. When we are trying TDD for the first time or when our deadline is tight, we will have the will to forget the tests and write only production code. Pair programming will prevent the team to cut corners and will keep it writing tests.

9. Keep your test code clean. Once, to speed our productivity, we decided that our test code shouldn’t be as clean as our production code. At first look, it was a good decision but software will change and tests will have to be changed too. We ended up with tests difficult to maintain and with larger estimates due the cost to maintain the tests.

10. Tests should have one and only one reason to fail. Be careful if your test has a lot of assertions. If functions and classes should have only one responsibility, our tests should test only one concept. In this way, it will be easier to look at a failed test and figure out what is wrong.

11. Write unit tests will save debug time. A lot of time is spent debugging code, looking for bugs. Once you are writing unit tests, you will have a real-time feedback of each piece in your code, it will be easier to find bugs and consequently and it will reduce the time we spend debugging.

12. Keep pushing. Apply TDD is all about change our mindset. It’s difficult to start to write tests and is even more difficult to write tests BEFORE to write production code. It’s important to keep pushing and writing tests, one day, they will end up saving our lives. Also, once your team is fully comfortable with TDD, the productivity tend to increase.

arrow18 Responses

  1. 8 mos, 1 wk ago

    Not much to say but good post! From a couple of year experience of the transition to TDD full time, I agree with all of these points, especially the last one.

  2. 8 mos, 1 wk ago

    Thank you!

  3. 8 mos, 1 wk ago

    Number 3 is probably what kicked my butt the most. I remember when I first started with TDD, I did not trust or believe in “wasting” time writing tests. I find the main reasons some newer devs are skeptical of TDD are they don’t know what to test, how to test it, and how to test it quickly.

    It’s very Ruby-oriented, but the testing principles in this book helped me out:
    http://www.amazon.com/Practical-Object-Oriented-Design-Ruby-Addison-Wesley/dp/0321721330

  4. Neil N
    8 mos, 1 wk ago

    Hello,
    I agree dojo type projects are the best way to practice/learn TDD. But I feel as though there is still a large “gap” between the dojo projects my team has done and our actual “big and complex production system” We have hit 20% code coverage, and continue to add tests, but truly TDD’ing new features proves difficult. Are there any “mid range” dojo projects you would recommend? Or have tips for creating some on our own? Thanks and great post.

  5. 8 mos, 1 wk ago

    What worked for me was the following path:

    Coding Dojos
    Small Toy Projects (small CRUDs)
    Small Real Projects (small CRUDs)
    Large Real Projects

  6. 8 mos, 1 wk ago

    Actually we started testing half year ago in a large real projects. FAIL!!!
    We had to go backwards to smaller units to understand the concepts of mocking and unit tests.

    Now I found a great book for C# developers.
    Professional Test Driven Development with C# by James Bender and Jeff McWherter

    It includes a with benefits of TDD and recommends starting with Dependency Injection
    Then go on with unit tests
    and after all to practice TDD itself

  7. 8 mos, 1 wk ago

    I used this book as guideline too. I also wrote a small review about this book in the post below.

    http://pauloortins.com/good-resources-to-learn-casp-net/

  8. Liordino Neto
    8 mos, 1 wk ago

    I’m starting out on this and trying to convince my coworkers to follow a TDD mindset (man it’s hard…), and have a question: what do you say about Code Katas as a resource to learn to apply TDD?

  9. Liordino Neto
    8 mos, 1 wk ago

    I mean, as an individual way to learn it, since I can’t go to a dojo with more people right now.

  10. dacanetdev
    8 mos, 1 wk ago

    First of all good post I agree with all the points. Ok I have been applying a kind of TDD not sure if I’m doing well. I’m using my business objects so I’m connecting to DB, that’s why I don’t feel is real TDD, I don’t have Mocks or Stubs and for the CRUD I’m really inserting,Updating, Deleting records
    How do you TDD when the App is Data Driven 100% Entity Frameowrk and/or Stored Procedures?

  11. 8 mos, 1 wk ago

    Yes, convince people to use TDD is hard :/

    About Code Katas

    I did, and I still doing code katas in my spare time and yes, it’s a good way to learn TDD.
    You can use them alone or in groups, through coding dojo.

    I wrote about it in two posts:
    http://pauloortins.com/coding-dojo-practice-programming/
    http://pauloortins.com/code-kata-javascript-jasmine/

  12. dacanetdev
    8 mos, 1 wk ago

    Even though what I’ve done saved me a lot of time of debugging and help me as integration test

  13. 8 mos, 1 wk ago

    I don’t know if I understood your question but in this case, you have to make a static database and test if the data is been modified or retrieved as you expected.

  14. 8 mos ago

    Here’s another one:

    “Don’t try to apply TDD if you’re not exactly sure what it is”

    You have no idea how many team leads out there think that they know it, but obviously don’t.

  15. ogurh
    8 mos ago

    good post, thanks, but i expected it to help me learning test, so i use this comment to ask it directly, can anyone point me to good resource to learn tdd testing, in js, cause i really don’t know where to start, testing really seems to be the thing to do, but when you are alone, knowing how to beging your app test is a HUGE barrier )

    thanks for the article :)

  16. 8 mos ago

    Sorry for the delay. If you want to read a book, maybe you can try one of these:

    JavaScript Unit Testing
    Test-Driven JavaScript Development (Developer’s Library)

    Or if you prefer to learn online, I wrote a blog post about jasmine and unit test and you can also use the tools tutorials:

    Jasmine
    Karma

  17. 7 mos, 4 wks ago

    Thank you very much for this articel.

    I’m working 2 years in a team working with TDD. It was a pleasure.
    Now I’m over one year in a team without TDD, but some day we want to start …

    And in my view we have exactly the problems you described.

  18. Aleksandar Naumovic
    5 mos, 2 wks ago

    Hello,

    I would advise you a couple of things:

    1. Keep data access components separate (necessary CRUD operations, reading could be with different criteria). Although it’s a good principle, your tests would be isolated for data access as well.

    2. If you don’t mock everything (it’s recommended because you test only the functionality of the component being under test, not their dependencies), you should mock at least the data access components themselves because their tests are slower. You don’t have to run everything against the database. You should really operate with a database, but only in data access components.

    3. You should test data access operations using another operations to make an assertion. Ex. if you test insert operation, you could test it using retrieval operation.

Leave A Comment