HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Integrating Unit Testing functionality into an old COM-based IDE

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
intointegratingtestingbasedidecomoldfunctionalityunit

Problem

My UnitTesting add-in works nicely, but it has dependencies on a Reflection and a System add-in, which means 3 add-ins loaded into Excel to write and run a VBA unit test, and I've recently decided that was a pain in the neck and didn't quite make VBA unit testing, uh, very much appealing.

So I proceeded to port my VBA code to C#, and implemented the Extensibitity.IDTExtensibility2 interface in a new COM-visible class library project.

At this point it only generates a "Test" menu, and so far only two commands have been implemented - I'd like what I have to be reviewed so I can make adjustments before I make a mess implementing the rest of the features.

For visual reference, this is the generated menu:

At this point, only the "Run/All tests" and "New test module" commands are implemented.

This is the Extension class that I've registered with ProgId "RetailCoderVBE" in my registry:

```
using System;
using Extensibility;
using Microsoft.Vbe.Interop;
using RetailCoderVBE.VBIDE;
using RetailCoderVBE.UnitTesting;
using System.Runtime.InteropServices;
using RetailCoderVBE.UnitTesting.UI;

namespace RetailCoderVBE
{
[ComVisible(true)]
[Guid("8D052AD8-BBD2-4C59-8DEC-F697CA1F8A66")]
[ProgId("RetailCoderVBE")]
public class Extension : IDTExtensibility2
{
private VBE _vbe;
private TestMenu _testMenu;

public void OnAddInsUpdate(ref Array custom)
{
}

public void OnBeginShutdown(ref Array custom)
{
}

public void OnConnection(object Application, ext_ConnectMode ConnectMode, object AddInInst, ref Array custom)
{
_vbe = (VBE)Application;
}

public void OnStartupComplete(ref Array custom)
{
CreateTestMenu();
}

private void CreateTestMenu()
{
if (_vbe == null)
{
throw new InvalidOperationException("Unable to initialize add-in.");
}

_t

Solution

Looks pretty good. A few minors:

-
You repeat a lot of code for the event raising. An extension method could help to facilitate DRY:

static public void Raise(this EventHandler handler, object sender)
{
    if (handler != null)
    {
        handler(sender, EventArgs.Empty);
    }
}


then you can raise an event like this:

OnNewTestClass.Raise(this);


-
In FindTestMethods you find a set of methods with LINQ yet in the loop you still have this check:

if (!procedure.HasAttribute() && !procedure.Name.StartsWith("Test"))
{
    continue;
}


which you could pull up into the Where clause as well. I'd also extract the Where condition into a private method like IsTestMethod and utilize SelectMany to get all members of all components. With all of that the method can be refactored to:

private IEnumerable FindTestMethods(VBProject project)
{
    return project.VBComponents
                  .Cast()
                  .Where(component => component.Type == vbext_ComponentType.vbext_ct_StdModule)
                  .SelectMany(module => ProjectComponent.GetMembers(module.CodeModule))
                  .Where(IsTestMethod)
                  .Select(procedure => new TestMethod(project.Name, procedure.Name));
}

Code Snippets

static public void Raise(this EventHandler handler, object sender)
{
    if (handler != null)
    {
        handler(sender, EventArgs.Empty);
    }
}
OnNewTestClass.Raise(this);
if (!procedure.HasAttribute<TestMethodAttribute>() && !procedure.Name.StartsWith("Test"))
{
    continue;
}
private IEnumerable<TestMethod> FindTestMethods(VBProject project)
{
    return project.VBComponents
                  .Cast<VBComponent>()
                  .Where(component => component.Type == vbext_ComponentType.vbext_ct_StdModule)
                  .SelectMany(module => ProjectComponent.GetMembers(module.CodeModule))
                  .Where(IsTestMethod)
                  .Select(procedure => new TestMethod(project.Name, procedure.Name));
}

Context

StackExchange Code Review Q#67757, answer score: 2

Revisions (0)

No revisions yet.