I’ve been using a BDD macro based on the one JP Boodhoo published for getting more descriptive test names along with a R# template so that I can type “test” + tab, type the test name (with spaces) and then hit Alt+- and voila – BDD style test names.
This worked well for a while until some point where R# started to do autocompletion on the test name as I typed (for instance, typing ‘Check that blah is not null’ often ended up as ‘Check that blah is NotImplementedException null’). That was OK though after a quick rework of the R# template and macro so R# wraps the test name in quotes which the macro then removes.
But R# doesn’t format the end result as well (the method braces don’t indent correctly) and this bugged me for a while.
So, a quick change to the macro and the R# template and now it’s much more smooth. Typing ‘tests’ + tab and R# outputs public class “FIXTURENAME” (with fixturename highlighted and ready to type over). Type out the name of the fixture, Alt+- and the macro replaces spaces, puts in the [TestFixture] attribute, drops in the opening and closed braces and puts the caret right where I want it. Sweet.
Do the same with ‘test’ + tab, type test name, Alt+- and you get the same for a test. Extra sweet.
This is the BDD macro:
1: Imports System
2: Imports System.Windows.Forms
3: Imports EnvDTE
4: Imports EnvDTE80
5: Imports System.Diagnostics
6:
7: Public Module CodeEditor
8: Private Const INDENT_SIZE As Integer = 4
9:
10: Public Sub ReplaceSpacesInTestNameWithUnderscores()
11: If DTE.ActiveDocument Is Nothing Then Return
12: Dim wrCS As Boolean = DTE.Properties("TextEditor", "CSharp").Item("WordWrap").Value
13:
14: Try
15: DTE.Properties("TextEditor", "CSharp").Item("WordWrap").Value = False
16: Dim selection As TextSelection = CType(DTE.ActiveDocument.Selection(), EnvDTE.TextSelection)
17: Dim textPoint As TextPoint = CType(selection.ActivePoint, TextPoint)
18: Dim line As Integer = textPoint.Line
19: Dim offset As Integer = textPoint.LineCharOffset
20: Dim index As Integer
21:
22: selection.SelectLine()
23: If selection.Text = "" Then Return
24:
25: Dim methodIndex As Integer = selection.Text.IndexOf("public void ")
26: Dim classIndex As Integer = selection.Text.IndexOf("public class ")
27:
28: If (methodIndex < 0 AndAlso classIndex < 0) Then
29: selection.MoveToLineAndOffset(line, offset)
30: Return
31: End If
32:
33: index = CType(IIf(methodIndex >= 0, methodIndex, classIndex), Integer)
34:
35: If methodIndex >= 0 Then
36: HandleTestMethod(selection, index)
37: Else
38: HandleTestClass(selection, index)
39: End If
40: Catch ex As Exception
41: MsgBox(ex.Message)
42: Finally
43: DTE.Properties("TextEditor", "CSharp").Item("WordWrap").Value = wrCS
44: End Try
45: End Sub
46:
47: Private Sub HandleTestClass(ByVal selection As TextSelection, ByVal index As Integer)
48: Dim whiteSpace As String = GetWhiteSpace(selection, index)
49: HandleTestNameFormatting(selection, "public class ", index)
50: AddAttribute(selection, index, "[TestFixture]", whiteSpace)
51: AddBraces(selection, index, whiteSpace)
52: End Sub
53:
54: Private Sub HandleTestMethod(ByVal selection As TextSelection, ByVal index As Integer)
55: Dim whiteSpace As String = GetWhiteSpace(selection, index)
56: HandleTestNameFormatting(selection, "public void ", index)
57: AddAttribute(selection, index, "[Test]", whiteSpace)
58: AddBraces(selection, index, whiteSpace)
59: End Sub
60:
61: Private Sub AddAttribute(ByVal selection As TextSelection, ByVal index As Integer, ByVal attribute As String, ByVal whiteSpace As String)
62: selection.LineUp()
63: selection.SelectLine()
64: If selection.Text.Trim <> attribute Then
65: selection.Insert(selection.Text & whiteSpace & attribute & vbCrLf)
66: End If
67: selection.LineDown()
68: End Sub
69:
70: Private Function AddIndent(ByVal spacer As Char) As String
71: Return String.Empty.PadRight(INDENT_SIZE, spacer)
72: End Function
73:
74: Private Sub AddBraces(ByVal selection As TextSelection, ByVal index As Integer, ByVal whiteSpace As String)
75: selection.SelectLine()
76: If selection.Text.Trim <> "{" Then
77: selection.Insert(String.Format("{0}{4}{1}{0}{2}{1}{0}{5}{1}{3}", whiteSpace, vbCrLf, AddIndent(whiteSpace(0)), selection.Text, "{", "}")) ' & whiteSpace & AddIndent(whiteSpace(0)) & vbCrLf & "}" & vbCrLf)
78: selection.LineUp()
79: selection.LineUp()
80: selection.LineUp()
81: selection.EndOfLine()
82: Else
83: selection.LineUp()
84: selection.EndOfLine()
85: End If
86: End Sub
87:
88: Private Function GetWhiteSpace(ByVal selection As TextSelection, ByVal index As Integer) As String
89: Return selection.Text.Substring(0, index)
90: End Function
91:
92: Private Sub HandleTestNameFormatting(ByVal selection As TextSelection, ByVal prefix As String, ByVal index As Integer)
93: Dim whiteSpace As String = GetWhiteSpace(selection, index)
94: prefix = whiteSpace + prefix
95: Dim description As String = selection.Text.Replace(prefix, String.Empty).Trim
96: If description(0) = """" Then
97: Dim lastQuote As Integer = description.LastIndexOf("""")
98: If lastQuote = 0 Then
99: description = description.Substring(1)
100: Else
101: Dim endOfDescription As String = description.Substring(lastQuote + 1)
102: description = description.Substring(1, lastQuote - 1) + endOfDescription
103: End If
104: End If
105: Dim text As String = prefix + description.Replace(" ", "_").Replace("'", "_") + vbCrLf
106: selection.Delete()
107: selection.Insert(text)
108: selection.LineUp()
109: End Sub
110: End Module
For the ReSharper templates, open up the live templates and add a template called ‘tests’ with the body of template as below:
public class "$FIXTURENAME$"
And then another one called ‘test’ with the body as
public void "$TESTNAME$"()
Mark both of these as available for C# only (or if for VB.Net, adjust the template body for the VB equivalent), and for the ‘test’ one, mark this as available only where a method declaration is allowed.
That’s it. Now you can get into the flow of typing ‘test’ TAB ‘name of test’ Alt+- and then typing in the test itself.

No comments yet
Comments feed for this article