How to deal with tangled uses dependencies in order to start unit testing?
Asked Answered
I

1

6

I have a messy Delphi 7 legacy system to maintain and develop. I am already reading "Working effectively with legacy code" and I like this book very much.

In order to start following the advices in the book, I created a test project and tried to write a single test. To do this I need to add some unit to the test project, but here lies the problem: the system under test has horrific uses dependencies. One unit uses some other unit, that uses some other unit and so on, and so on. It seems that most units directly or indirectly use one particular unit, and this unit in turn has 170 dependencies in its uses clause. There are indirect circular dependencies also.

Currently I am trying to add all of the legacy system's units into the test project, but I am running into all kind of problems, like "unit xxx was compiled with a different version of xxx", and others.

So I wonder if I am doing something wrong. I have used unit testing before, but in my own projects, that were smaller and with better structure and modularization. What are the options I have in this situation? Am I missing something?

Inman answered 21/8, 2012 at 11:10 Comment(9)
If changing code is an option I would consider refactoring at the right places to create seams which make testing single pieces in isolation much easier.Charles
@stefan Even in a legacy system? Really? Yes certainly for a system under active development.Hatshepsut
His first sentence says: "I have a messy Delphi 7 legacy system to maintain and develop"Charles
I am still struggling to find my way into the system. Writing tests was supposed to help me with that. I want to gain some confidence in my understanding of the system and then start refactoring.Inman
@Stefan I only saw legacy. In my opinion legacy systems are not developed so the terminology confused me. I'd personally lean towards adding tests first and then using those to support re-factoring. Re-factoring really needs tests to be already in place .Hatshepsut
@DavidHeffernan: nowadays "legacy" seems to be used for any system older than 6 months. Well, at least for systems that are no longer "green field" development, though with the agile approach that would mean that all systems are legacy after the first sprint? :-)Riggall
@David, according to the book mentioned in the question, "legacy code" is defined as "code without unit tests". It makes no difference what the current status of the project might be - if it doesn't have testing implemented, it's legacy.Hockenberry
@ken That's a novel definition for me.Hatshepsut
@David, it was to me, too, until I saw it in the book. It's related to the big move to Xtreme Programming in the early 2Ks (the book was published in 2004).Hockenberry
H
5

You will always have dependencies in your code. Well, as long as you have code re-use, you will have dependencies. Since you are testing a legacy system, wholesale re-structuring is out of the question.

So you simply need to accept the dependencies. The most convenient and practical approach is to have a single unit tests project. That project contains all your unit tests. Use the facilities of your runner program to run only specific tests at any one time.

This leads to your project have the same list of units in its .dpr file as the main project. That's what you have currently tried and it's the right approach.

Your problem sounds like you are sharing the DCU directory (unit output directory) between the main project and the unit tests project. And you have different compiler options for the two projects. That's the most likely explanation for the error you report.

There are a couple of obvious solutions:

  1. Align the compiler options for both projects. Then they can share DCUs.
  2. Have separate DCU directories for the two projects.

Option 2 is much more robust and is best practise. However, you should try to understand why the compiler options differ. It's quite possible that your compiler options in the new unit tests project will need to be changed so that the units under test compile and function as desired. In modern Delphi I would use option sets to ensure consistency of compiler options.

Now, there may be other technical problems that you are facing, and my explanation of the error may not be quite right since I'm having to guess a little. But the bottom line is that having the same list of units in your .dpr files is the way to go.

Hatshepsut answered 21/8, 2012 at 12:17 Comment(1)
Thank you for the explanation. I tried both sharing DCUs and outputting them to different folders and the problem persists. But I feel better now that I only need to hunt some technical problem, knowing that my general approach is right.Inman

© 2022 - 2024 — McMap. All rights reserved.