Extension is available for other Visual Studio versions:
When you are doing Test Driven Development (TDD) you are constantly switching back and forth between production code and test classes.
As it’s good idea to have those files in separate projects, it’s sometimes very hard to find test code for a class and vice-versa.
Some time ago I decided to write a simple Visual Studio macro, that solves this problem.
It’s based on the convention that all your test classes have Test or Tests suffix (e.g. CSVReader.cs and CSVReaderTests.cs)
I’m far from being VB expert, so the code is not perfect (Why does VS use Visual Basic for Macros?):
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports System.Diagnostics
Imports System.IO
Public Module MainModule
Dim _patterns As String() = {"{0}Test", "{0}Tests"}
Dim _reversePatterns As String() = {"Tests", "Test"}
Sub GoToTest()
If DTE.SelectedItems.Count = 0 Then
Return
End If
Dim fullFileName As String = DTE.ActiveDocument.Name
Dim fileName As String = Path.GetFileNameWithoutExtension(fullFileName)
Dim extension As String = Path.GetExtension(fullFileName)
If IsTestFile(fileName) Then
For Each reversePattern As String In _reversePatterns
If fileName.Contains(reversePattern) Then
TryOpen(fileName.Replace(reversePattern, "") + extension)
End If
Next
Else
For Each pattern As String In _patterns
TryOpen(String.Format(pattern, fileName) + extension)
Next pattern
End If
End Sub
Function IsTestFile(ByVal fileName As String)
For Each reversePattern As String In _reversePatterns
If fileName.Contains(reversePattern) Then Return True
Next
Return False
End Function
Function TryOpen(ByVal fileName As String) As Boolean
Dim item As EnvDTE.ProjectItem
item = FindItem(FileName)
If Not (item Is Nothing) Then
OpenItem(item)
Return True
End If
Return False
End Function
Function FindItem(ByVal fileName As String) As EnvDTE.ProjectItem
If String.IsNullOrEmpty(fileName) Then
Return Nothing
End If
Dim item As EnvDTE.ProjectItem = DTE.Solution.FindProjectItem(fileName)
Return item
End Function
Sub OpenItem(ByVal item As EnvDTE.ProjectItem)
item.Open()
item.Document.Activate()
End Sub
End Module
How to install:
Start Visual Studio and go to Tools/Macros/Load Macro Project…:
Right click on the Visual Studio toolbar, and select customize:
Select ‘Macros’ category and find ‘GoToTest’ Macro:
Of course you can change the name of the button.
And finally the macro itself:
GotoTestMacro
Posted in Programming, Tools | Tags: NavigateToTest, Unit testing, vs
As I always have problem synchronizing my office and home machine’s templates I thought this would be good place to store them.
Inline templates (LiveTemplates.xml)
test
[Test]
public void Method_Condition_Result()
{
$END$
}
setup
[SetUp]
public void SetUp()
{
$END$
}
record
using(mocks.Record())
{
$END$
}
play
using(mocks.Playback())
{
$END$
}
File templates (FileTemplates.xml)
NUnitTestFile
using NUnit.Framework;
namespace $Namespace$
{
[TestFixture]
public class $FileName$
{
[Test]
public void Method_Condition_Result()
{
}
};
}
FileTemplates
LiveTemplates
Posted in Programming, Tools | Tags: C#, ReSharper, Unit testing
In most applications we have some kind of assembler classes, that create models used in the presentation layer:
public class EntityComboModelAssembler
{
public List<comboBoxModel> CreateComboBoxModels(IList<entity> entities)
{
List<comboBoxModel> list = new List<comboBoxModel>();
foreach (Entityentity in entities)
{
list.Add(new ComboBoxModel(entity, entity.Name));
}
return list;
}
}
It is possible to write this code in 1 (one) line of code:
public class EntityComboModelAssembler
{
public List<comboBoxModel> CreateComboBoxModels(IList<entity> entities)
{
return entities.AsList().ConvertAll(x => new ComboBoxModel(x, x.Name));
}
}
We can also remove AsList method by using extension method that adds ConvertAll method to IList interface:
public static class IListExtensions
{
public static List<tout> ConvertAll<tin, TOut>(this IList<tin> source, Converter<tin, TOut> converter)
{
return source.ToList().ConvertAll(converter);
}
}
And the final code:
public class EntityComboModelAssembler
{
public List<comboBoxModel> CreateComboBoxModels(IList<entity> entities)
{
return entities.ConvertAll(x => new ComboBoxModel(x, x.Name));
}
}
Posted in Programming | Tags: C#
PostSharp is AOP (Aspect-Oriented-Programming) framework (www.sharpcrafters.com).
It transparently inserts itself in the build process and post-processes the compiled assembly.
To enable PostSharp in your project you need to download and run the PostSharp installer, and add appropriate references in your project.
However if your project is in SVN, and you are not the only one compiling it (other developers, CI machine) most likely you don’t want to run PostSharp installer on all the machines.
There is a way to introduce PostSharp transparently to your project.
- Put all the PostSharp files in the LibPostSharp folder of your project and add this folder to SVN.
- Modify the .csproj file: After the last ItemGroup following xml must be inserted:
<propertyGroup>
<dontImportPostSharp>True</dontImportPostSharp>
<!-- Add the next line if you are using Visual Studio 2010 -->
<!-- <postSharpUseCommandLine>True</postSharpUseCommandLine>-->
</propertyGroup>
- Modify the .csproj file: After the
<import Project="$(MSBuildToolsPath)Microsoft.CSharp.targets" />
following xml must be inserted:
<import Project="..LibPostSharpPostSharp.targets" />
The whole change should be similar to this sample:
</itemGroup>
<propertyGroup>
<dontImportPostSharp>True</dontImportPostSharp>
</propertyGroup>
<import Project="$(MSBuildToolsPath)Microsoft.CSharp.targets" />
<import Project="..LibPostSharpPostSharp-1.5.targets" />
</project>
Posted in Programming | Tags: C#, PostSharp
If you are doing WPF development, most likely you are tired of writing property implementations that raise PropertyChanged event manually:
public class MainWindowViewModel : ViewModel
{
private string _message;
public string Message
{
get
{
return _message;
}
set
{
_message = value;
OnPropertyChanged("Message");
}
}
// ...
}
PostSharp is a great tool to make such things simplier.
Let’s look at the specific ViewModel class that has a Message property that is bound to some UI element using XAML:
public class MainWindowViewModel : ViewModel
{
[RaisePropertyChanged]
public string Message { get; set; }
// ...
}
Notice the RaisePropertyChanged attribute, which we’ll implement later.
Here’s our base ViewModel class that provides actual implementation of the INotifyPropertyChanged interface:
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged
= delegate { };
public void OnPropertyChanged(string propertyName)
{
PropertyChanged(this,new PropertyChangedEventArgs(propertyName));
}
};
Finally the PostSharp attribute:
[Serializable] // required by PostSharp
public class RaisePropertyChangedAttribute : OnMethodBoundaryAspect
{
private string _propertyName;
/// <summary>
/// Executed at runtime, after the method.
/// </summary>
public override void OnExit(MethodExecutionEventArgs eventArgs)
{
ViewModel viewModel = (ViewModel)eventArgs.Instance;
viewModel.OnPropertyChanged(_propertyName);
}
public override bool CompileTimeValidate(MethodBase method)
{
if (IsPropertySetter(method))
{
_propertyName = GetPropertyName(method);
return true;
}
return false;
}
private static string GetPropertyName(MethodBase method)
{
return method.Name.Replace"set_", "");
}
private static bool IsPropertySetter(MethodBase method)
{
return method.Name.StartsWith("set_");
}
};
Note that we are validating if the method is in fact a property only during compilation time using CompileTimeValidate method.
During compile time appropriate invocations of OnPropertyChanged method will be injected after every set operation applied to the Message property.
Posted in Programming | Tags: C#, MVVM, PostSharp, WPF