patterncsharpMinor
Integrating Unit Testing functionality into an old COM-based IDE
Viewed 0 times
intointegratingtestingbasedidecomoldfunctionalityunit
Problem
My
So I proceeded to port my VBA code to C#, and implemented the
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
```
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
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:
then you can raise an event like this:
-
In
which you could pull up into the
-
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.