views:

333

answers:

7

I have a solution that is missing a lot of code coverage. I need to refactor this code to decouple to begin to create unit tests. What is the best strategy? I am first thinking that I should push to decouple business logic from data access from businessobjects to first get some organization and then drill down from there. Since many of the classes don't support single responsible principle, it's hard to begin testing them.

Are there are other suggestions or best practices from taking a legacy solution and getting it into shape to be ready for code coverage and unit testing?

+10  A: 

Check out Working Effectively with Legacy Code.

orip
+1  A: 

Start by creating the tests. Refactor the code as needed to support the tests.

Kristopher Johnson
A: 

These are generic guidelines I find useful for unit testing:

1) Identify Boundary Objects (Win/WebForms, CustomControls etc).

2) Identify Control Objects (Business layer objects)

3) Write Unit tests only for control objects public methods invoked by boundary objects. This way you'll be sure you're covering main functional aspects of your app.

In your case, if the business rules are tightly coupled with boundary objects you're in trouble - in my opinion you should try to refactor your stuff focusing on hot spots based on functional requirements of your app.

The feasibilty of this obviosuly highly depends on the specific case.

JohnIdol
+1  A: 

I suggest creating tests for the existing code first, until you have good enough coverage. You need to test your code as it is to make sure you don't break anything when you refactor. Of course, you'll want to do this piece by piece, writing tests for a module, then refactoring it before moving on to the next one. Once you have good coverage you can decide if it's worth continuing with the refactoring just to make the code more testable. From your description, I suspect it will be.

Bill the Lizard
+4  A: 

One of the most important things to do and best ways to approach in legacy code is defects. It is a process that you will continue to do with any code base that you introduce unit testing to, as well. Whenever a defect is reported, write a unit test that will expose the defect. You will quickly find that code that would break on a regular basis (i.e. "Oh, yay. The plugh() method in the xyzzy class is broken again!) will start breaking less and less.

Really, just start doing it. You aren't going to have tremendous coverage in a legacy application overnight. Start by hitting the code that is more prone to breakage, and start branching out. Make sure that any new development within the code has a higher code coverage, as well.

Remember the mantra of TDD is "red/green/refactor", and you might want to look into refactoring tools to help do some of the tedious tasks that go along with it. JetBrain's ReSharper is popular, and my personal choice.

joseph.ferris
A: 

Try to start reading about TDD.

http://www.codeproject.com/KB/dotnet/tdd%5Fin%5Fdotnet.aspx

Makah
A: 

You need to test your code as it is to make sure you don't break anything when you refactor.

maggiechen55