# Monday, 29 April 2013

Last week was the first dotnetconf, a virtual conference put on by Javier Lozano and Scott Hanselman.  The event was live streamed via Google Hangout and included a bunch of really cool content.  I was given the honor of presenting on test driven development in .NET during the two day conference.  If you weren’t able to catch my session live or did make the live event and are looking for the slides and demos the links are below.

posted on Monday, 29 April 2013 16:24:00 (Central Daylight Time, UTC-05:00)  #    Comments [2]
# Saturday, 01 September 2012

This week I had the pleasure of speaking at devLINK.  I did 5 sessions over the 3 day conference and had a blast networking with the other speakers and attendees.  Kudos to the devLINK staff on a job well done.

Here are the 5 sessions I did at devLINK 2012 and links to the associated slides and demos.

posted on Saturday, 01 September 2012 18:45:00 (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Wednesday, 01 August 2012

Last month I had the awesome opportunity to be part of the aspConf virtual conference.  aspConf evolved from the very popular mvcConf, but instead of being focused solely on ASP.NET MVC aspConf is focused on the entire ASP.NET stack of goodness.  The great thing about aspConf is that it is a virtual conference allowing for a much broader audience.

I presented two sessions at aspConf:

  1. Test Driving ASP.NET MVC - (slides and code)
  2. Kendo UI - Lighten Your Load by Adding a Sword(slides and code)

The aspConf staff also put in the immense effort of editing every session and making them available on Channel 9 for everyone to watch.

If you missed aspConf this year, well you can always watch it on Channel 9, but also make sure you follow them on Twitter and keep on eye on the aspConf site so you don’t miss next year’s event!

posted on Wednesday, 01 August 2012 06:28:16 (Central Daylight Time, UTC-05:00)  #    Comments [3]
# Monday, 23 April 2012

Having been a part of many large enterprise ASP.NET MVC application implementations using test driven development I learned early on that separating your controller classes into a their own project significantly reduces the noise in your web project.  It wasn’t until a recent talk I gave to user group in my region that I realized that this isn’t a widely adopted practice.  For large applications with a lot of developers and a complex architecture I highly recommend it. 

Putting your controllers in a separate assembly is very straight forward.  First create a controllers project in your solution and then you just need to update your route registrations to tell them where to look for the controllers.

  1. routes.MapRoute(name: "Default", url: "{controller}/{action}/{id}",
  2.                 namespaces: new[] {"[Namespace of the Project that contains your controllers]"},
  3.                 defaults: new {controller = "Home", action = "Index", id = UrlParameter.Optional});

In order to tell ASP.NET MVC where to look for your controllers when registering your routes you use the ‘namespaces’ parameter of the MapRoute method as illustrated above.

I know that the concept of putting controllers in a separate assembly is a bit controversial and everyone seems to have a strong opinion either for or against, so let me know what side of the fence you fall on.

posted on Monday, 23 April 2012 08:02:14 (Central Daylight Time, UTC-05:00)  #    Comments [12]
# Monday, 16 April 2012

Back in 2009 I published ReSharper Live Template For Creating Unit Test Stub.  A lot of things have changed since 2009, including my templates.  Since I am doing another series of presentations on Test Driven Development I thought I should get these out because people always ask for them.

As stated in my original post these templates are a way for you to create unit test names that help in describing the true intentions of the test and also to provide a common unit test format that will make reading and comprehending your unit tests easier on everyone.  And of course as lazy developers any redundancies should be automated!

The first template is for a unit test that does not have specific input criteria.

Test w/out Input Criteria
  1. [TestMethod]
  2. public void $MethodUnderTest$_Should_$ExpectedResult$() {
  3.     //Arrange
  4.     $END$
  5.     //Act
  6.     //Assert
  7. }

The second template is for a unit test that has specific input criteria.

Test with Input Criteria
  1. [TestMethod]
  2. public void $MethodUnderTest$_Should_$ExpectedResult$_When_$Condition$() {
  3.     //Arrange
  4.     $END$
  5.     //Act
  6.     //Assert
  7. }

You can take the two templates and create new Live Templates and map to whatever key stroke combination you wish.  I use ‘tt’ and ‘tw’.

Note:  I have been using these Live Templates since ReSharper 3 and I am currently using them in the latest build of ReSharper 6 without any issues so you should be good to go.

As always if you feel these can be improved on or have other Live Templates you want to share let me know in the comments below.

posted on Monday, 16 April 2012 07:09:59 (Central Daylight Time, UTC-05:00)  #    Comments [1]
# Monday, 12 December 2011

Integration Testing is a necessary evil that often gets overlooked or is implemented, ran once, and then not maintained.  The reasoning behind this is that by definition Integration Testing relies on external resources that are often outside of our control and some times completely hands off.  Also these external resources are in constant use by a large number of people making whatever resource the external systems are serving very volatile.  In this post I am going to focus on the most common external resource; the Database.

Integration Testing when you have a Database as an external resource can be a nightmare.  First off you need to have access to the database.  Once that is accomplished you need to have elevated access to the database in order to run scripts.  Scripts you say?  Yes scripts!  Scripts that can put the database in an expected state every time you run the Integration Tests.  Oh, yeah then you have to make sure that the script is run.

Luckily if you are using Entity Framework Code First you more than likely already have elevated access to the Database and are probably running a local instance of SQL Server on your dev box that you are in control of.  But in the typical scenario you would still have to write the SQL Scripts, which if you are like me you don’t enjoy, and then you have to make sure they are run and that they don’t impact the data that you use to manually UI test your application…we all have that one piece of data that rely on…don’t deny it!

So how does EF Code First help me with this overwhelming problem?

All example code is from my EFCodeFirstDemo.

Seeded Data:

In Entity Framework Code First you are given the ability to hook into the database generation process and seed the database with relevant data for testing.  The best part about this is that you do it all using your POCO domain entities and LINQ to Entities…NO SQL SCRIPTS!  WOOT!

The first step in the process is to create a custom data context initializer that implements an implementation IDatabaseInitializer.

  1. public class TestDataContextInitializer : DropCreateDatabaseIfModelChanges<DataContext> {}

The next step is to override the Seed method that hooks into the generation of the database.

  1. protected override void Seed(DataContext context) {
  2.     base.Seed(context);
  3. }

Finally you can use this Seed method to build up your test data and populate the database either every time your model changes (DropCreateDatabaseIfModelChanges) or if you choose every time you spin up a new session that accesses the database (DropCreateDatabaseAlways), I don’t recommend the latter.

In the code below I am building up object graphs using my standard POCO entities and LINQ to Entities.

  1. public class TestDataContextInitializer : DropCreateDatabaseIfModelChanges<DataContext> {
  2.  
  3.     private Manufacturer _astonMartin;
  4.     private Model _astonMartinDB9;
  5.     private Engine _astonMartinV12;
  6.     private Model _astonMartinV12Vantage;
  7.     private Manufacturer _ferrari;
  8.     private Model _ferrari458Italia;
  9.     private Model _ferrariScaglietti;
  10.     private Engine _ferrariV12;
  11.     private Engine _ferrariV8;
  12.     private Manufacturer _lamborghini;
  13.     private Model _lamborghiniAventador;
  14.     private Model _lamborghiniGallardo;
  15.     private Engine _lamborghiniV10;
  16.     private Engine _lamborghiniV12;
  17.     private Manufacturer _porsche;
  18.     private Model _porsche911GT2R2;
  19.     private Engine _porscheStraight6;
  20.  
  21.     protected override void Seed(DataContext context) {
  22.         SeedManufacturer(context);
  23.         SeedEngine(context);
  24.         SeedModel(context);
  25.         base.Seed(context);
  26.     }
  27.  
  28.     private void SeedManufacturer(DataContext context) {
  29.         _ferrari = new Manufacturer {Name = "Ferrari", Country = "Italy"};
  30.         _lamborghini = new Manufacturer {Name = "Lamborghini", Country = "Italy"};
  31.         _astonMartin = new Manufacturer {Name = "Aston Martin", Country = "United Kingdom"};
  32.         _porsche = new Manufacturer {Name = "Porsche", Country = "Germany"};
  33.         _ferrari.Location = DbGeography.Parse("POINT(44.53244    10.86412)");
  34.         _lamborghini.Location = DbGeography.Parse("POINT (44.65934    11.12693)");
  35.         _astonMartin.Location = DbGeography.Parse("POINT (52.18708    -1.48351)");
  36.         _porsche.Location = DbGeography.Parse("POINT (48.83498    9.15231)");
  37.         new List<Manufacturer> {_ferrari, _lamborghini, _astonMartin, _porsche}.ForEach(x => context.Manufacturers.Add(x));
  38.     }
  39.  
  40.     private void SeedEngine(DataContext context) {
  41.         _astonMartinV12 = new Engine {Name = "6.0L V12", BreakHorsepower = 510, NumberOfCylinders = 12, Liters = 6.0m};
  42.         _ferrariV8 = new Engine {Name = "5.4L V8", BreakHorsepower = 570, NumberOfCylinders = 8, Liters = 5.4m};
  43.         _ferrariV12 = new Engine {Name = "5.7L V12", BreakHorsepower = 532, NumberOfCylinders = 12, Liters = 5.7m};
  44.         _lamborghiniV10 = new Engine {Name = "5.2L V10", BreakHorsepower = 562, NumberOfCylinders = 10, Liters = 5.2m};
  45.         _lamborghiniV12 = new Engine {Name = "6.5L V12", BreakHorsepower = 700, NumberOfCylinders = 12, Liters = 6.5m};
  46.         _lamborghiniV12 = new Engine {Name = "6.5L V12", BreakHorsepower = 700, NumberOfCylinders = 12, Liters = 6.5m};
  47.         _porscheStraight6 = new Engine {Name = "3.6L Straight 6", BreakHorsepower = 620, NumberOfCylinders = 6, Liters = 3.6m};
  48.         new List<Engine> {_astonMartinV12, _ferrariV8, _ferrariV12, _lamborghiniV10, _lamborghiniV12, _porscheStraight6}.ForEach(x => context.Engines.Add(x));
  49.     }
  50.  
  51.     private void SeedModel(DataContext context) {
  52.         _ferrari458Italia = new Model {Name = "458 Italia", BasePrice = 220000, Year = 2012, Manufacturer = _ferrari, AvailableEngines = new List<Engine> {_ferrariV8, _ferrariV12}, EngineLocation = EngineLocationType.Mid};
  53.         _ferrariScaglietti = new Model {Name = "Scaglietti", BasePrice = 313000, Year = 2012, Manufacturer = _ferrari, AvailableEngines = new List<Engine> {_ferrariV12}, EngineLocation = EngineLocationType.Front};
  54.         _lamborghiniGallardo = new Model {Name = "Gallardo LP 570-4 Superleggera", BasePrice = 237600, Year = 2012, Manufacturer = _lamborghini, AvailableEngines = new List<Engine> {_lamborghiniV10}, EngineLocation = EngineLocationType.Mid};
  55.         _lamborghiniAventador = new Model {Name = "Aventador LP 700-4", BasePrice = 387000, Year = 2012, Manufacturer = _lamborghini, AvailableEngines = new List<Engine> {_lamborghiniV12}, EngineLocation = EngineLocationType.Mid};
  56.         _astonMartinDB9 = new Model {Name = "DB9", BasePrice = 185000, Year = 2012, Manufacturer = _astonMartin, AvailableEngines = new List<Engine> {_astonMartinV12}, EngineLocation = EngineLocationType.Front};
  57.         _astonMartinV12Vantage = new Model {Name = "V12 Vantage", BasePrice = 180000, Year = 2012, Manufacturer = _astonMartin, AvailableEngines = new List<Engine> {_astonMartinV12}, EngineLocation = EngineLocationType.Mid};
  58.         _porsche911GT2R2 = new Model {Name = "911 GT2 R2", BasePrice = 245000, Year = 2012, Manufacturer = _porsche, AvailableEngines = new List<Engine> {_porscheStraight6}, EngineLocation = EngineLocationType.Rear};
  59.         new List<Model> {_ferrari458Italia, _ferrariScaglietti, _lamborghiniAventador, _lamborghiniGallardo, _astonMartinDB9, _astonMartinV12Vantage, _porsche911GT2R2}.ForEach(x => context.Models.Add(x));
  60.     }
  61. }

The result of this process is that every time my database is dropped and recreated it is also seeded with test data. 

I know what your saying…”But I don’t use the same data for manually walking through my UI that I would use for Integration Testing!”  Luckily I can easily specify a different Connection String and Database Initializer to use when running my Integration Tests.

The first thing you have to do is modify the connection string in the AppConfig of your Integration Test project to use a different initial catalog.  As you can see all I did was suffix mine with “_TEST”…clever I know!  This is going to setup a new database for you that will only be used for testing.

  1. <connectionStrings>
  2.     <add name="EFCodeFirst" connectionString="Data Source=(local);Initial Catalog=EFCodeFirst_TEST;Integrated Security=True;MultipleActiveResultSets=True;" providerName="System.Data.SqlClient"/>
  3.   connectionStrings>
  4.  
  5.  

Next you need to tell EF what Database Initializer to use.  This can be accomplished two ways.  The first way is to explicitly set it in code.  In the example below I am doing this in the ClassInitialize of my Integration Test class.

  1. [ClassInitialize]
  2. public static void ClassInitialize(TestContext context) {
  3.     Database.SetInitializer(new TestDataContextInitializer());
  4. }

The second way is to set it configure it in the App/Web Config.

  1. <appSettings>
  2.     <add key="DatabaseInitializerForType EFCodeFirst.DataContext.DataContext, EFCodeFirst" value="EFCodeFirst.DataContext.TestDataContextInitializer, EFCodeFirst" />
  3.   appSettings>
  4.  
That’s it!  Now you have a separate Database instance just for Integration Testing that will always contain the clean fresh data that is required to exercise your Integration Test suite.  Better yet, every developer that runs your Integration Tests will also have this data and everything will just work.
posted on Monday, 12 December 2011 09:25:24 (Central Standard Time, UTC-06:00)  #    Comments [2]
# Sunday, 03 July 2011

Earlier this year during Chicago Code Camp 3, I had the privilege of sitting down with Clark Sell and Marc Nichols and recording my first podcast.  Clark and Mark are the duo behind Developer Smackdown.  If you are not familiar with Developer Smackdown I suggest you take a listen.  In my musing, as Clark and Marc refer to the episodes, we discuss a topic very near and dear to my hear, Test-driven Development.  Take a listen and let me know what you think.

 TDD With Keith Burnell

posted on Sunday, 03 July 2011 20:30:00 (Central Daylight Time, UTC-05:00)  #    Comments [2]
# Sunday, 22 May 2011

Last weekend I presented a session at the third annual Chicago Code Camp entitled: Test-driven Development in .NET – Tips, Tools, and Techniques.  The session was standing room only and carried into the commons area afterwards with some excellent questions from attendees.  What is greater than that is that the questions didn’t stop there, they kept coming via email.  One question in particular has stuck with me because it was a hurdle I myself had to overcome early on in my TDD adventures.

The question boiled down to how do you test code the depends on ASP.NET, specifically Web Configuration and Application Settings?  So I thought I would put together a blog post how this can be done, and how it should be done.

To set the stage…I have a simple ASP.NET web application with one page and one class.  The page load method calls the one method in the class that returns an app setting stored in the web config file.

Index.aspx.cs
  1. namespace WebApp
  2. {
  3.     public partial class Index : System.Web.UI.Page
  4.     {
  5.         protected void Page_Load(object sender, EventArgs e) {
  6.             lblValue.Text = SomeClassThatNeedsTesting.GetSomeStringValue();
  7.         }
  8.     }
  9. }

SomeClassThatNeedsTesting.cs
  1. namespace WebApp
  2. {
  3.     public static class SomeClassThatNeedsTesting
  4.     {
  5.         public static string GetSomeStringValue() {
  6.             return System.Web.Configuration.WebConfigurationManager.AppSettings["MyAppSettingValue"];
  7.         }
  8.     }
  9. }

Your first option to getting your tests to run and return the configuration and/or app settings is to tell your tests to run under the ASP.NET host process and not the VSTest host process and also tell what url to run the test under.

SomeClassThatNeedsTesting_Test
  1. [TestMethod]
  2. [HostType("ASP.NET")]
  3. [UrlToTest("http://localhost:2356/Index.aspx")]
  4. [AspNetDevelopmentServerHost("$(SolutionDir)\\WebApp")]
  5. public void GetSomeStringValue_ShouldReturn_NonNull_NonEmpty_String() {
  6.     var val = WebApp.SomeClassThatNeedsTesting.GetSomeStringValue();
  7.     Console.WriteLine(val.ToString());
  8.     Assert.IsFalse(string.IsNullOrEmpty(val));
  9. }

If you run this you will see that the test passes…eventually…after Casini is started and the test runner twiddles its thumbs for a bit.  Speed is my first issue with setting up your test to run in this fashion.  My second issue is that you aren’t testing the ASP.NET configuration framework so why would you need to add all this extra plumbing to make your code take that route?  There is a better option!

Since we really don’t care how or where are value comes from we just need some sort of value returned so we can test our method, we can easily add a thin layer of abstraction and mock the pieces of code that depend on ASP.NET.

Lets start by creating an interface for a simple class that reads application settings.

IAppSettingsReader.cs
  1.  
  2. namespace WebApp {
  3.  
  4.     public interface IAppSettingsReader {
  5.  
  6.         string GetAppSettingValue(string settingKey);
  7.     }
  8. }

Now we can implement the interface and add the actual code to read the app settings from the web config file.

AppSettingsReader
  1. namespace WebApp {
  2.  
  3.     public class AppSettingsReader : IAppSettingsReader {
  4.  
  5.         public string GetAppSettingValue(string settingKey) {
  6.             if (string.IsNullOrEmpty(settingKey)) throw new NullReferenceException("settingKey is required");
  7.             return (WebConfigurationManager.AppSettings[settingKey]);
  8.         }
  9.  
  10.     }
  11. }

Next we will modify our class that needs testing to use the new AppSettingsReader.  Because our goal is to eventually be able to mock the settings reader we need to invert the control of the dependency and provide a mechanism for injecting the dependency.  The change is fairly straightforward.

SomeClassThatNeedsTesting
  1. namespace WebApp {
  2.  
  3.     public class SomeClassThatNeedsTesting {
  4.  
  5.         private readonly IAppSettingsReader _settingsReader;
  6.  
  7.         public SomeClassThatNeedsTesting(IAppSettingsReader settingsReader) {
  8.             _settingsReader = settingsReader;
  9.         }
  10.  
  11.         public string GetSomeStringValue() {
  12.             return _settingsReader.GetAppSettingValue("MyAppSettingValue");
  13.         }
  14.     }
  15. }

Now we have introduced a breaking change and need to modify our page and our test to accommodate the change to SomeClassThatNeedsTesting.

Index.aspx.cs
  1. namespace WebApp {
  2.  
  3.     public partial class Index : Page {
  4.  
  5.         protected void Page_Load(object sender, EventArgs e) {
  6.             var someClass = new SomeClassThatNeedsTesting(new AppSettingsReader());
  7.             lblValue.Text = someClass.GetSomeStringValue();
  8.         }
  9.     }
  10. }

SomeClassThatNeedsTesting_Test
  1. namespace TestProject {
  2.  
  3.     [TestClass]
  4.     public class SomeClassThatNeedsTesting_Tests {
  5.  
  6.         [TestMethod]
  7.         [HostType("ASP.NET")]
  8.         [UrlToTest("http://localhost:2356/Index.aspx")]
  9.         [AspNetDevelopmentServerHost("$(SolutionDir)\\WebApp")]
  10.         public void GetSomeStringValue_ShouldReturn_NonNull_NonEmpty_String_ASP() {
  11.             SomeClassThatNeedsTesting someClass = new SomeClassThatNeedsTesting(new AppSettingsReader());
  12.             string val = someClass.GetSomeStringValue();
  13.             Console.WriteLine(val);
  14.             Assert.IsFalse(string.IsNullOrEmpty(val));
  15.         }
  16.     }
  17. }

At this point we can run our test from above and, after we have taken a bathroom break, checked Twitter, and made a sandwich, we will notice that the test still passes.  This is true because all we have done is add a layer of abstraction.  We have not changed the core functionality of the process.  Now that the layer of abstraction is in place we can write another test and this time instead of writing more code to please ASP.NET lets drop that dependency completely by mocking it.

To implement our mock I am going to use my mocking tool of choice, RhinoMocks.  (I am purposefully not supplying a URL here because you should be using NuGet to get your packages!)

Here is our new and improved test.

New And Improved Test
  1. [TestMethod]
  2. public void GetSomeSringValue_ShouldReturn_NonNull_NonEmpty_String_Mocked() {
  3.     //Arrange
  4.     string myAppSettingValue = "This is my expected mocked setting value";
  5.     MockRepository _repository = new MockRepository();
  6.     IAppSettingsReader mockSettingsReader = MockRepository.GenerateStrictMock<IAppSettingsReader>();
  7.     mockSettingsReader.Expect(msr => msr.GetAppSettingValue("MyAppSettingValue")).Return(myAppSettingValue).Repeat.Once();
  8.     _repository.ReplayAll();
  9.     //Act
  10.     SomeClassThatNeedsTesting someClass = new SomeClassThatNeedsTesting(mockSettingsReader);
  11.     string val = someClass.GetSomeStringValue();
  12.     //Assert
  13.     Assert.AreEqual(myAppSettingValue, val, "Wrong value returned from GetSomeSringValue");
  14. }

If you take a look at the test you can see that the first thing that I did was create my mock AppSettingReader and set my expectations.  After that I instantiated my class under test and passed in the settings reader mock.

Hope you found this useful!  Complete code is available here!

posted on Sunday, 22 May 2011 19:17:23 (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Saturday, 02 April 2011

Unit testing certainly does give you the developer a warm fuzzy but that warm fuzzy can only get you so far.  In the end you still have to make sure all your little pieces of code/functionality play nice together.  This requires integration testing and if we are going to do any sort of testing that we actually expect to be performed on a regular basis we have to automate it.  Automated integration testing often gets neglected and is substituted with manual testing, which delays finding issues and adds time to the project timeline.  The reason that integration testing is often neglected is that it requires touching actual data. 

Why is this is an issue:

  1. Someone has to take the time create the data for the testing.
  2. The data has to be reset after each test run

All of this requires a lot of work, coordination…and a DBA [cringe]!

Let me introduce a scenario where all that is not required.  Why can’t we wrap our tests in a Transaction?

Here’s what I am thinking:

  1. Have a local empty copy of the database.
  2. Either in a test-by-test basis or test-suite basis
    1. Start a transaction (either at the start of your test or on build-up of the test suite)
    2. Create your data and put it in the DB
    3. Perform your tests on the data you just created and inserted
    4. Rollback the transaction
  3. … And Repeat

Here is an example:

  1.         [TestMethod]
  2.         public void GetAllEligible_ShouldReturn_All_Attendess_InThe_Database_Where_IsEligible_Equals_True() {
  3.             using (new TransactionScope()) {
  4.                 //Arrange
  5.                 int expectedCount = 1;
  6.                 Attendee attendee1 = new Attendee {FirstName = "Joe", LastName = "Smith", IsEligible = true};
  7.                 Attendee attendee2 = new Attendee {FirstName = "Randy", LastName = "Jones", IsEligible = false};
  8.                 using (var dc = new DayOfDotNetDataContext()) {
  9.                     dc.Attendees.InsertAllOnSubmit(new List<Attendee> {attendee1, attendee2});
  10.                     dc.SubmitChanges();
  11.                 }
  12.                 //Act
  13.                 IAttendeeRepository attendeeRepository = new AttendeeRepository();
  14.                 IList<AttendeeDTO> attendees = attendeeRepository.GetAllEligible();
  15.                 //Assert
  16.                 attendees.Count.ShouldEqual(expectedCount, "Wrong number of attendess");
  17.             }
  18.         }

You can see that the first line of my test starts a transaction scope.  I then create some data and add it to my empty database.  Now, remember this database needs to be empty as to not mess up your expectations.  After the data has been created I then perform the operation I am testing and assert the results.

You may be confused by the lack of a “Rollback” statement.  The way TransactionScope works is that it only commits when explicitly told to do so.

Automated integration testing is a must have and in order to make your life easier follow the steps I have outlined and you will be free to live the TDD dream!

posted on Saturday, 02 April 2011 14:19:41 (Central Standard Time, UTC-06:00)  #    Comments [4]
# Friday, 10 September 2010

* Download Complete Source Code

In my previous post I covered doing automated user interface testing of a WPF application using Iron Ruby and Cucumber.  The reason I was drawn to this path was my current interest in Ruby, Rails, and BDD.  What made Bewildr such a draw for me, other than writing my tests in IronRuby, was the fact that I can use with Cucumber and have a truly human-readable natural language test.

  1. Scenario: The Log On window should be displayed on application start
  2.     Given I ensure that there are no instances of "CompositeAppPoc.Shell.exe" running
  3.     When I start "C:\\MyCompositeAppPoc.Shell.exe"
  4.     Then 1 window is displayed with name "Log On"
  5.       And Terminate the app

Again, because of the learning curve and the fact that I would be introducing a completely new programming language, and let’s face it a completely new way of thinking, into a corporate environment that I will not be around to support long-term I had to pursue a more conventional solution, which led me to White.

White is an automated UI testing framework similar to Bewildr in that they both rely on the MS UI Automation Framework to hook and manipulate the user interface.  What makes White a better choice given my current situation is that from a programmers perspective it is implemented and reads exactly like the standard .NET test frameworks.

  1. [TestMethod]
  2. public void OnApplicationStart_TheLogOnWindow_ShouldBeDisplayed() {
  3.     //Act
  4.     Window window = _app.GetWindow("Log On");
  5.     //Assert
  6.     window.ShouldNotBeNull();
  7. }

Take a look at the video clip below to see what running a White test looks like.

Getting up and running with White is very easy.  Other than downloading the binaries from CodePlex all you need is a tool like UISpy to help you dig deep into how the UI elements are rendered.

At the highest level White operates on the concepts of Application and Windows.  Application being the application you are testing and Windows being the main surface of the application.  As a best practice I would recommend spinning up the application, retrieving your window(s) and killing your application as part of test setup and teardown.

  1. #region Private Fields
  2.  
  3. private Application _app;
  4. private Window _window;
  5.  
  6. #endregion
  7.  
  8. #region Setup & Tear Down
  9.  
  10. [TestInitialize]
  11. public void MyTestInitialize() {
  12.     _app = Application.Launch(@"c:\pathtomyapp\myapp.exe");
  13.     _window = _app.GetWindow("MyWindow");
  14. }
  15.  
  16. [TestCleanup]
  17. public void MyTestCleanup() {
  18.     _app.Kill();
  19. }
  20.  
  21. #endregion

With all that in place let’s walk through setting up a couple tests.

The first thing I want to test is that when my application spins up for the first time the Log On window is displayed.  Because this is an Application level test I am going to put it in a test class called ApplicationTests.  I will use the practice of spinning up the app and killing it as I described above.  My test will simply attempt to retrieve a window with title “Log On” and make sure it is not null.

  1. [TestClass]
  2. public class ApplicationTests {
  3.     #region Private Fields
  4.  
  5.     private Application _app;
  6.  
  7.     #endregion
  8.  
  9.     #region Setup & Tear Down
  10.  
  11.     [TestInitialize]
  12.     public void MyTestInitialize() {
  13.         _app = Application.Launch(
  14.         @"c:\wpf\compositeapppoc\compositeapppoc.shell\compositeapppoc.shell\bin\debug\compositeapppoc.shell.exe");
  15.     }
  16.  
  17.     [TestCleanup]
  18.     public void MyTestCleanup() {
  19.         _app.Kill();
  20.     }
  21.  
  22.     #endregion
  23.  
  24.     [TestMethod]
  25.     public void OnApplicationStart_TheLogOnWindow_ShouldBeDisplayed() {
  26.         //Act
  27.         Window window = _app.GetWindow("Log On");
  28.         //Assert
  29.         window.ShouldNotBeNull();
  30.     }
  31. }

My next test is going to be to make sure that when I enter an invalid username and password and click the log on button a message is displayed telling me my credentials are not valid.  Because this test is specific to the Log On window I am going to create a new test class called LogOnTests.  I will use the practice of spinning up the app, getting my window and killing the app as I described above.  My test will enter an invalid username and password, click the log on button, and verify that the error message label is visible.

  1. [TestClass]
  2. public class LogOnTests {
  3.  
  4.     #region Private Fields
  5.  
  6.     private Application _app;
  7.     private Window _window;
  8.  
  9.     #endregion
  10.  
  11.     #region Setup & Tear Down
  12.  
  13.     [TestInitialize]
  14.     public void MyTestInitialize() {
  15.         _app = Application.Launch(
  16.             @"c:\wpf\compositeapppoc\compositeapppoc.shell\compositeapppoc.shell\bin\debug\compositeapppoc.shell.exe");
  17.         _window = _app.GetWindow("Log On");
  18.     }
  19.  
  20.     [TestCleanup]
  21.     public void MyTestCleanup() {
  22.         _app.Kill();
  23.     }
  24.  
  25.     #endregion
  26.  
  27.    [TestMethod]
  28.     public void Entering_InvalidCredentials_AndClickingThe_LogOnButton_ShouldDisplayThe_InvalidCredentialsMessage() {
  29.         //Arrange
  30.         _window.Get<TextBox>("txtUsername").Text = "InvalidUsername";
  31.         _window.Get<TextBox>("txtPassword").Text = "InvalidPassword";
  32.         var btn = _window.Get<Button>("btnLogOn");
  33.         //Act
  34.         btn.Click();
  35.         _window = _app.GetWindow("Log On");
  36.         //Assert
  37.         (_window.Get<Label>("lblErrorMessage")).Visible.ShouldBeTrue();
  38.     }
  39. }

It’s that easy.  With very little effort you can have a full suite of automated tests for testing your UI.  How cool is that!?

* Download Complete Source Code

posted on Friday, 10 September 2010 16:25:00 (Central Daylight Time, UTC-05:00)  #    Comments [6]
# Monday, 23 August 2010

* Download Complete Source Code

In an attempt to be a Pragmatic Programmer I make an effort to learn a new programming language yearly.  This year the language of choice is Ruby, including Rails.  About a month ago I started the Build Your Own Blog :: Rails series at TekPub.  In this series Rob Conery instructs on creating a blog engine using Rails and focusing on Behavior Driven Development.  Rob introduces some amazing tools, such as Cucumber and Pickle, that make BDD on Rails easy and dare I say…fun!

If you have been following along at home with my previous serious of blog posts you know that in my day job I am currently architecting a large WPF MVVM composite application using Prism.  My development methodology for .Net development is TDD and not BDD, because I just don’t feel the tools are there yet in the .Net space for efficient BDD.  I am at the point in the project where I am starting work on the UI and being fresh of learning the wonderful BDD tools available in the Rails stack it was really annoying me that I had no way to TDD my UI.  Grant it, using MVVM I was able to get much closer to the actual UI than I otherwise would, but it still wasn’t the same.  Finally I got to the point where I just had to research the idea of Cucumber style testing in WPF.  What I found out was it is possible using IronRuby.  Don’t be mistaken, it does not offer the same ease and simplicity as it does on the Rails stack but it is certainly a leap in the right direction.

The tool that is going to make this all possible was written by Nathaniel Ritmeyer and is called Bewildr!

Here are the steps to getting your environment setup…

  1. Follow the steps in my previous blog post to get Ruby, IronRuby, and Cucumber installed. 
  2. Install Bewildr.
    image
  3. Install UISpy.

I am going to be testing the UI created in my previous series: Rolling Your Own Module Level Security for a WPF MVVM Composite Application

Detailed information on Cucumber can be found here.  But, basically Cucumber allows you to write plain-text functional descriptions as automated tests.  Cucumber code consists of two main pieces; Features/Scenarios and Step Definitions.  This is not meant to be a Cucumber tutorial so if you are not familiar with Cucumber I would suggest reading up on it prior to continuing.

OK.  So, now that your familiar with Cucumber you are probably asking yourself how is this going to allow me to do automated UI testing?  This is where Bewildr enters the party.  Bewildr is a Ruby GEM that uses the MS UI Automation Framework to gain programmatic access to a WPF UI.  Basically, I can spin up a WPF application and manipulate the UI, click buttons, enter text in text boxes, etc, all via code.

So, let’s start with a simple scenario.  (I apologize for the formatting/highlighting…need to find a good formatter plug-in for Cucumber code.

application.feature
  1. @application
  2. @window
  3.  
  4. Feature: Application Interaction
  5.  
  6.   Scenario: The Log On window should be displayed on application start
  7.     Given I ensure that there are no instances of "CompositeAppPoc.Shell.exe" running
  8.     When I start "C:\\development\\research\\wpf\\CompositeAppPoc\\CompositeAppPoc.Shell\\CompositeAppPoc.Shell\\bin\\Debug\\CompositeAppPoc.Shell.exe"
  9.     Then 1 window is displayed with name "Log On"
  10.       And Terminate the app

If we go ahead and run this feature Cucumber is going to puke on us because we haven’t created our steps yet.  But, when Cucumber pukes…it pukes in a helpful way.  It is going to give us the shell for the steps we need to create in order to execute this feature.

image

As you can see Cucumber lets us know that we need to define 4 steps in order to get our Feature and Scenario running.  So let’s do that.  Since 3 of the steps deal with the application itself and 1 deals specifically with a window I am going to create 2 step files.

application_steps.rb
  1. require 'bewildr'
  2.  
  3. Given /^I ensure that there are no instances of "([^"]*)" running$/ do |app|
  4.   Bewildr::Application.kill_all_processes_with_name(app)
  5. end
  6.  
  7. When /^I start "([^"]*)"$/ do |app|
  8.   @application = Bewildr::Application.start(app)
  9. end
  10.  
  11. When /^Terminate the app$/ do
  12.   @application.kill
  13. end

window_steps.rb
  1. require 'bewildr'
  2.  
  3. Then /^ (\d+) window is displayed with name "([^"]*)"$/ do |count,name|
  4.       @window = @application.wait_for_window(name)
  5.       @application.windows.size.should == count.to_i
  6.       @window.name.should match(name)
  7. end

In the steps coded above you can begin to see what Bewildr allows us to do.  Now if you run this feature you should see the output below as well as the app physically spinning up and closing.

image

And as you can see our scenario passed.

This is really just scratching the surface of what you can do.  I would suggest downloading the code and get an understanding of some of the more advanced scenarios and then start creating your own.

* Download Complete Source Code

posted on Monday, 23 August 2010 18:04:00 (Central Daylight Time, UTC-05:00)  #    Comments [89]
# Friday, 13 August 2010

In doing some research I found that it is possible to do Rails type BDD/testing in WPF using IronRuby.  I am very excited about this and will be doing an in-depth post on this in the very near future.  But, for now I wanted to get a post out on how to get Cucumber up and running in IronRuby because in attempting to do this myself I ran into an issue that turns out is fairly well-known but as far as I can tell is not documented.  I would like to thank Nathaniel Ritmeyer, aka NatOnTesting, for helping me through this and take a look at his Bewildr gem…it will be a key piece of my future post.

Here are the steps for getting Cucumber up and running with IronRuby:

  1. Install Ruby (to save headaches install to c:\ruby and make sure “c:\ruby\bin” is in your Path environment variable)
  2. Install IronRuby (to save headaches install to c:\ironruby and make sure “c:\ironruby\bin” is in your Path environment variable)
  3. Install Cucumber (here is the undocumented part…until now)
    1. Because Gherkin is required by Cucumber version > 0.6.3 and Gherkin is not compatible with IronRuby we need to install Cucumber version <= 0.6.3.
    2. image
  4. Next you need to create a Cucumber wrapper script for IronRuby
    1. Go to c:\ruby\bin
    2. Create a blank text file “icucumber.bat”
    3. Open icucumber.bat in text editor
    4. Enter this text
      1. @ECHO OFF
        SET GEM_PATH=c:\ruby\lib\ruby\gems\1.9.1
        @"C:\IronRuby\bin\ir.exe" "c:\Ruby\bin\cucumber" %*

    5. Save the file
  5. Test it (results are truncated)

    image

That’s it.  You now have Cucumber running with IronRuby.  Why is this helpful?  Stay Tuned!

posted on Friday, 13 August 2010 17:00:00 (Central Daylight Time, UTC-05:00)  #    Comments [6]
# Sunday, 26 April 2009

I figured I was to the point where I was comfortable enough with the concept of mocking that I would start implementing it in one of the projects I am working on at my current client.  The data access layer of the application obtains data from two sources; a CIS system that is only reachable via web services and a data warehouse on a SQL Server that we are accessing directly using stored procedures and LINQ to SQL.  I started with mocking the web service piece and that went off without a hitch. 

The Linq To SQL piece did not go as smoothly.  I had a few issues creating the Interface for the DataContext and then ran into trying to mock System.Data.Linq.Table which is Sealed.  Instead of copying and pasting the code in the post and explaining it I think that I will let the code speak for itself.  If you are like me you find it much easier to understand complex code in the solution structure offered by Visual Studio.  So grab the code from here and dive in.

posted on Sunday, 26 April 2009 19:26:34 (Central Daylight Time, UTC-05:00)  #    Comments [6]
# Thursday, 23 April 2009

I have recently started researching the mocking framework RhinoMocks and finding good resources hasn’t been as easy as I was hoping it would be.  I decided to post the useful links I found to this point.  I am hoping this will become a living post for all RhinoMocks references worth tracking.

Reader Submitted
posted on Thursday, 23 April 2009 03:39:00 (Central Daylight Time, UTC-05:00)  #    Comments [4]