Using SimpleBrowser with SpecFlow for BDD with ASP.NET MVC

The SpecFlow project provides a useful way to integrate BDD (Behavior Driven Development) testing into .NET projects using the Gherkin language. The main idea is that the project specs or user stories are written in user language and then are linked to actual tests that are automatically executed as the project is developed. There are several possible ways to implement this with ASP.NET MVC to automate the testing with the browser.

WatiN

Steve Sanderson wrote a nice article about applying SpecFlow with ASP.Net MVC.  In this case he used the WatiN tool to drive the tests through a browser. I implemented a similar testing setup on a project using SpecFlow and WatiN but found that driving an actual browser made the tests too slow.

HtmlUnit

A later article from Sanderson describes a way to use HtmlUnit for a “headless browser automation” approach to testing.  This approach is faster but requires using the IKVM method of linking Java within .NET. To ease this aspect of it there is a Nuget package called NHtmlUnit.  I did a small spike with NHtmlUnit but found it slower than I expected but faster than the WatiN approach.

SimpleBrowser

I found a project on GitHub called SimpleBrowser by Nathan Ridley which offers a headless browser testing approach written in directly in .NET. I found the interface to be easy to use and best of all the tests written with SimpleBrowser are very fast.

For example a typical SpecFlow scenario for user login:

    Feature: Log On
       In order to access the features of the website
       As a user
       I want to be able to log On.

    Scenario: Log On User
       Given I am on the Login Page
       When I enter my username and password
       And I click the Log On button
       Then I am on the Home Page Logged In

The tooling that SpecFlow provides for Visual Studio creates a method stub for the tests steps, which can then be filled in to use the SimpleBrowser methods. For example for the first step of being on the Registration page, after filling in the test method with the SimpleBrowser calls:

[Given(@"I am on the Login Page")]
public void GivenIAmOnTheLoginPage() {
     WebBrowser.Current.Navigate("http://localhost:51044/Account/LogOn");
     Assert.IsTrue(WebBrowser.Current.Find("h2", FindBy.Text, "Log On").Exists);
}

The method is linked to the scenario step via the attribute [Given(…)] and the body of the method uses the SimpleBrowser “Navigate” method to load the page.  Then the “Assert” tests that the SimpleBrowser has indeed loaded the log on page by finding an “h2” tag where its inner text is “Log On”.

The “WebBrowser.Current” is a static class that holds the SimpleClass browser instance within the SpecFlow ScenarioContext so that it can maintain state between steps, especially after a login:

[Binding]
public static class WebBrowser {
   public static Browser Current {
       get {
          if (!ScenarioContext.Current.ContainsKey("browser"))
             ScenarioContext.Current["browser"] = new Browser();
          return (Browser)ScenarioContext.Current["browser"];
       }
   }
}

The “new Browser();” is where the SimpleBrowser Browser class is created.

Steps such as clicking on the Log On button are easy to accomplish with the Click() method:

[When(@"I click the Log On button")]
public void WhenIClickTheLogOnButton() {
    WebBrowser.Current.Find("input", FindBy.Value, "Log On").Click();
}

There is also an overload for the Find() method that allows a shortcut if there is an “id” attribute within the html element. For example if there is are “id” elements with UserName and Password for those input elements, then the step for filling in the form fields is simple:

[When(@"I enter my username and password")]
public void WhenIEnterMyUsernameAndPassword() {
    WebBrowser.Current.Find("UserName").Value = "user";
    WebBrowser.Current.Find("Password").Value = "password";
}

Conclusion

I found using the SimpleBrowser easy to use and capable for most testing required for BDD testing with a “headless” browser. The resulting tests run very fast and aren’t fragile to minor changes in the HTML. The only limitation is that it doesn’t support Javascript but test that require Javascript can be done using WatiN or Selenium as part of automated integration tests rather than BDD.

Posted in Software Development | Tagged , , , | 2 Comments

JQuery UI Autocomplete and MVC3 Remote Validation Conflict–Update

I previously posted about a fix to a problem when the JQuery UI Autocomplete doesn’t play well with the ASP.Net MVC3 Remote validation. Part of the solution included a way to ensure that the remote validation isn’t fired for each key click or change of focus in the text box.

The method for doing this is to change the settings of the validation to not fire onkeyup or onfocusout, but to get there the validator settings must be obtained from the form in question.  The following snippet was given to grab the settings (do not use this method):

var validatorSettings = $.data($('form')[0], 'validator')

The problem is that this method of getting the settings will not work correctly if a new form is inserted before the form in question, because that will case the original form to have a counter of [1] and the code will no longer work. Better to use the following method to get the form by named id:

var validatorSettings = $('#searchForm').validate().settings;

Here’s how it looks in the whole snippet of Javascript:

<script type="text/javascript">
    window.onload = function () {
        var validatorSettings = $('#searchForm').validate().settings;
        validatorSettings.onkeyup = false;
        validatorSettings.onfocusout = false;
    }
</script>

Then the form can be given an id so that JQuery will select the correct form:

@using (Html.BeginForm("Index", "Services", FormMethod.Get, new { id = "searchForm" })) {

For the full code refer to the previous article (where this issue has been corrected).

Posted in Software Development | Leave a comment

Remembering Steve Jobs

jobs_billboard_different

Steve brought a lot of greatness to the world. I remember buying my first Apple computer back in early ‘82.  It was an Apple II-Plus and I remember how cool it was that it did color graphics with a TV output. My brother and I were playing the Swashbuckler game right after we got it out of the box. It was also fun and easy to program in Applesoft Basic. Then along came the Apple IIc which was small and easy to haul around, although it wasn’t a true laptop. I then got distracted by the “Amiga” computer and didn’t buy another Apple product for a while but we bought an iPad last year and have really enjoyed it.

He was great in that he stuck to his principles went against the conventional wisdom again and again (Apple Store, iTunes, iPad, etc).  He listened to his own inner voice and vision, and turned a company that was on the ropes into the leading technology company.

He was great in his emphasis on design and taste. His lessons on minimalism in design and functionality should be an inspiration to us all. The modern Apple machines are well designed, well built, and more like easy-t0-use, instant-on appliances rather than complicated computers that take forever to start. The whole concept of knowing what to leave out and keeping it simple are great design principles that Steve used to create products that are easy to use and understand.

Thanks Steve, you were insanely great.

Posted in General, Software Development | Tagged , | Leave a comment

JQuery UI Autocomplete and MVC3 Remote Validation Conflict

On a recent project I had a great deal of trouble to get JQuery UI Autocomplete and ASP.Net MVC3 Remote Validation to play nicely with each other. The goal was to have a type-in for selecting a city for a search in which the pull-down would auto-complete based on the available cities in the database:

Autocomplete in action.

Once a city is selected from the autocomplete it should do a validation as to whether the city is populated with actual data in the database (in case the user types in an invalid city:

Validation for missing city.

This is accomplished using the MVC 3 remote validation which makes it easy to do by adding an annotation to the ViewModel to indicate that the attribute will be remotely validated:

    public class SearchFormViewModel {
        ...
        [Remote("IsCityAvailable","Listings",ErrorMessage="Selected city has no listings, please reselect.")]
        public string City { get; set; }
    }

This of course requires an “IsCityAvailable” action on the “Listings” controller that will return false if there are no database entries for the given city:

     //Check that a city exists on the search selector.
     public JsonResult IsCityAvailable(string city) {
            City findCity = cityRepository.FindByCityName(city);
            if (findCity == null) {
                return Json(false, JsonRequestBehavior.AllowGet);
            } else {
                return Json(true, JsonRequestBehavior.AllowGet);
            }
     }

Conflict with Autocomplete

The problem comes in when the user types in a part of the city name and then selects from the drop-down autocomplete, it causes the remote validation to fire but it only includes the text that was typed, e.g. “A” rather than the selected drop-down text.  This causes the validation to fail when it should indicate success.

This has to do with the way the JQuery validation fires based on key-up and blur events. Researching the web shows that there are ways to turn this part off, but it is complicated by the layer that MVC3 puts on top of the JQuery validation.

Solution

The solution was to add some Javascript to the partial view that defined the search inputs so that the “onkeyup” and “onfocusout” settings are set to false. This is done in the “window.onload” so that it they are turned off early enough in the process:

<script type="text/javascript">
    window.onload = function () {
        var validatorSettings = $('#searchForm').validate().settings;
        validatorSettings.onkeyup = false;
        validatorSettings.onfocusout = false;
    }
</script>

Then a JQuery handler is added to the Search button click event so that the validate is forced when the search button is pressed (also works when the form is submitted via a return):

    $("#searchSubmit").click(function (event) {
        $("#searchForm").validate().element("input#City");
    });
Posted in Software Development | Tagged , , | 3 Comments

Clipboard Printer App

Sometimes you might want to print a small section from an email that has 30-embedded replies or just a snippet of code from that big class file. The Clipboard Printer Windows app makes it easy to do by copying what you want to print into the clipboard (CTL-C or right-mouse “Copy”) and then print it to your printer.

I built this small app for this purpose a couple of years ago and thought I’d share it here in case someone else needed to use it. It’s simple to use:

  • Copy the text you want to print to the clipboard by highlighting it and using CTL-C or right-mouse “Copy”. clipboard_printer_icon
  • Start the Clipboard Printer app by clicking on the icon:
  • Then optionally verify what’s in the clipboard by clicking “Preview” and then click “Print” to send it to the printer:

clipboard_printer

To install the app download the installer MSI file:

ClipboardPrinterSetup.msi

The source code is also available here:

Clipboard Printer Source at Github

Posted in General, Internet, Software Development | Leave a comment

User Initialization in Code First/Altairis

In a previous post I showed how Entity Framework Code First ORM could be integrated with the Altairis Web Security simple membership provider to create a simple way to add a membership provider with an application using the EF 4.1 framework. One of the issues is that when the database is regenerated during development the users would have to be manually re-registered.  This is a hassle if you want to create an initial admin account or user account for testing.

RWBrad asked in the comments if there was a way to seed an initial user in the DBInitializer routine. I did some experimenting with the Seed method and found that it can be done by calling the membership provider directly to create a new user and then adding the appropriate roles via the EF context as shown below:

// Create a user.
MembershipCreateStatus status = new MembershipCreateStatus();
Membership.CreateUser("admin", "password", "admin@user.com");
if (status == MembershipCreateStatus.Success) {
    // Add the role.
    User admin = context.Users.Find("admin");
    Role adminRole = context.Roles.Find("Administrator");
    admin.Roles = new List<Role>();
    admin.Roles.Add(adminRole);
}

Then Adam Nagle then showed that the user can also be created more directly by the context when it’s preferred to keep the data access independent of the provider assembly.

These ideas make this concept more useful by allowing the seeding of initial users without having to go to SQL to add the admin role.

The example ASP.Net MVC3 application has been updated with these changes and is available for download at Github: Download Code

Posted in Uncategorized | Leave a comment

Force Database Initialization in Code First EF

Continuing on the previous post about using the drop-in Altairis.Web.Security membership provider, I ran into an issue where the database may not be recreated in a timely fashion on a change to the model classes. For example if you add the following property to the User class:

public string FullName { get; set; }

And change the initializer in the ApplicationDB.cs class to drop and create the database on model change:

public class DBInitializer : DropCreateDatabaseIfModelChanges<ApplicationDB>

The problem is if you then access the database by creating a new user in the “Account/Register” controller, the database will not drop and create because the Altairis membership provider uses non-EF (ADO.Net classic) methods of data access. Therefore, the Entity Framework access methods haven’t been touched yet and won’t drop/create the DB until that time.

The solution is to add a section to the Application_Start() method in the Global.asax:

protected void Application_Start() {
     AreaRegistration.RegisterAllAreas();

     // Initializes and seeds the database.
     Database.SetInitializer(new DBInitializer());

     // Forces initialization of database on model changes.
     using (var context = new ApplicationDB()) {
          context.Database.Initialize(force: true);
     }

     RegisterGlobalFilters(GlobalFilters.Filters);
     RegisterRoutes(RouteTable.Routes);
}

The code in lines 8-10 forces the context to initialize the database and if there is a model change then it will drop and recreate the database on start of the application, before it can be accessed by the non-EF methods.

The example ASP.Net MVC3 application has been updated with these changes and is available for download at Github: Download Code

Posted in Internet, Software Development | Tagged , | 2 Comments

Code First EF 4.1 with the Altairis Membership/Role Provider

Problem with Current Membership/Role Provider

I’ve always thought the default membership/role provider for ASP.Net is a bit heavy in that it is targeted by default to a different database than the main application database and takes several additional steps to set up and deploy. I found the Altairis Web Security Toolkit on CodePlex and it has a nice, simple schema that is easy to integrate that into your application database. It is also available from Nuget as Altairis.Web.Security.

Working with the EF Magic Unicorn Edition

unicorn07The new Entity Framework Code First, also known as the “EF Magic Unicorn Edition” provides a nice way to generate the database and the ORM from POCO (Plain Old CLR Objects) classes that you write up front. This gives a nice “code first” approach where the domain objects drive the database rather than vice-versa (also known as “persistence ignorance”).

With the current edition of Magic Unicorn the database is constantly being regenerated during development, which interrupts the workflow to do the additional step of adding the membership/role tables. And even if that’s not too much trouble the membership/role tables aren’t accessible to the code first EF context for access by the application.

Code First Integration with the Drop-in Altairis Provider

One solution, besides writing a provider from scratch, is to create code first classes that generate the database schema that is expected by the drop-in membership provider.  That way the membership provider still works as expected without change, and the user/role classes are available to the application for doing administration and easily adding additional columns for the User table.

To implement this I did the following steps for an MVC3 project:

    1. Start a new MVC3 web application project.
    2. Use the NuGet console to download the following packages:
      Altairis.Web.Security
      EntityFramework
    3. Create User and Role classes and include them in a class that defines the EF context. In the context class I did a few special things to make sure that the many-to-many table for the roles was generated correctly:

public class ApplicationDB : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<Role> Roles { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        // Maps to the expected many-to-many join table name for roles to users.
        modelBuilder.Entity<User>()
        .HasMany(u => u.Roles)
        .WithMany(r => r.Users)
        .Map(m =>
        {
            m.ToTable("RoleMemberships");
            m.MapLeftKey("UserName");
            m.MapRightKey("RoleName");
        });
    }
}

Data may also be seeded into the initial database, for example to create some default roles. The commented out class definition can be utilized during development to recreate the database if the model changes:

// Change the base class as follows if you want to drop and create the database during development:
// public class DBInitializer : DropCreateDatabaseIfModelChanges<ApplicationDB>
public class DBInitializer : CreateDatabaseIfNotExists<ApplicationDB>
{
    protected override void Seed(ApplicationDB context)
    {
        var roles = new List<Role>{
            new Role{RoleName = "Administrator"},
            new Role{RoleName = "User"},
            new Role{RoleName = "PowerUser"}
        };

        roles.ForEach(r => context.Roles.Add(r));
    }
}

The classes themselves are straightforward and can be decorated with attributes that integrate well with MVC:

public class User {
    [Key]
    [Required(ErrorMessage = "User Name is required")]
    [Display(Name="User Name")]
    [MaxLength(100)]
    public string UserName { get; set; }

    [Required]
    [MaxLength(64)]
    public byte[] PasswordHash { get; set; }

    [Required]
    [MaxLength(128)]
    public byte[] PasswordSalt { get; set; }

    [Required(ErrorMessage = "Email is required")]
    [MaxLength(200)]
    public string Email { get; set; }

    [MaxLength(200)]
    public string Comment { get; set; }

    [Display(Name = "Approved?")]
    public bool IsApproved { get; set; }

    [Display(Name = "Crate Date")]
    public DateTime DateCreated { get; set; }

    [Display(Name = "Last Login Date")]
    public DateTime? DateLastLogin { get; set; }

    [Display(Name = "Last Activity Date")]
    public DateTime? DateLastActivity { get; set; }

    [Display(Name = "Last Password Change Date")]
    public DateTime DateLastPasswordChange { get; set; }

    public virtual ICollection<Role> Roles { get; set; }

}

public class Role {
    [Key]
    [Display(Name = "Role Name")]
    [Required(ErrorMessage = "Role Name is required")]
    [MaxLength(100)]
    public string RoleName { get; set; }

    public virtual ICollection<User> Users { get; set; }
}

Additional properties could be added to the User class and they wouldn’t interfere with the operation of the membership provider as long a they are not “Required” properties.

I wrote an example ASP.Net MVC3 application and it is available for download at Github: Download Code

Update: I found an issue with database initialization if the model is changed and the EF data access is not initialized before the classic ADO.Net access provided by Altairis. See this post for more information.

Posted in Internet, Software Development | Tagged , | 14 Comments

Magic Pen and Paper

I bought a magic gadget from Best Buy called the LiveScribe smart pen and paper after watching a colleague using it for making notes during a meeting.

Magic Pen

Technology

The smart pen is really a small computer with an infrared camera analyzing a series of micro-dots in a matrix pattern on paper (originally invented by Anoto in Sweden). You write as with an ordinary pen on special notebook paper and the pen also optionally records audio. It can record everything you write and say and all of it is synched in time and saved to the pen.  Later you can play back the whole session or just click the pen on the a section of the paper and hear the audio that was being spoken when you wrote the particular entry. You can also synch it back to a computer to save as PDF or put on the Internet as an interactive Flash presentation.

I was mainly interested in using it to sketch and record ideas on user interface, workflow, and data design for software and web applications.  I was hoping to use the iPad for that but it’s resolution and ease of drawing doesn’t approach that of pen and paper. This “magic pen” combines the best of both worlds.

Usage

Besides capturing design it would also be very useful for:

  • Taking notes and audio during meetings and posting the notes with audio as flash playbacks for later reference.
  • Taking notes in and recording lectures in class (wish I had one of these for that!).
  • Story-boarding or outlining for screenplays, plays, books, etc.
  • Medical professionals taking notes during sessions.

These videos are useful for seeing what it can do:

LiveScribe Pulse Pen Review Part I

LiveScribe Pulse Pen Review Part II

Posted in General, Software Development | 1 Comment

Tropical Storm Hermine Over Driftwood

hermineWe were visited by the “dirty” (west) side of Tropical Storm Hermine on September 7 which dumped some significant rainfall on us. The main density of rainfall walked right up I-35 in what the weathermen call a “train” effect. Then again on September 8 a second load of rain was pulled up from the gulf by the tail of the storm. Unfortunately the ground was still drenched from the previous rain and it resulted in some flooding in our area. The bad thing about flooding in this area are the low-water crossings that people will sometimes try to drive through. In some subdivisions the flooded crossings also trap people so they can’t leave or get back to their house.

There’s a normally-dry creek bed in the ravine behind our house. This afternoon it was a river that we could hear loudly raging from the house.  I walked down to the area of the creek and captured some video of the flooding:

Posted in General | Tagged | Leave a comment