This is a sample unit test written using the FluentAssert BDD framework.
[Test] public void Given_a_business_object_with_no_natural_keys() { Test.Verify( with_a_business_object_that_has_no_natural_keys, when_lookup_is_called, should_return_a_valid_notification); }
When my cursor is on one of the test actions and I hit alt-enter Resharper is usually smart enough to suggest creating a method.
Other times, however, Resharper doesn’t offer the option we need.
My solution to this problem is a Visual Studio macro that creates a void parameterless method for the “word” the cursor is on. This necessitates determining where the new method should be created e.g. top of the file, bottom of the file, just before the method, just after the method. I like to keep the new method close to the test when I’m first creating it so that means above or below the method. Initially I tried it above the method but learned that in my workflow I expect the new method to be added below the test. So how do we do that? We’ll write a Visual Studio macro to do the work.
First we need to copy the proposed method name. We’ll grab the word under the cursor and put it in a variable. Also, since we don’t want to affect the user’s copy-paste buffer we’ll do it within an undo context.
DTE.UndoContext.Open("AddBddMethod") DTE.ExecuteCommand("Edit.SelectCurrentWord") Dim name As String name = DTE.ActiveDocument.Selection.Text
Next to move to the end of the test method we’ll search for ‘}’ and close the find dialog when we’re done.
DTE.ExecuteCommand("Edit.Find") DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument DTE.Find.FindWhat = "}" DTE.Find.MatchCase = True DTE.Find.MatchWholeWord = False DTE.Find.Backwards = False DTE.Find.MatchInHiddenText = True DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral DTE.Find.Action = vsFindAction.vsFindActionFind If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then Throw New System.Exception("vsFindResultNotFound") End If DTE.Windows.Item("{CF2DDC32-8CAD-11D2-9302-005345000000}").Close()
We want one newline between the test method and the new method so we move the cursor one position to the right to get past the ‘}’ then add two newlines.
DTE.ActiveDocument.Selection.CharRight() DTE.ActiveDocument.Selection.NewLine() DTE.ActiveDocument.Selection.NewLine()
Next we’ll introduce the new method.
DTE.ActiveDocument.Selection.Text = "private void " DTE.ActiveDocument.Selection.Text = name DTE.ActiveDocument.Selection.Text = "()" DTE.ActiveDocument.Selection.NewLine DTE.ActiveDocument.Selection.Text = "{}"
Our method now looks like:
private void when_lookup_is_called() { }// <- cursor here
Now we want to set up to add contents to the new method so we move up between the ‘{}’ and add a newline.
DTE.ActiveDocument.Selection.LineUp() DTE.ExecuteCommand("Edit.BreakLine")
Our method now looks like:
private void when_lookup_is_called() { // <- cursor here }
Finally we need to close the undo context.
DTE.UndoContext.Close()
That’s it.
Next we need to add it as a Visual Studio macro. First open the macro editor.
Create a new module called “RecordingModule” under MyMacros.
Then replace the entire contents of the default macro with the macro we built:
Option Strict Off Option Explicit Off Imports System Imports EnvDTE Imports EnvDTE80 Imports EnvDTE90 Imports System.Diagnostics Public Module RecordingModule Sub Add_BDD_method() DTE.UndoContext.Open("AddBddMethod") DTE.ExecuteCommand("Edit.SelectCurrentWord") Dim name As String name = DTE.ActiveDocument.Selection.Text DTE.ExecuteCommand("Edit.Find") DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument DTE.Find.FindWhat = "}" DTE.Find.MatchCase = True DTE.Find.MatchWholeWord = False DTE.Find.Backwards = False DTE.Find.MatchInHiddenText = True DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral DTE.Find.Action = vsFindAction.vsFindActionFind If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then Throw New System.Exception("vsFindResultNotFound") End If DTE.Windows.Item("{CF2DDC32-8CAD-11D2-9302-005345000000}").Close() DTE.ActiveDocument.Selection.CharRight() DTE.ActiveDocument.Selection.NewLine() DTE.ActiveDocument.Selection.NewLine() DTE.ActiveDocument.Selection.Text = "private void " DTE.ActiveDocument.Selection.Text = name DTE.ActiveDocument.Selection.Text = "()" DTE.ActiveDocument.Selection.NewLine DTE.ActiveDocument.Selection.Text = "{}" DTE.ActiveDocument.Selection.LineUp() DTE.ExecuteCommand("Edit.BreakLine") DTE.UndoContext.Close() End Sub End Module
Finally, bind a keystroke to the macro and you’ll be able to create test actions very quickly.