I’m doing some work with TypeMock and I start to love it more and more. For example, how about removing your database completely from your continuous tests? Sure you can do some database testing during the nightly build, but please keep the tests as fast as possible.
A little story about a build Just a few days ago on a Friday my colleague Alex Thissen and I were planning to leave the building. Unfortunately after checking in some code, a few unit tests failed in Alex’s project. It were some really minor changes, but as it was 20:00 hours already, we weren’t as sharp anymore. After 4 trial-and-error sessions getting the test to work, we could go home. The code changes took only a few seconds, running the build took much, much longer. Mainly because Visual Studio 2008 for DB Professionals was deploying the database every time. What if we only needed that during the nightly build and actually had the continuous build running much faster?
Imagine a nice little table like the one on the right. Just some Class-A trainers in there. Imagine some code retrieving the trainers.
public List<MyTrainer> GetTrainers()
{
List<MyTrainer> trainers = new List<MyTrainer>();
using (SqlConnection con = new SqlConnection())
con.ConnectionString = @"Server=.\sqlexpress;database=courses;integrated security=sspi;";
con.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = "select * from trainers";
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
MyTrainer t = new MyTrainer();
t.Name = rdr["Name"].ToString();
trainers.Add(t);
}
return trainers;
Normal ADO.NET code for retrieving trainers and adding them to a collection of MyTrainer objects. We could just test this with a special test database so that we always get the same results. We could create a very easy test where we just execute the GetTrainers method and see what data it returns. But as this accesses the database you might want to do this in a nightly batch. To be a little more sure you don’t break the build at night, you can always run these tests from your local machine.
[TestMethod]
public void GetTrainers_DBAccessed_Return7Trainers()
DAL dal = new DAL();
List<MyTrainer> trainers = dal.GetTrainers();
Assert.IsNotNull(trainers);
Assert.AreEqual(7, trainers.Count());
Assert.AreEqual("Anko Duizer", trainers[0].Name);
But we really want to test the code without actually connecting to the database. You could stub out a lot, but that’s a lot of work. Especially because the datareader is very hard to stub out. I’ve once used a datareader that was running on a dataset with one ore more tables in it. Pretty nice, but still took a whole lot of code to fill the datareader initially.
When we want to use a mocking framework like TypeMock, it still requires some code. We need to actually mock out three objects and create expectations for them. Here’s the code.
[TestMethod, VerifyMocks]
public void GetTrainers_NoDBAccess_Return2Trainers()
using (RecordExpectations rec = RecorderManager.StartRecording())
con.ConnectionString = "";
cmd.CommandText = "";
SqlDataReader fakeReader = RecorderManager.CreateMockedObject<SqlDataReader>();
rec.ExpectAndReturn(cmd.ExecuteReader(), fakeReader);
rec.ExpectAndReturn(fakeReader.Read(), true).Repeat(2);
rec.ExpectAndReturn(fakeReader["name"].ToString(), "Dennis van der Stelt");
rec.ExpectAndReturn(fakeReader["name"].ToString(), "Alex Thissen");
Assert.AreEqual("Dennis van der Stelt", trainers[0].Name);
Assert.AreEqual("Alex Thissen", trainers[1].Name);
As you can see we set up a recorder and created expectations for the values that should be returned. The reader.Read method should return true twice so we can fill two MyTrainer objects with data. We then set expectations for the two times the name column is accessed using the reader. When finished recording, we actually execute the code we’re testing and mocking. Of course this is a very simple implementation, but it’s to show how to mock things out. For more advanced scenarios you should check the TypeMock manual.
Now let’s see how we would retrieve the same data with LINQ.
public List<Trainer> GetTrainersViaLINQ()
CoursesDataContext db = new CoursesDataContext();
var query = from t in db.Trainers
select t;
return query.ToList();
This is a lot less code. When we want to mock this out, we again use a recorder and just use the same code. However LINQ to SQL returns an IQueryable collection of Trainer objects. You can’t use recorder.Return(someList.AsQueryable()) inside the recording-block because then the AsQueryable would be mocked out as well. So we have to prepare the collection of trainers in advance.
public void GetTrainersViaLINQ_NoDBAccess_Return2Trainers()
var fakeTrainers =
(new [] {
new Trainer() { Name = "Dennis van der Stelt" },
new Trainer() { Name = "Alex Thissen" } }
).AsQueryable();
rec.Return(fakeTrainers);
IEnumerable<Trainer> trainers = dal.GetTrainersViaLINQ();
Assert.AreEqual(2, trainers.Count());
Assert.AreEqual("Dennis van der Stelt", trainers.ElementAt(0).Name);
Assert.AreEqual("Alex Thissen", trainers.ElementAt(1).Name);
You can see I prepared the fakeTrainers collection in advance, start recording and set the return value to the prepared collection. I then actually execute the code inside my tested class and assert that everything’s as expected.
How about this, a pc in/on a napkin to use, read, write, collaborate with and more…
As you see in the picture on the left, there are enough in the holder and you can grab one to work with. Or each member of the team grabs one and start drawing out ideas and exchange napkins to share ideas and work them out more.
When you combine napkins you can create larger surfaces and present something to the team. The idea sounds awesome and I can only hope something like this will become reality. For now, it’s just an idea from a contest. Unfortunately.
Marco mailed me this morning with the following sentence
Unit tests are meant to test functionality, NOT code! That means if you write your unit tests after the fact, you’re probably not focusing on the functionality.
This comes from two weblogs that have some unit testing comments. Jason Young posted the sentence and he refers to Obishawn who also has something to say. Why I’m writing this post is for two reasons. Or three actually. The first reason is that I liked the quote. The second reason is that Obishawn tries to prove that you should even test properties, something not many people do. But his argument is that it can grow to something that you definitely would want to test, so you should have a test in place to test the functionality. He also states that you should not trust your framework and although he’s probably right, I wouldn’t test my properties because I don’t trust the framework. If that’d be the case, it’d probably be enough to test a single property because with that I’d have tested them all. I know the .NET Framework has its bugs, but I hope to find these when writing tests that target my own code functionality.
Anyway, Obishawn also provides a few lines of code to prove you should test properties. I have written a small piece of code to expands on this a bit. There are three errors in it and maybe you can spot them. Although these are extremely simple (once you know which ones I mean) it’s an example of why you should seriously consider writing tests for all your code functionality.
public class CoD4 : Game
private List<string> _redPlayers;
private List<string> _bluePlayers;
private string _name;
public CoD4()
this.Name = "Call of Duty 4";
public List<string> BluePlayerCount
get { return BluePlayers.Count(); }
public string Name
get { return Name; }
public void AddPlayer(string name)
base.AddPlayer(name);
if (_redPlayers.Count <= _bluePlayers.Count)
_bluePlayers.Add(name);
else
_redPlayers.Add(name);
A little snippet that I use from time to time when I need information on how long something takes. Type ‘sw’ (without the quotes) and tab-tab.
Installation is easy, just create a file called “sw.snippet” in your %Documents%\Visual Studio 2008\Code Snippets folder and paste the following in the file. You can use it immediately without restarting Visual Studio.
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>Add Stopwatch code</Title>
<Shortcut>sw</Shortcut>
<Description>Code snippet for adding complete Stopwatch usage and display of elapsed time.</Description>
<Author>Dennis van der Stelt</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<References>
<Reference>
<Assembly>System.Diagnostics</Assembly>
</Reference>
</References>
<Code Language="csharp">
<![CDATA[Stopwatch sw = new Stopwatch();
sw.Start();
sw.Stop();
TimeSpan ts = sw.Elapsed;
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
Console.WriteLine(String.Format("\n\nProcessing time : {0}", elapsedTime));]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
You might know that I’m quite the Microsoft addict. While a lot of people are very sceptic with everything Microsoft releases, I tend to have a positive feeling for everything Microsoft releases, at first. After some experience, I might hate or love it, or just don’t use it because I don’t feel the need for it. Microsoft Sync, Parallel extensions and many more products and frameworks; after I get my hands dirty with it I’ll decide if it does any good for me or not.
About Office Live Workspace, I know there are many alternatives to it but I really want to give this a change. Everything looks good (I almost always like Microsoft GUI's), looks familiar, has a nice Office plugin and some other benefits. And hey, it’s a Microsoft product! ;-)
I just read they released new languages and that May was a very hectic month for them. But I seriously can’t believe why they don’t introduce folders. Everyone is crying out for folders but instead of folders, we get more languages and other stuff. So I thought, let’s see when they’ll introduce folders and went to their blogs. Of course (?) you have to login to place a comment. So I click the little Passport (or Windows Live ID) login icon at the top-right corner. But I get presented a login/registration screen. First thing I thought was that this was some phising attempt for my Windows Live ID username and password. Why use the icon and have a different registration system. Heck, why a different registration system at all? So I left the blogs and decided to write a long and boring post on my own weblog. And guess what, anonymous comments are enabled! :)
Anyway, I’ve registered for a workspace months ago and would really like to use it, but haven’t done so yet. Simply because of the lack of folders. I’m not even going to upload a small amount of folders to later find out I have to move every single one of them via a web interface.
Please introduce folders into Office Live Workspace! Thanks.
Two tools I absolutely love!
Windows Live Writer A new version was just released, June 2nd. Download it here.
Sysinternals ZoomIt Version 2.0 was released on May 28. I just downloaded that version myself and it has some nice features. However, I did not know about all 1.x existing features myself. I just saw a part of the TechEd keynote and noticed this guy was drawing rectangles and arrows. I thought : “What tool is this guy using? Can it be my favorite tool ZoomIt?” And yes he was!!!
Now I did not know that! New features in 2.0 (afaik) are:
Sw33t!!!
This has taken us some time; depending on which environment you are, telling Visual Studio 2008 for Database Professionals Edition (or simply DataDude) what user it should use to deploy the SQL scripts, during an automated build. We're working with Windows XP users, Windows Vista users and Windows 2008 Server. As you might now, XP uses the "ASPNET" user to run IIS and Vista and 2008 use the "Network Service" user.
We're using FinalBuilder, a most excellent product, which in turn is using MSBuild and were trying to figure out how to pass variables to MSBuild, who should pass them to DataDude, which in turn would have to pass them to SQLCommand. Sounds difficult, but when you've figured it out, it's quite easy! :-)
The goal is to use "Network Service" when automated and let the user specify what user to use when running locally.
Here are the steps we took
<PropertyGroup Condition=" '$(Configuration)' == 'Default' ">
<SetVariables>
<Variable Name="TargetUser" Value="ASPNET" />
</SetVariables>
</PropertyGroup>
<Variable Name="TargetUser" Value="$(DatabaseUser)" />
<DatabaseUser>aspnet</DatabaseUser>
If you're interested how to use this in FinalBuilder, here's how.
Good luck! :-)
It's happening
I'm using FinalBuilder to build and deploy websites on our test server. FinalBuilder is a great product, but our client is using Windows Server 2008 and FinalBuilder does not have actions for IIS7. I might add the actions to my weblog, but here's some code to create a new IIS7 website using C#.
Create a new solution and add a reference to C:\Windows\System32\InetServ\Microsoft.Web.Administration.dll. Paste the following code and you've got yourself a website on port 82 using the default application pool. In IIS it's named MyCoolWebsite.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Web.Administration;
namespace TestApp
class Program
static void Main(string[] args)
string siteName = "MyCoolWebsite";
string applicationPoolName = "DefaultAppPool";
string virtualDirectoryPath = "/";
string virtualDirectoryPhysicalPath = "C:\\temp\\";
string ipAddress = "*";
string tcpPort = "81";
string hostHeader = "";
string applicationPath = "/";
long highestId = 1;
using (ServerManager mgr = new ServerManager())
Site site = mgr.Sites["siteName"];
if (site != null)
return; // Site bestaat al
ApplicationPool appPool = mgr.ApplicationPools[applicationPoolName];
if (appPool == null)
throw new Exception(String.Format("Application Pool: {0} does not exist.", applicationPoolName));
foreach (Site mysite in mgr.Sites)
if (mysite.Id > highestId)
highestId = mysite.Id;
highestId++;
site = mgr.Sites.CreateElement();
site.SetAttributeValue("name", siteName);
site.Id = highestId;
site.Bindings.Clear();
string bind = ipAddress + ":" + tcpPort + ":" + hostHeader;
Binding binding = site.Bindings.CreateElement();
binding.Protocol = "http";
binding.BindingInformation = bind;
site.Bindings.Add(binding);
//site.Bindings.Add(bind, "http");
Application app = site.Applications.CreateElement();
app.Path = applicationPath;
app.ApplicationPoolName = applicationPoolName;
VirtualDirectory vdir = app.VirtualDirectories.CreateElement();
vdir.Path = virtualDirectoryPath;
vdir.PhysicalPath = virtualDirectoryPhysicalPath;
app.VirtualDirectories.Add(vdir);
site.Applications.Add(app);
mgr.Sites.Add(site);
mgr.CommitChanges();
Now that was a smooth transition. Within minutes BloggingAbout.NET was upgraded from version 2007.1 to Community Server 2008. We've gotten a brand new license from the great folks over at Telligent, the folks behind Community Server.
For logged in users, the frontpage will show recent activity of blogs, posts, threads and friends you're linked to or were active in. Not logged in users will see a welcome message and latest activities. That page is quite empty with no recent activity, I'm looking into it why this is. Also not all posts for every blog comes up in the blogs overview when you're not logged in.
If you see any other problems or have questions, don't hesitate to contact us.
Thanks,Dennis van der Stelt
TAGS
When you've installed Community Server on Windows 2008 and especially are running under IIS7, you'll probably get some problems with at least your tags. Community Server will throw a 404 "Page not found" error on tags with spaces. If that's the case, open up your web.config and paste the following code at the bottom, but within the "configuration" tags.
<system.webServer>
<security>
<requestFiltering allowDoubleEscaping="true" />
</security>
</system.webServer>
Now IIS7 might still throw an error because the configuration won't allow you to overrule the default setting. In this knowledge base article you'll find more information.
Find the following file %windir%\System32\inetsrv\config\applicationHost.config and open it in Notepad under Administrator permissions. Find the key 'requestFiltering' and set overrideModeDefault to "Allow" instead of "Deny".
AVATARS
When your avatars aren't showing, it might be because you're running in "Classic .NET AppPool" mode and not in "Integrated Pipeline". Change it and it should work.
If you're looking at this, you're looking at BloggingAbout.NET on a brand new 19" server that's dedicated to BloggingAbout.NET. We were hosted on a server with about 100 or 200 other sites and we were pulling so much traffic and resources that our sponsor has decided to give us a brand new 19" in their own rack. Here are some pictures.
Although this won't be the only site on this server, all will be personal sites and will probably not pull as much traffic as this one. With uncompressed traffic we were pulling over 2.5 Gigabytes a day. On this new server we should be running much faster and hopefully never go down, although that's all up to me now, with some support from our sponsor of course. Thanks to Tellus for providing this!
The first site I tested this with is my brand new personal site http://dennisvanderstelt.nl/ running on GraffitiCMS. Although it's in Dutch, it's probably worth taking a look.
I was looking for CopySourceAsHtml for Visual Studio 2008, but for some reason it's not on the 'official' page so I had to search for it. There are multiple versions, but on Guy Burstein's blog there's more information and the only RTM version I could find.
I always search on Jan Schreuder his weblog for the following piece of css to include:
border-top: windowtext 1pt solid;
border-top-color: #CCCCCC;
padding-top: 1pt;
border-left: windowtext 1pt solid;
border-left-color: #CCCCCC;
padding-left: 1pt;
border-right: windowtext 1pt solid;
border-right-color: #CCCCCC;
padding-right: 1pt;
border-bottom: windowtext 1pt solid;
border-bottom-color: #CCCCCC;
padding-bottom: 1pt;
width: 100%;
overflow: auto;
background-color: #F5F5F5;
Can't live without CopySourceAsHtml now, can we?!
BloggingAbout.NET is doing great in visitors, bloggers and traffic. Unfortunately a bit too good for what we can provide. We're running into increasing hosting costs as we currently pull dozens of Gigabytes of data and our database is also growing larger and is reaching almost 200GB. Therefore the BloggingAbout.NET team has made some decisions on how to move forward in the future.
The first wave of change will be adds on every page, including in the RSS feed.
The next wave will be to charge of a small fee to all who currently have a weblog at BloggingAbout.NET.We've provided excellent support and a great change for everyone to grow so we think our community is definitely worth it. We're still deciding on how much we'll charge, but it'll be around $10 per month or a slightly larger yearly fee. If you want you can comment and tell us what your preferences are, both as weblogger and as visitor.
Thanks in advance for the understanding,BloggingAbout.NET team
Update : It's April 2nd now... Hope you got it, because April fools! ;-)
Update 2 : What is cool is that BloggingAbout.NET is currently on a server with a load of other websites. Soon we'll have a dedicated 19" machine! And no, no payment required from anyone! ;-)