4

I have a bit of a silly issue:

I have a large number of unit tests which all have method attributes like this:

    [TestMethod]
    [Owner("me")]
    [Description("It tests something.")]
    [TestProperty(TC.Name, "Some Test")]
    [TestProperty(TC.Requirement, "req203")]
    [TestProperty(TC.Reviewer, "someguy")]
    [TestProperty(TC.Environment, "MSTest")]
    [TestProperty(TC.CreationDate, "24.01.2012")]
    [TestProperty(TC.InternalTcId, "{9221A494-2B31-479D-ADE6-D4773C2A9B08}")]
    public void TestSomething()
    { ... }

(If you're wondering: these attributes are used for automated testing and requirement coverage stuff.. )

Now, unfortunately these attributes are in a different order at most test methods - which makes it a bit messy to review and such. So I'm looking for a way to order them..

Would you know any other way than rearranging them manually?

(I thought about writing some VS plugin or so) - I'm just wondering whether I'm really the first person with that wish.

Efrain
  • 3,248
  • 4
  • 34
  • 61
  • ordering based on what idea ? – Tigran Jan 24 '12 at 14:35
  • @Efrain Not an answer per-se as its a one-liner, but you could use Powershell scripts to edit the *cs files in place. No need to write a Visual Studio add-in. You get the full .NET framework in a scripting language. I've just learned how to use it recently - to modify csproj (XML) files as a pre-deployment step: http://stackoverflow.com/questions/8963328/powershell-to-remove-and-add-reference-to-csproj – Dr. Andrew Burnett-Thompson Jan 24 '12 at 14:46
  • @Tigran alphabetic would be fine I guess. however, a perfect solution would include a lookup of all present attributes, and then displaying a window that allows the user to define a hierarchical sequence. – Efrain Jan 24 '12 at 15:53

2 Answers2

4

Open up the Macro Explorer - and paste this code into a module (It's straight from my own little collection of macros):

Sub Sort()
    Dim selection As EnvDTE.TextSelection = DTE.ActiveDocument.Selection
    If selection Is Nothing Or String.IsNullOrWhiteSpace(selection.Text) Then
        Exit Sub
    End If

    Dim lines As String() = selection.Text.Split(vbCrLf.ToCharArray(), StringSplitOptions.RemoveEmptyEntries)

    If lines.Length <= 1 Then Exit Sub

    lines = lines.OrderBy(Function(s As String) s, StringComparer.CurrentCulture).ToArray()
    DTE.UndoContext.Open("Sort Lines")

    selection.Insert(String.Join(vbCrLf, lines))
    selection.SmartFormat()

    DTE.UndoContext.Close()
    DTE.StatusBar.Text = "Sort Lines complete"

    selection.SmartFormat()
End Sub

(just edited it as the try/end try wasn't really right - so I've taken it out)

Now you can bind a shortcut to this macro in VS - it uses a Linq OrderBy using the current culture's string comparer to sort the lines of the currently selected block of text. It should therefore group the attributes together accordingly.

If you need something that context-sensitive (i.e. the same attribute being called with different numbers of parameters) - then you'll need to do considerably more work.

Andras Zoltan
  • 41,961
  • 13
  • 104
  • 160
1

You are the first person with that wish :)

I would arrange them manually, but also, if you are looking for a more solid solution, then I would implement a property in the TestPropertyAttribute class int Index { get; set; } and set the order in which I want them processed. In that case, you can control which how attributes are read in the reflection code that reads them. This is how NHibernate does it.

[TestProperty(TC.Name, "Some Test", 0)]
[TestProperty(TC.Requirement, "req203", 1)]
Tomislav Markovski
  • 12,331
  • 7
  • 50
  • 72