38

I'm working with a new team that has historically not done ANY unit testing. My goal is for the team to eventually employ TDD (Test Driven Development) as their natural process. But since TDD is such a radical mind shift for a non-unit testing team I thought I would just start off with writing unit tests after coding.

Has anyone been in a similar situation? What's an effective way to get a team to be comfortable with TDD when they've not done any unit testing? Does it make sense to do this in a couple of steps? Or should we dive right in and face all the growing pains at once??

EDIT

Just for clarification, there is no one on the team (other than myself) who has ANY unit testing exposure/experience. And we are planning on using the unit testing functionality built into Visual Studio.

4
  • +1 This question outlines almost exactly the situation that I'm in, only for Eclipse PHP Dev instead of VS. Dec 9, 2011 at 17:40
  • Not a suitable question for this forum
    – Ryan
    Aug 6, 2012 at 12:29
  • 3
    What did you end up doing? Would really like to hear how this turned out.
    – Snoop
    Apr 26, 2018 at 14:50
  • Enforce testing an the version control level. I never let my team submit code unless it passes all automated tests. Do not allow code to be submitted to any branch unless all tests pass, and the coverage is sufficient. Jul 13, 2021 at 16:45

7 Answers 7

37

Practice on existing bugs/defects.

This is a really tough situation. I've never gone all the way to TDD from nothing before, but in my experience, getting a team to go from no unit tests to proactively writing them has been a very "one step at a time" approach.

First, get them comfortable writing unit tests and knowing really what they are and their benefits. For my teams, it's been best to write unit tests for existing bugs. Current bugs in systems have two things that you need to teach people to write unit tests well:

  1. an expected precondition and postcondition
  2. an outcome that currently is not what is expected and violates that precondition/postcondition

This gives members very concrete practice examples. They can write a test before they fix the bug, so that it fails. Then, they can fix the code so that it passes, and fixes the bug. Once they're comfortable with this, then you can get them the rest of the way so that they can write unit tests with no code up-front and then write new code to get their tests to pass.

I think the trick is to give them something to practice on where there are clear method pre/post-conditions. If requirements for methods are fuzzy, it's hard for even experienced TDD people to know exactly where to start. Take it a step at time and you'll get there. Good luck!

2
  • Wouldn't writing a unit test for an existing bug wind up being a lousy unit test, i.e it would test a whole bunch of stuff rather than a single unit? Wouldn't an integration test be more suitable for this scenario? Aug 12, 2014 at 16:43
  • write test for bug,it's good advice.
    – 王奕然
    Jul 23, 2015 at 14:42
33

I've managed to convince my whole company to switch to TDD. It wasn't easy, but it was well worth the effort: the quality of the code went up after the transition, and now nobody imagines going back to the horrible, cowboy coding times.

  1. Explain, explain, explain. You don't want your team to write tests. You want your team to want to write tests. This means that they should fully understand why they should be doing it, what are the benefits, and how this will make their job much easier. Red, Green, Refactor, writing a regression test as proof that a bug has been fixed, etc. You have to convince them the whole thing makes sense before you ask them to write any code.

  2. Go for the real thing (first tests, then code). Writing tests after the code hardly makes any sense, as you will never know if they actually work (and people do write buggy test cases). My intuition is that the amount of effort you need to go from no tests to tests first is much less than what you need to go form no tests through code first to tests first, so you may as well skip the middle step.

  3. Start with regression tests. These are pretty simple to understand, and they give instant gratification. Of course, this assumes that the code is properly modularized and easily testable. If not, skip this step.

  4. Take baby steps. TDD takes some time to get used and may be frustrating at first. Try to introduce testing in a brand new project or component, ideally: something not very important. You want to avoid at all costs the situation when there's something really important to be done really quickly and the programmers feel that TDD is getting in the way.

  5. When the team starts being comfortable, have all new functionality written in a TDD manner. This depends on the size of your project, but after some time you should get a pretty good coverage, with only some legacy parts of your project written in the old way.

  6. By this point, the team should already understand and embrace TDD, and the legacy (non TDD) stuff should be considered difficult and annoying to work with. Get it refactored: most pople will do it with pleasure.

Some other important points:

  • Make sure you are using the best testing framework available. It will be much harder to convince people to do TDD if they have to interact with a library that is poorly written.

  • Make sure the tests are easy to run and don't take to much time to finish (or cheat, for example by using an in-memory db for the tests).

  • Setup some continuous integration software, so that broken tests are found immediately.

1
  • 2
    Probably most important is to get management on-board.
    – Todd
    Jul 30, 2018 at 14:12
20

One way to get comfortable with TDD is to write integration tests first. Introduce test seams and true unit tests later.

The problem with writing unit-tests after coding is that the code may not necessarily be well-designed to be testable. You may need to do some refactoring or maybe re-design to introduce the test seams. But how can you refactor or re-design safely if you have no test coverage of any kind?

Integration tests can give you that coverage initially. Every time you have a regression or a production issue, fix it in the code and cover that code with a test. Once you have enough of a safety net provided by such tests, you can introduce unit tests of more finely-grained, isolated components and/or classes of your system.

2
  • 6
    I think this is a great way: Show the team first how end-to-end tests can be automated and run on every build. They don't even need to write the tests, you can do that all by yourself if the team is hard to convince. As soon as they see how great is to have automated feedback each time they change something, they will be the ones asking you how to do more of that stuff. Oct 11, 2010 at 4:31
  • 1
    You second para is spot on. The code is hard to test but because its on a legacy code-base with no tests, refactor is not an option. The test then can be so difficult to implement that it turns off people to even bother.
    – Todd
    Jul 30, 2018 at 14:07
5

TDD is very difficult to implement and isn't always the best option for every development team. In my previous job, the team was heavily focused on TDD. Our development model was entirely TDD using the agile development approach.Testing was done through Visual Studio unit tests.

If a developer didn't write any unit tests for his/her feature they'd be in trouble with the technical lead. Furthermore if anyone check-in a broken build or any unit tests, the developer would need to fix all issues and add a $1 to the team money jar.

3

Just a small thing to add, visualize the process. Make the continous integration run tests automatically and check for code coverage. List the most complete tested modules on some startpage that everyone can see. That should get the team competition going.

1

I went from no JUnit experience straight to TDD, and the experience made the value of TDD unmistakably apparent. I have become so thankful for the unit tests that I quickly became an an evangelist for the approach

0

I've been on teams that didn't do any unit testing but it was introduced and has become almost common to have some tests now. I would suggest exploring how well does your team understand the basics of unit testing as well as what tools are you wanting to bring in here?

In my case it was bringing in nUnit for some .Net code that was a mix of business logic, user interface, and back-end functionality. I would suggest seeing if there are some people that are more willin to want to get to it more than others so that a couple of people on the team get it and it can spread a bit better than the flip side where you try to get everyone to jump in on this. By getting some to do it well first, this enables some cross-training so that those that pick it up can be tested as to how well can they teach it to someone else.

Another point is to consider bringing in those that have more expertise to try to show this off to some extent. Thoughtworks was brought in where I work to show us some stuff that some of it did get widely adopted and other parts not so much, but I think that would be true in most places.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.