22 Jul
2007

Including Tests into the Original Assembly

Category:UncategorizedTag: , , :

I am working on a project in which I am diligently applying TDD.  I am enjoying the process of actually driving my design with tests, as it as clearly saved my bacon already with discovering bugs in my class constructors. I am using ReSharper’s NUnit support + Matt Berther’s excellent TDD Live Templates over MSUnit, which is a whole post in itself.

projects

As you can see in the image to the right, I have embedded the actual test fixtures into the original assembly.  For the first few days of this project, I was managing a separate project and assembly for unit tests, but I finally decided it makes more sense to keep the tests near the original class files.

  1. It doesn’t swell the physical size of the assembly my much.
  2. I may embed a unit test runner function into the Help menu of the final application.  This will be enormously helpful for troubleshooting and support.
  3. Management of the tests is easier because it requires future developers to load on fewer project.

For now, I have chosen to put my tests into a separate folder within the project.  This separates the test classes from the other classes in the assembly by a namespace and that makes sense to me for the time being.  Alternatively one could have a ClassTest file next to each Class file. 

 

Technorati tags: , ,

8 thoughts on “Including Tests into the Original Assembly

  1. It might not swell the assembly by much, but you’ve now got to package all the test framework’s assemblies (and dependencies) with the finished product. It’s too much work to write a wrapper around the test framework to avoid having to do this.

  2. You’re right about that. It does increase the size of the deliverable by the size of nunit.framewok.dll and Rhino.Mocks.dll.  Combined, that is 284K, which I suppose I can live with.

    I realized another benefit last night, though.

    I can test internal classes.

  3. you can test internal classes anyway by just tagging the assebly as a friend:
    [assembly: InternalsVisibleTo “your.other.assembly”)]

    The increased size of the deliverable wouldn’t be an issue if the .Net framework wouldn’t require you to define the output of a project but rather allow you to define the output though a build process. Then you could include the tests in the project, which I agree is good, but wouldn’t have to include them in your production deliverable because your build script would just exclude them.

  4. Tom,

    That’s a sweet tip. I didn’t know about that attribute.

    You can define the tests in the project, but omit them during the build process. Although Visual Studio has no facility for doing this, you may do it through your build process with file masks or whatever. Just use NAnt or MSBuild to delete your test fixture code files from the pile of code files. This would require a naming convention, though. Lame, I guess.

  5. It could also be thoroughly argued, by me and others, that you should only exercise unit tests on your public interfaces. The internal classes would be used by the public interfaces, and if not, then you should remove them.

    Dead code should be relentlessly removed from your projects.

  6. You are suggesting that you should only build unit tests for public interfaces, not concrete implementation classes?

    I dont get that. Why wouldnt I put as much code under test as possible? I dont understand your point.

  7. I am stating that you put as much code under test as possible… However, if I have an internal helper class, I dont need unit tests for that as long as I have unit tests for the public interface that exercises that helper class.

    Going this route decouples my tests from the knowledge of the internal workings of my class library. I have expected inputs and expected outputs. If one of my internal classes is a collaborator to the expected output, then the test on the public interface needs to be changed, as well as the test for the helper class.

    Similarly, what happens if I decide I no longer want to use that internal class? I now throw away all the work that I did for creating tests on a class that no longer exists.

    Since the tests on the public interface already call to the internal classes, why would I duplicate efforts? It’s called DRY (Dont Repeat Yourself).

  8. Uhhhhh…..
    So what you’re advocating is placing as much code under test regardless of whether it is some form of functional or unit testing? If not you have a little bit of a conundrum to resolve because your unit tests will never involve a collaborator because a true valid unit tests never depends on anything that is not controlled by a mock implementation. If your class that depended on the previously mentioned internal class was a true unit test it wouldn’t be using the internal class for its own unit testing so changes to the internal class would never have any effect.

    “Similarly, what happens if I decide I no longer want to use that internal class?…….”
    If I hear you correctly – The unit tests that I put into my system that are suppose to protect me and make change easier sometimes actually have the opposite effect and make change more difficult because I now have a ‘user’ of the class that I must update. Now that I have succesfully put words into your mouth; I agree with you 🙂

    The DRY principle:
    What would you say about the different levels of testing and how it relates to DRY? You typically have some form of unit testing, plus acceptance/functional testing and then some exploritory testing. IMO each level of testing is basically a violation of the DRY principle because each level of testing operates in a silo and you have a hugh amount of duplicated effort.

Comments are closed.