Overriding MSBuild variables via command line options
While working on a build script for the Pex Extensions project, I wanted to be able to specify the version of Pex which the project was built against for use within the AssemblyInfo and file names. This build script is being executed manually in order to create all the zip files to upload but I didn't want to have to manually edit the script to set the value. I wanted to provide the version when I executed MSBuild via the command line as a command line argument.
After a bit of searching on MSDN, I found that you can override any variables created within the PropertyGroup. At the top of your build script, you generally define your variables within the PropertyGroup to specify paths, versions etc. Within my build script, my PropertyGroup looked like this:
<PropertyGroup>
<BuildDir>$(MSBuildProjectDirectory)</BuildDir>
<PexVersion>0.6</PexVersion>
</PropertyGroup>
Using the /p: command line switch, I can override the PexVersion property by executing the script as follows:
> msbuild Pex.msbuild /p:PexVersion=0.6.30728.0
If I forget to set the argument, the value set within the script will be used.
Labels: MSBuild
Continuous Integration Builds for CodePlex Projects
As many of you might be aware, I maintain the IronEditor project on CodePlex. I like CodePlex, I find the wiki and issue tracking to be useful, but I find the directory structure and searchablity of projects on the site to be most useful. However, the one thing which I wish it could offer, and this goes for Google Project Hosting as well, is a continuous integration server. I would like to know that after I have pushed my changes to CodePlex, that it does actually compile.
As I've posted before, I run TeamCity on my home machine as it is free and easy to configure. As TeamCity can connect to Team Foundation Server (what CodePlex runs under the covers), I decided I would just be able to connect to the CodePlex servers and threat it like any normal source control system.
Sadly, I was wrong. When I tried to connect, I found the following (extremely helpful) error:
If anyone knows the reason why this failed, please leave a comment.
However, all is not lost! CodePlex have created the SVNBridge, a small application which runs on your local machine, or in this case your CC server. This translates all SVN commands into TFS commands, the result is that you can connect to CodePlex using SVN clients, one of which is TeamCity!
Connecting TeamCity via SVNBridge to CodePlex
SVNBridge is a single executable. It lives in the system tray and listens for communications on a particular port, in my case 8081.
In order to connect to SVNBridge, and as such your CodePlex project you must use a particular URL. The URL is your SVNBridgeAddress/YourCodePlexServer/YourProject
For example, IronEditor lives on tfs03.codeplex.com and in order for me to connect via the bridge my URL would be:
http://localhost:8081/tfs03.codeplex.com/IronEditor
With my setup, I simple wanted to be able to click run and TeamCity go off, download the latest code from TFS, build my solution and execute my unit tests again just to be sure I haven't broken anything (or in my case simply forgot to upload the latest code changes).
In order to connect TeamCity to CodePlex, you simply need to use the Subversion VCS settings and point it at your SVNBridge. Below, are my settings for IronEditor. The username and password you need to use to connect are your website login details.
On TeamCity's dashboard, I now have my new CodePlex build along with my local IronEditor build, both run the IronEditor.build MSBuild script, they just pull the sources from different locations. After I have pushed my changes to CodePlex, I manually click run, and off it goes. The reason I don't have it manually checking is because it's rare I push changes to codeplex and as such I'm happy to be in control of when it happens.
TeamCity is now happily talking to my CodePlex repository, building as and when asked. If you happen to have a spare server, or a windows home server, then you could run this setup from there, have it automatically check for modifications with all the developers on your project benefiting.
Labels: CodePlex, IronEditor, MSBuild, TeamCity
How to have Pex generate NUnit, MbUnit and XUnit tests
By default, Pex will generate MSTEST tests, however that doesn't mean you are constrained to using MSTEST for your project. The Pex Extensions project on CodePlex has a set of extensions which allows Pex to generate code for the three main test frameworks. I've just committed some changes to make the code work against the newly released Pex 0.6. In order to generate tests for a particular framework, you need to follow these instructions.
XUnit
2) In your test project's AssemblyInfo.cs. Add the attribute - [assembly: Pex.Xunit.PexXunitPackage]
3) Pex will now start generating xUnit tests.
NUnit
2) In your test project's AssemblyInfo.cs. Add the attribute - [assembly: Pex.NUnit.PexNUnitPackage]
3) Pex will now start generating NUnit tests.
MbUnit v3
1) Reference Pex.MbUnit.dll
2) In your test project's AssemblyInfo.cs. Add the attribute - [assembly: Pex.MbUnit.PexMbUnitPackage]
3) Pex will now start generating MbUnit v3 tests. A MbUnit extension is also included within the Gallio\MbUnit package.
Note: At the moment, you need to download the source code from codeplex and compile the binaries yourself, there is a single solution file which will build everything.
You also need to ensure both the extensions and your test project are built against the same version of the unit testing framework, otherwise there will be a type mismatch and Pex won't be able to generate any tests.
Labels: Pex
Very exciting news! Red Gate's .Net Reflector
Red Gate announced today that, under a new agreement, it will be responsible for the future development of .NET Reflector, the popular tool authored by Lutz Roeder.
Reflector is one of the must-have tools if you are a .Net developer or tester, allowing you to really understand the software and APIs in a very unique fashion. Personally, I always have a copy of Reflector open on my desktop and without it .Net development would be very different!
If you are interested knowing more about this agreement, I would recommend you read the interview between James Moore and Lutz Roeder on Simple Talk. The most important part – “Red Gate will continue to offer the tool for free to the community.”
If you haven’t tried Reflector yet, I really recommend you download it. It could change the way you develop .Net applications - http://reflector.red-gate.com/
MVC Html.Resolve() - Resolve URLs to your page
For the current MVC application I'm developing, I needed to host the site under a IIS Virtual Directory. This caused a problem as I can't use the following code:
<%=Html.Image("~/Content/icon_green.gif") %>
This would ignore the fact that I was under a Virtual Directory and point to the root site - http://mysite/ instead of http://mysite/myvirtual/ like I want.
Rob Conery mentioned a Html.ResolveUrl method, however I couldn't find the method on the HtmlHelper so I wrote my own. The method is called Resolve and is an extension to the HtmlHelper within MVC. Here is one of the unit tests for it.
[Fact]
public void Resolve_With_IIS_Virtual_Directory_Returns_Full_Path()
{
HtmlHelper html = CreateHtmlHelper("http://localhost/TestProject");
string result = html.Resolve("~/Content/t.jpg");
Assert.Equal("http://localhost/TestProject/Content/t.jpg", result);
}
Implementation is very simple, we prefix the virtual directory with the application path if required.
public static string Resolve(this HtmlHelper helper, string virtualUrl)
{
if (!virtualUrl.StartsWith("~/"))
return virtualUrl;
virtualUrl = virtualUrl.Remove(0, 2);
string applicationPath = helper.ViewContext.HttpContext.Request.ApplicationPath;
if(string.IsNullOrEmpty(applicationPath) || !applicationPath.EndsWith("/"))
{
applicationPath = applicationPath + "/";
}
return applicationPath + virtualUrl;
}
However, this brought up an interesting point. How do you test extension methods? It turns out, you can easily test the methods, you just need to create the object they are extending and call the method - obviously.
The problem with this is, HtmlHelper (the object I'm extending) has a number of dependencies, for example in my Resolve method I'm calling HttpContext in order to get the ApplicationPath.
In order to create the HtmlHelper object, I added myself a little helper method. I'm using Rhino Mocks 3.5 in order to generate the stubs, sadly ViewContext requires a number of different parameters (the only one I care about is httpContext), as a result I had to generate a number of different stubs.
private HtmlHelper CreateHtmlHelper(string appPath)
{
HttpContextBase httpContext = MockRepository.GenerateStub<HttpContextBase>();
HttpRequestBase httpRequestBase = MockRepository.GenerateStub<HttpRequestBase>();
httpRequestBase.Stub(h => h.ApplicationPath).Return(appPath);
httpContext.Stub(h => h.Request).Return(httpRequestBase);
ViewContext viewContext = MockRepository.GenerateStub<ViewContext>(httpContext,
new RouteData(),
MockRepository.GenerateStub<IController>(),
"Test", "MasterTest", new ViewDataDictionary(),
new TempDataDictionary(httpContext));
return new HtmlHelper(viewContext, MockRepository.GenerateStub<IViewDataContainer>());
}
The end result is that I have my HtmlHelper object created which returns a known ApplicationPath, this allows me to fully test my extension method. However, I have had put in some additional effort due to requiring ViewContext.
Download Tests: HtmlExtensionTests.txt
Download Implementation: Html.txt
Labels: MVC
Using 'Where' command to find location of file
When using the command line, your $PATH variable holds different paths to search when you enter a command. Today, I was using the Visual Studio 2008 command prompt, which has setup my $PATH variable to point at known locations relating to .Net and Visual Studio.
I could happily type in 'sn' in order to execute the program, however I had no idea where that exe lived and I needed the full path. I thought I would have to search using Windows, however I found that there is a 'where' command which will return you the full path for a command.
C:\Program Files\Microsoft Visual Studio 9.0\VC>where sn
C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\sn.exe
Surprisingly useful!!
Taking a look at NUnit 2.5 Alpha 3
It's always interesting to see how the different unit testing frameworks approach automated testing, each framework has it's own style, approach and feature set with everyone having their own view on which framework everyone should use. One of the more (you could say most) popular .Net framework is NUnit and over the past few months Charlie has been working on v2.5 so I thought it was about time I took a look.
Parameterised Tests (Documentation can be found here Parameterized Tests)
Similar to XUnit and MbUnit, NUnit 2.5 includes the concept of parameterised tests. RowTest was included in 2.4.7, however additional attributes have now been included.
ValuesAttribute
The first new attribute allows for combinational style testing, this is where two sets of inputs are combined to create each possible test combination. In certain situations useful - always good to have in the toolbox, however generally I wouldn't need to use this on a day-to-day basis. MbUnit has had this for a while, however I prefer the syntax of this approach, which I think is a similar syntax to MbUnit V3.
To implement this, you add the ValuesAttribute, which takes an object array for the test values, before the method parameter.
[Test]
public void ValuesAttributeTest([Values(1,2,3, 20)] int v, [Values(9,8,7)] int v2)
{
Assert.IsTrue(v < v2);
}
When NUnit loads this up, they create a combination of the test values, as a result we have 12 tests created. If we had another parameter of the test, for example with 3 possible values, then we would have another possible combination and we would have 36 tests. As a result, you can very quickly build up a good selection of test cases.
RangeAttribute
Similar to the ValuesAttribute, however instead of you defining the values, you define the range of possible values which NUnit then creates tests for. You define the range (min, max) and NUnit does the rest. The values are then combined in a combinational style.
[Test]
public void RangeAttributeTest([Range(1,100)] int v, [Range(1,100)] int v2)
{
Assert.IsTrue(v < v2);
}
The test creates produces then looks something like this:
RandomAttribute
Similar to the two previous attributes, Random produces a set of random input. You can either give it a count of the inputs to use, as I have done with the first attribute which produces 10 random values, while in the second parameter I provide the min and max range for the random values together with the amount of data to produce.
[Test]
public void RandomAttributeTest([Random(10)] int v, [Random(1, 50, 10)] int v2)
{
Assert.IsTrue(v < v2);
}
However, I'm not sure how useful testing against random data would actually be?
TestCaseAttribute
This attribute is similar to RowTest, however as part of the TestCase you can set your own TestName which I think is actually really useful.
[TestCase("Test1", TestName = "This is a great!", Description = "My first test")]
[TestCase("Test2")]
[TestCase("")]
public void TestCaseAttributeTest(string test)
{
Console.WriteLine(test);
Assert.IsNotEmpty(test);
}
The TestCase is then reflected In the GUI and report. The first two tests use the test method name plus their parameter inputs, while the third uses the TestName property we set on the TestCaseAttribute.
Also as part of the TestCaseAtribute, you are able to provide the Result. Generally, the expected result is passed in as a parameter and verified within the test itself. With this approach you have the result as part of the TestCase itself, with the test returning it's result which NUnit then compares to decide if the test has passed. This does make more sense as the parameters of the test as then really test inputs with the test output being verified as an output, a small difference however it is more logical.
[TestCase("Test1", TestName = "This is a great!", Description = "My first test", Result = 5)]
public int TestCaseAttributeTest(string test)
{
Console.WriteLine(test);
return test.Length;
}
This approach to testing has a lot of potential use cases and opportunities as it really increases test case (code) reuse and test maintenance.
TestCaseFactoryAttribute
Similar to MbUnit's FactoryAttribute, you define a class which yield returns each TestCaseData object. It has the advantage of using a fluent interface to define all the different properties, such as results and the test name. While I have hardcoded the 4 test cases here, there is nothing stopping you dynamically creating these.
[Test,Factory(typeof(MyFactoryClass))]
public int FactoryAttributeTest(int a, int b)
{
Console.WriteLine(a / b);
return a/b;
}
public class MyFactoryClass
{
[TestCaseFactory(typeof(int), typeof(int))]
public static IEnumerable TestCases
{
get
{
yield return new TestCaseData(12, 3).Returns(4);
yield return new TestCaseData(12, 2).Returns(6);
yield return new TestCaseData(12, 4).Returns(3);
yield return new TestCaseData(0, 0)
.Throws(typeof(DivideByZeroException))
.WithName("DivideByZero")
.WithDescription("An exception is expected");
}
}
}
The TestCases then look like this:
New Assertions
Assert.Throws<T>
Simple, straight forward. Does the method call throw can exception?
[Test]
public void ThrowException()
{
Assert.Throws<Exception>(throwEx);
}
public void throwEx()
{
throw new Exception("Test");
}
Assert.DoesNotThrow
Simpler approach, Assert that the method does not throw any exceptions when it is called.
[Test]
public void doesNotThrowExTest()
{
Assert.DoesNotThrow(doesNotThrowEx);
}
public void doesNotThrowEx()
{}
Others
RequiredAddinAttribute
This is extremely useful if you are writing your own NUnit addins, as it is very important that the addin is available before you attempt to execute your tests. After adding attributes about the addins you require,
[assembly: RequiredAddin("MyTestFixtureAddin")]
[assembly: RequiredAddin("MyTestAddin")]
[assembly: RequiredAddin("MyDecoratorAddin")]
If they are not available and you execute the test, it will fail but will actually tell you the reason why.
PlatformAttribute
Finally, there is a new PlatformAttribute. This attribute defines which platforms the test is allowed to run on, really useful if you have issues with a certain target platform, or if you have a set of tests only targeting a platform, such as mono.
[Test]
[Platform(Exclude="Win98,WinME", Reason = "This only works on Windows 2000 and above")]
public void OnlyWorksWith2000OrHigher()
{
Assert.IsTrue(Environment.OSVersion.Version.Major > 5);
}
[Test]
[Platform(Include = "Win98,WinME")]
public void BugOnWin98()
{
Assert.IsTrue(Environment.OSVersion.Version.Major > 5);
}
The list of possible platforms can be found here: http://nunit.org/index.php?p=platform&r=2.5
When the test is executed on an invalid platform, the test is skipped.
This post has summarised all of the interesting bits of the new Alpha release. In future releases, I expect to see some changes going forward before the final 2.5 release. It's nice to see NUnit taking the different approaches from the different frameworks and incorporating them with their own approach, hopefully v3 will have some really interesting concepts. The main feature missing at the moment are data driven test attributes, such as pulling test cases from CSV or SQL Server, but a framework has an additional extension point to make this attribute easier to write. After this I think most of the missing features would be more suitable in NUnit 3.0.
Release Notes: http://nunit.com/index.php?p=releaseNotes&r=2.5
Download: http://nunit.com/index.php?p=download
Mono and File Paths
The joy of developing cross platform applications!!
When dealing with files and paths on a windows based platform you always use a backslash (\) as the path separator, for example 'Config\Settings.xml'. Append the full path onto the beginning and you would be able to load the settings. However, if your application needs to run on top Linux or Mac OS X (Mono) then file paths are slightly different. Instead of 'Config\Settings.xml' you need to use 'Config/Settings.xml'. Notice the all important forward slash (/)! It's a simple mistake to make and it can take a few moments to realise what the problem is.
If you wanted to be really hard core (and correct), you would use Path.DirectorySeparatorChar property to define your separator. Alternatively, you might want to look at IOMap which should solve this mismatch problem for you.
Variations like this is a great reason why you should run your unit\integration tests on both platforms as part of your build.
Labels: Mono
Deploying ASP.net MVC to IIS 6 still returns 404
This morning I was checking my deployment instructions for an ASP.net MVC application, ideally this would be automated but that is my next task.
I was following Option 1 Steve Sanderson wrote on his blog, where you use Wildcard mapping for aspnet_isapi.dll. After setting up this while card mapping, you should be able to use the same pretty URLs without any modifications or additional mappings.
Unfortunately I didn't read the post correctly and forgot to untick 'Verify that file exists',
As a result, I kept receiving 404 error messages - yet I knew that the path was correct.
It took me a while to figure out that I had forgot to untick the verify that file exists box. Once the box had been set correctly, my content was serving again.
This raised an interesting question - why does 'Verify that file exists' need to be unticked? The executable is a 'Win32 DLL (ISAPI extension)', but not sure why this needs to be unticked - answers on a postcard (or a comment)!
How To: Script a SQL Database Schema and Data to a single file
At the moment I'm working on a web application, using ASP.net MVC connected to SQL Server 2005. As part of this work, I wanted to script out my current database schema into a flat file. I had created my SQL Database using SQL Management Studio on my laptop, but I wanted to reliability deploy this onto a machine in the office.
Luckily, I had Red Gate SQL Compare to hand (Surprising as I work for Red Gate :))! This allows for a number of different approaches, such as connecting to the office via VPN and syncing my two databases or syncing to a scripts folder, but I found SQL Compare could create a single SQL file containing my database schema just using the command line tool.
The command below will sync my local Northwind database schema into a file called Schema.sql. If the file already exists, I override it.
SQLCompare.exe /database1:Northwind /scriptfile:"C:\Northwind\Schema.sql" /force
Perfect!! I can now use SQL Cmd or SSMS to execute the file to produce my schema.
The same command works for SQL Data Compare, allowing me to script all the data in the database to a single sql file.
SQLDataCompare.exe /database1:Northwind /scriptfile:"C:\Northwind\Data.sql" /force
NOTE: These scripts do not include the USE statement, as such they will run under the database your connected on. You just need to be aware of what database your connected to or which database you use in your connection string
Labels: Red Gate





Social networks
Twitter GitHub SlideShare