Thoughts on testing COM objects

| 5 Comments

Ben over at Code Circle is thinking about unit testing COM objects. I did quite a lot of this back in 2000 when I was working with an investment bank. The first thing you need to realise is that COM is just an interface layer; so lots of your unit testing should be done on the code that the COM interface layer calls into. You can test pretty much all of the actual functionality of a COM object without bringing COM into the mix at all. This keeps the tests nice and fast.

So, rule one for testing COM objects is: Test as much as you can using normal unit testing techniques for the object implementation language.

Once you've done that you can start thinking about what it means to test a COM object...

I wrote my COM object tests as a C++ project that could be worked on in a separate instance of Visual Studio whilst the COM object itself was developed. This meant that I could add functionality to the tests as I added COM functionality to the objects under test. The compiled test could then be checked into source control and run as part of the release build of the object under test. This seemed to work well.

We had a selection of standard COM object tests, the kind of thing that you need to test for all objects. These included things like:

  • Checking for the interfaces that you expect an object to support.
  • Checking that the object didn't support additional interfaces. This one was harder than the first one. What we did was pull the list of interfaces from HK_CLASSES_ROOT\Interface which was less than ideal but it caught a few problems...
  • Check for the presence of a proxy when you expect one and the lack of a proxy when you don't expect one. We did this by querying for IProxyManager
  • Check for the presence of the FTM. This was the main reason that I started testing our COM objects, I'd created a new version of an existing object and the new version used the FTM and I needed a way to prove that it actually did (yes, I released a version that said it did but didn't...) We tested for this by getting the unmarshal class for the object under test and making sure that it was the FTM...

Of course all of these general tests needed to be run in all combinations of across apartment usage. This was the slightly complicated bit. I seem to remember that my COM object test base class dealt with all the threading issues and would create the object under test on the correct kind of thread and then test from the correct kind of thread and do all the permutations that you needed... Doing stuff like that tends to focus the mind on exactly how all that marshalling malarky actually works ;)

Once I was sure that the basic COM stuff was correct for the object I tested each interface. Since we had several common interfaces that many of our objects used I wrote tests for each interface and the object test simply did the basic COM testing and then ran a test for each of the supported interfaces. These were the tests which are most like today's view of unit tests.

I remember that I used "traits" quite a lot in these tests. This allowed me to pass in a policy which controlled how the test ran. We needed this because the interface test should be usable on all objects that implemented the interface. The traits let us specify things that were per object based; such as the class id that's returned by a particular instance of IPersistStream etc.

In my opinion this way of testing COM objects was far superior to using a more COM conversant language (like VB) as you could test far more important aspects of the object. I did have to write most of it from scratch though. Later, at another investment bank, some guys had put together a COM version of CPPUnit, but I never really got involved in it... Perhaps Nick Gunn might like to tell us about it?

5 Comments

I used to work with one of the guys behind CruiseControl.NET, and he started working on COMUnit [1] back then. It was VB-based, so probably not your cup of tea, and it's more focused on testing the functionality of COM objects than the actual COM aspects of them.

I remember he brought me into a tantrum by claiming that the most important aspect of code was its testability. In my mind it was shippability. I've since changed my mind :-)

[1] http://comunit.sourceforge.net/

There used to be a COM testing product called iUnitTest here: http://www.iunittest.co.uk, but not accessible at the moment.

Hi Len,
I read your thought about testing COM objects...I am struggling with a different situation and probably you know the answer.
I am working on a product that provide support to COM. You can interface COM objects with our product and can access COM objects properties/methods.

What is your suggestion for automating testing for our COM support.

There are so many COM components out there and we receive bugs if users not able to interface their objects to our product. Even if our developer fix the bug, the standard practice is to write a manual test for that particular object and verify the bug. I am searching for a strategy to automate this testing. Is it feasible? Please let me know..

Without knowing more about what your product actually does it's hard to say.

Surely you can just write a test for each way that your product manipulates a COM object and then each time you find a real world object that breaks your product you can add that breaking functionality to your tests and fix the problem. Then you'll grow your tests as you find problems...

I think your problem comes from this statement: "I don't know much about COM".

You need to understand what you want to test and how what you want to test interacts with COM before you can solve your problem.

I expect that your applications requires/makes use of a limited set of COM interfaces and you should probably aim to write tests that will prove conformance with those interfaces. You can then ask clients to run these tests on objects that they have to ensure that their objects conform to what your application expects. You can also write some test objects that implement the interfaces that your application expects and have them act in such a way that your application can be tested.

Leave a comment