Sitecore OMS Error: Overwhelming Change Notification

Today, our websites generated a stack trace error with an “Out of Memory Exception” message for the whole world to see.

Immediately looking at the IIS logs, we discovered 500 internal server errors over a 3-minute time span. Using the time stamp generated by IIS, I then compared against the error logs created by Sitecore (typically in [website path]\data\logs).

Looking at the Sitecore logs, sandwiched between two Analytics errors, I see the following:

4304 14:29:31 ERROR Failed to insert Analytics data
Exception: System.Data.SqlClient.SqlException
...

4276 14:30:18 INFO  **************************************************
4276 14:30:18 WARN  Sitecore shutting down
4276 14:30:18 WARN  Shutdown message: Overwhelming Change Notification in C:\inetpub\wwwroot
Overwhelming Change Notification in C:\inetpub\wwwroot
Change in GLOBAL.ASAX
HostingEnvironment initiated shutdown
CONFIG change

4304 14:30:26 ERROR Failed to insert Analytics data
Exception: System.Data.SqlClient.SqlException
...

Having no idea what “Overwhelming change notification” meant of what it was referring to, our team contacted Sitecore directly. Turns out that this error is a result of a bug in OMS 1.0.1 (running under Sitecore 6.1). An unhandled exception appeared in the Sitecore OMS module due to improper handling of the AnalyticsLogger class. Their support team were able to reproduce the issue and generate the following error message related to the one triggered above:

ERROR Unhandled exception detected. The ASP.NET worker process will be terminated.
Exception: System.IndexOutOfRangeException
Message: Index was outside the bounds of the array.
Source: mscorlib
   at System.Collections.Generic.List`1.Add(T item)
. . .

Currently, the only work around for this is to disable error logging for Sitecore OMS by following the steps below:

  1. Open the \Website\App_Config\Include\Sitecore.Analytics.config file.
  2. In Sitecore.Analytics.config file, comment the following pipeline’s processor:

    <!– <processor type=”Sitecore.Analytics.

    Pipelines.HttpRequest.StartDiagnostics, Sitecore.Analytics” patch:after=”processor[@type=’Sitecore.Pipelines.HttpRequest.StartMeasurements, Sitecore.Kernel’]” /> –>

Tough choice here…. Keep your OMS error logging or take your chances with random OMS exceptions?

Advertisements

Getting Started with the Facebook C# SDK

Facebook recently announced the release of the Facebook C# SDK. The SDK allows .NET developers to create Facebook applications by directly calling their API. To get started with the SDK, follow these steps:

  1. Download the source and build the FacebookAPI project.
  2. Create your Facebook application from the Developer Section of your Facebook profile’s Application Settings.
  3. Coding your application to use the FacebookAPI.

In this example, I’ll demonstrate the creation of a simple .NET application that communicates with Facebook to pull my profile and friends list.

Building the FacebookAPI Project

First, download the source of the Facebook API project. Open the solution FacebookAPI.sln in Visual Studio and build the project. You will later use Facebook API assembly to interact with Facebook via .NET.

Creating the Application on Facebook

In order to successfully make calls to Facebook, you have to first register your application with Facebook and obtain authentication keys to be used with OAuth 2.0.

1. Go to http://developers.facebook.com/setup/ to begin registering your application. Make sure you use Internet Explorer. I ran into problems when attempting to register using Firefox (application would register, but a blank page was displayed).

2. Register the application using a site name and URL of the path relative to your authenticating logic. The redirect_url parameter you provide to the Facebook Graph API needs to match the path used to register the application.

create facebook application

In this example, I’ve registered the application as:

    Site Name: Dave Test
    Site URL: http://localhost/Facebook/oauth/

3. Once registered, you can view your application’s configuration settings and authentication keys. These details will be referenced in the example code to make requests to Facebook.

my application overview

Coding the Application

To accomplish the task of pulling my Facebook profile and friends list, I need to do the following:

  • Redirect from my local web application to Facebook with my application id and URL of my redirect handler
  • Construct the redirect URL handler to accept the access token provided by Facebook
  • Instantiate the FacebookAPI object with the access token above
  • Access my Profile via the FacebookAPI

1. Redirecting to Facebook

We need to send Facebook our application id and URL of the handler for Facebook’s redirect, containing our access token.


protected void btnAuthenticate_Click(object sender, EventArgs e)

{

    string clientId = "117342178314989";

    string redirectUrl = "http://localhost/Facebook/oauth/oauth-redirect.aspx";

 

    Response.Redirect(string.Format("https://graph.facebook.com/oauth/authorize?client_id={0}&redirect_uri={1}", clientId, redirectUrl));

}

Notice that the variable clientId matches the field Application Id in my Facebook Application configuration settings and the relative path in the variable redirectUrl matches the path defined in the field Connect URL.

After redirecting, a response is sent back to http://localhost/Facebook/oauth/oauth-redirect.aspx containing a code in the query string parameters of the URL. Successfully making a call, results in the following URL:

http://localhost/Facebook/oauth/oauth-redirect.aspx?code=2.UwNcNB5FfO69d_l5S1j76Q__.3600.1280984400-1427490881%7CGE2JRQaeMDwAZHwZMkk0NUiMQD4.

Notice the parameter code. This value will be used to request an access token from Facebook’s Graph API.

2. Building the Handler for Facebook’s Redirect

In step 1, we’ve created the request to Facebook. In step 2, we need to build the handler to accept the access token provided by Facebook to successfully make API calls.

Currently, there’s nothing built into the API that requests the access token, so I had to build one. The code below calls the Facebook Graph API, requesting an access token.


private Dictionary<string, string> GetOauthTokens(string code)

{

    Dictionary<string, string> tokens = new Dictionary<string, string>();

 

    string clientId = "117342178314989";

    string redirectUrl = "http://localhost/Facebook/oauth/oauth-redirect.aspx";

    string clientSecret = "bc7996cfc4f0c66d0417b54eea73f4e7";

    string scope = "read_friendlists,user_status";

 

    string url = string.Format("https://graph.facebook.com/oauth/access_token?client_id={0}&redirect_uri={1}&client_secret={2}&code={3}&scope={4}",

                    clientId, redirectUrl, clientSecret, code, scope);

 

    HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;

    using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)

    {

        StreamReader reader = new StreamReader(response.GetResponseStream());

        string retVal = reader.ReadToEnd();

 

        foreach (string token in retVal.Split('&'))

        {

            tokens.Add(token.Substring(0, token.IndexOf("=")),

                token.Substring(token.IndexOf("=") + 1, token.Length - token.IndexOf("=") - 1));

        }

    }

 

    return tokens;

}

Variables clientId and clientSecret should match fields Application Id and Application Secret, respectively, in the Facebook Application Settings page.

Scope defines the scope of the request. These values are considered Extended Permissions which means requesting access to data not marked as public to everyone in a user’s Facebook profile.

3. Instantiate FacebookAPI with an Access Token

The method GetOauthTokens accepts a parameter code. We’ll pass in the code value obtained in the query string param of the response in step 1 and cache the response for the time defined by the expiration value in Facebook’s Graph API response.


protected void Page_Load(object sender, EventArgs e)

{

    if (Request.Params["code"] != null)

    {

        Facebook.FacebookAPI api = new Facebook.FacebookAPI(GetAccessToken());

        ...

    }

}

 

private string GetAccessToken()

{

    if (HttpRuntime.Cache["access_token"] == null)

    {

        Dictionary<string, string> args = GetOauthTokens(Request.Params["code"]);

        HttpRuntime.Cache.Insert("access_token", args["access_token"], null, DateTime.Now.AddMinutes(Convert.ToDouble(args["expires"])), TimeSpan.Zero);

    }

 

    return HttpRuntime.Cache["access_token"].ToString();

}

4. Access My Facebook Profile

Now that we have an active connection with Facebook, we can use the API in step 3 to request my profile information. Doing so is as easy as a few lines of code:


JSONObject me = api.Get("/me");

JSONObject meFriends = api.Get("/me/friends");

making Get requests to Facebook via the API returns JSON containing profile information. The first requests my profile while the second obtains my friends list.

Placing a watch on these objects gives us
a watch on me

a watch of variable meFriends

As you can see, the variable me contains all of my public profile attributes. The variable meFriends has all 188 of my friends in an array of dictionary items. Each friend is stored in an id/name combo. If we wanted, we could take this another level deeper and get all friends profiles by requesting the id via the Graph API like so (1427490881 is my Facebook id):


JSONObject me = api.Get("/1427490881");

Full Source

/Default.aspx.cs

using System;

using System.Collections;

using System.Configuration;

using System.Data;

using System.Linq;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Linq;

 

namespace Facebook

{

    public partial class _Default : System.Web.UI.Page

    {

        protected void btnAuthenticate_Click(object sender, EventArgs e)

        {

            string clientId = "117342178314989";

            string redirectUrl = "http://localhost/Facebook/oauth/oauth-redirect.aspx";

 

            Response.Redirect(string.Format("https://graph.facebook.com/oauth/authorize?client_id={0}&redirect_uri={1}", clientId, redirectUrl));

        }

    }

}

/oauth/oauth-redirect.aspx.cs


using System;

using System.Collections;

using System.Configuration;

using System.Data;

using System.Linq;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Linq;

using Facebook;

using System.IO;

using System.Net;

using System.Collections.Generic;

 

namespace Facebook

{

    public partial class oauth_redirect : System.Web.UI.Page

    {

        protected void Page_Load(object sender, EventArgs e)

        {

            if (Request.Params["code"] != null)

            {

                Facebook.FacebookAPI api = new Facebook.FacebookAPI(GetAccessToken());

 

                JSONObject me = api.Get("/me");

                JSONObject meFriends = api.Get("/me/friends");

            }

        }

 

        private string GetAccessToken()

        {

            if (HttpRuntime.Cache["access_token"] == null)

            {

                Dictionary<string, string> args = GetOauthTokens(Request.Params["code"]);

                HttpRuntime.Cache.Insert("access_token", args["access_token"], null, DateTime.Now.AddMinutes(Convert.ToDouble(args["expires"])), TimeSpan.Zero);

            }

 

            return HttpRuntime.Cache["access_token"].ToString();

        }

 

        private Dictionary<string, string> GetOauthTokens(string code)

        {

            Dictionary<string, string> tokens = new Dictionary<string, string>();

 

            string clientId = "117342178314989";

            string redirectUrl = "http://localhost/Facebook/oauth/oauth-redirect.aspx";

            string clientSecret = "bc7996cfc4f0c66d0417b54eea73f4e7";

            string scope = "read_friendlists,user_status";

 

            string url = string.Format("https://graph.facebook.com/oauth/access_token?client_id={0}&redirect_uri={1}&client_secret={2}&code={3}&scope={4}",

                            clientId, redirectUrl, clientSecret, code, scope);

 

            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;

            using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)

            {

                StreamReader reader = new StreamReader(response.GetResponseStream());

                string retVal = reader.ReadToEnd();

 

                foreach (string token in retVal.Split('&'))

                {

                    tokens.Add(token.Substring(0, token.IndexOf("=")),

                        token.Substring(token.IndexOf("=") + 1, token.Length - token.IndexOf("=") - 1));

                }

            }

 

            return tokens;

        }

    }

}

Integrating Selenium Tests into CruiseControl.Net via NUnit

Getting Selenium and CruiseControl.Net to talk to each other requires some work and behind-the-scenes configuration. Before incorporating Selenium tests into CruiseControl.Net, make sure you:

To successfully get Selenium, NUnit and CruiseControl.Net talking to each other, you will have to accomplish the following:

  1. Configure Selenium RC to run as a service
  2. Edit your CruiseControl.Net config file to include a NUnit task
  3. Point NUnit to your Selenium Unit Test Library

The details of this article help to get you started in accomplishing the tasks above.

Running Selenium RC as a service

By default, Selenium RC runs as a stand-alone application capable of managing Selenium unit tests and directing traffic for different browser requests. If you want to incorporate your Selenium tests into CruiseControl.Net, you have to get Selenium RC running as a service.

I found a great resource that details how to do this. To summarize the article, follow these simple steps:

  1. Download a copy of the Windows Resource Kit.
  2. Register the new service “SeleniumRC”

    "C:\Program Files\Windows Resource Kits\Tools\instsrv.exe" SeleniumRC
    "C:\Program Files\Windows Resource Kits\Tools\srvany.exe" -a [myuser] -p [mypass]
    
  3. Edit your registry to include the path of your Selenium RC installation and executable:

    Windows Registry Editor Version 5.00
    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SeleniumRC\Parameters]
    "Application"="java.exe"
    "AppDirectory"="C:\\Program Files\\selenium-server-1.0.1"
    "AppParameters"="-Xrs -jar selenium-server.jar"
    
  4. Now that you have the Selenium RC service created, go to Administrative Tools > Services and start the service. Check the system event logs for errors to ensure everything is working properly.

    Wire-Up Selenium to CruiseControl.Net using NUnit

    With the Selenium RC service running, edit your CruseControl.Net config file to incorporate NUnit:

    
    

        <tasks>

          <exec>

            <executable>C:\Program Files (x86)\NUnit 2.5.5\bin\net-2.0\nunit-console.exe</executable>

            <buildArgs>"C:\Users\Dave\Documents\Visual Studio 2008\Projects\SeleniumTest\SeleniumTest\bin\Debug\SeleniumTest.dll"</buildArgs>

          </exec>

        </tasks>

    After a successful execution of your test plan using Selenium RC in CruiseControl.Net, you should see a response from NUnit in your CruiseControl.Net build log like the following:

    <buildresults>
      <message>NUnit version 2.5.5.10112</message>
      <message>Copyright (C) 2002-2009 Charlie Poole.</message>
      <message>Copyright (C) 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov.</message>
      <message>Copyright (C) 2000-2002 Philip Craig.</message>
      <message>All Rights Reserved.</message>
      <message>Runtime Environment - </message>
      <message>   OS Version: Microsoft Windows NT 6.1.7600.0</message>
      <message>  CLR Version: 2.0.50727.4927 ( Net 2.0 )</message>
      <message>ProcessModel: Default    DomainUsage: Single</message>
      <message>Execution Runtime: net-2.0</message>
      <message>.</message>
      <message>Tests run: 1, Errors: 0, Failures: 0, Inconclusive: 0, Time: 20.9481982 seconds</message>
      <message>  Not run: 0, Invalid: 0, Ignored: 0, Skipped: 0</message>
    </buildresults>
    </build>
    </cruisecontrol>
    

How to Register ASP.NET with IIS7

The ASP.NET IIS Registration Tool is no longer required to register ASP.NET with IIS7. Follow the steps below to register ASP.NET with IIS7 for both Windows 7 and Windows Server 2008:

Windows 7

1. Go to Start > Control Panel > Programs and Features
2. Click on the Turn Windows features on or off link.
Turn Windows Features On or Off

3. Expand Internet Information Services > World Wide Web Services > Application Development Features and select ASP.NET and any other features you wish to install.

Choose ASP.NET

Choose ASP.NET

 

Windows Server 2008

1. Go to Start > Control Panel > Programs and Features
2. Click on the Turn Windows features on or off link. The Server Manager window will open.

Windows Server 2008 Server Manager

3. From within the Server Manager, Click on Roles.
4. Click on Add Roles.
5. Select Web Server (IIS).

Windows Server 2008 Add Role

Next, add the ASP.NET Role Service while still remaining within the Server Manager:

1. Click on Role Services.
2. Click on Add Role Services.
3. Select ASP.NET and follow any confirmation messages.

Windows Server 20008 IIS Role Services

Add Role Services for ASP.NET

Windows Server 2008 IIS Role Services Confirmation

Confirm Installation of Required Components

Configuring CruiseControl.Net with SVN, Visual Studio 2008 and MSBuild

Integrating CruiseControl.Net into our development environment was a fairly simple process. The steps below detail what was required to get CruiseControl.Net to pull changes from SVN, on an interval trigger, then build using Visual Studio 2008 via MSBuild.

For details on configuration options for CruiseControl, refer to the online documentation.

Installing CruiseControl.Net

1. Download the latest installation files. The latest release at the time of this article is 1.5.725.

2. Run the installation file and place the files in the default directory C:\Program Files\CruiseControl.NET.

CruiseControl.Net Overview

CruiseControl can run either as a stand-alone exe or by running as a service. It’s important to run the stand-alone application when building your config file at first. The exe will run in a command window displaying everything that’s happening within your CruiseControl.Net server. It’s an essential tool to debugging your config file.

Stand alone application is located in: C:\Program Files\CruiseControl.NET\server\ccnet.exe

The CruiseControl.Net service is named CruiseControl.Net Server (in Control Panel/Administrative Tools/Services)

Editing Your Configuration File

1. Open CruiseControl.Net’s main configuration file

Locate file ccnet.config in C:\Program Files\CruiseControl.NET\server.

2. Add your project


<project name="Public Website">

  <workingDirectory>d:\build\trunk\Website</workingDirectory>

  <webURL>http://server1/ccnet/server/local/project/testProject/ViewLatestBuildReport.aspx</webURL>

  <triggers>

    <intervalTrigger name="continuous" seconds="30" buildCondition="ForceBuild" initialSeconds="30"/>

  </triggers>

  ...

</project>

The project contains the following tags:

  • <workingDirectory> – The directory CruiseControl.Net will use to manage your project.
  • <webURL> – The build report for the project you’re configuring.
  • <triggers> – How often CruiseControl will pull down files from source control and build the solution. The example above has an interval trigger of 30 seconds. Every 30 seconds CruiseControl will check source control for modifications. If they exist, a build will be triggered.

3. Define SVN as your Source Control


    <sourcecontrol type="svn">

      <trunkUrl>https://MyServer/svn/website/trunk</trunkUrl>

      <workingDirectory>d:\build\Website</workingDirectory>

      <username>dave</username>

      <password>dave123</password>

      <timeout units="minutes">30</timeout>

    </sourcecontrol>

Within the <sourcecontrol> tag, our SVN configuration is defined:

  • <trunkUrl> – Location of the main trunk for our project.
  • <workingDirectory> – Directory to place all files pulled down from SVN when doing a build.
  • <username> / <password> – SVN credentials

4. Add an MSBuild task

A basic MSBuild task is below, essentially building our solution from the command prompt using Visual Studio. Build options used are debug and rebuild all.

    <tasks>

      <msbuild>

        <executable>C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe</executable>

        <workingDirectory>D:\build\Website</workingDirectory>

        <projectFile>MyWebSolution.sln</projectFile>

        <buildArgs>/p:Configuration=Debug /v:diag /t:rebuild</buildArgs>

        <timeout>120</timeout>

      </msbuild>

    </tasks>

5. Configure Notifications

CruiseControl.Net does a great job of notifying when builds break. The CCTray, CruiseControl’s notification icon stays in the bottom right-hand corner of your desktop in your system tray. Your icon turns green on successful builds, yellow when building and red when the build fails.

If this isn’t enough, you can setup email notifications. If you work in an environment where you have outsourced development, it helps to send out instant notifications if someone breaks the build.

    <publishers>

      <xmllogger logDir="D:\build\Website\BuildLogs" />

      <email mailport="25" includeDetails="TRUE">

        <from>no-reply@wordpress.com</from>

        <mailhost>mail.MyServer.com</mailhost>

        <users>

          <user name="Dave" group="BuildGuru" address="david.scott.peterson@gmail.com" />

        </users>

        <groups>

          <group name="BuildGuru">

            <notifications>

              <notificationType>Failed</notificationType>

              <notificationType>Fixed</notificationType>

              <notificationType>Exception</notificationType>

            </notifications>

          </group>

        </groups>

      </email>

    </publishers>

Server Configuration

The CruiseControl.Net service needs to run as an account that has access to the source code repository. Since our source control is listed under HTTPS, but with no valid SSL certificate, we have to convince CruiseControl to ignore the certificate error. The CruiseControl.Net user account needs to permanently accept the certificate exception, otherwise, CriuseControl will fail to pull down the latest code from SVN.

Steps to creating the CruiseControl.Net service account:

1. Create a CruiseControl.Net local user account.

New CruiseControl.Net User

Create a new user for the CruiseControl.Net service

2. Setup service to run as new CruiseControl.Net local user account.

CruiseControl.Net Service Settings

Run the service as your new CCNetUser local account

3. Accept SSL exception for CruiseControl.Net local user account.

Accept the SSL Certificate Permanently

Accept the SSL Certificate Permanently

Login to the server hosting CruiseControl.Net using the account created in step 1. Open a command prompt and type: ‘svn list https://<svn repository location>’. When prompted to accept the certification exception, type ‘p’ for permanently.

Full CCNet.config

<cruisecontrol>

  <!– This is your CruiseControl.NET Server Configuration file. Add your projects below! –>

 

  <!– Trunk –>

  <project name=My Website>

    <workingDirectory>d:\build\trunk\Website</workingDirectory>

    <webURL>http://server1/ccnet/server/local/project/testProject/ViewLatestBuildReport.aspx</webURL>

    <triggers>

      <intervalTrigger seconds=30 buildCondition=IfModificationExists/>

    </triggers>

    <sourcecontrol type=svn>

      <trunkUrl>https://MyServer/svn/website/trunk</trunkUrl>

      <workingDirectory>d:\build\Website</workingDirectory>

      <username>dave</username>

      <password>dave123</password>

      <timeout units=minutes>30</timeout>

    </sourcecontrol>

    <tasks>

      <msbuild>

        <executable>C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe</executable>

        <workingDirectory>D:\build\Website</workingDirectory>

        <projectFile>MyWebSolution.sln</projectFile>

        <buildArgs>/p:Configuration=Debug /v:diag /t:rebuild</buildArgs>

        <timeout>120</timeout>

      </msbuild>

    </tasks>

    <externalLinks>

      <externalLink name=My Website url=http://MySite.com />

    </externalLinks>

    <publishers>

      <xmllogger logDir=D:\build\Website\BuildLogs />

      <email mailport=25 includeDetails=TRUE>

        <from>no-reply@wordpress.com</from>

        <mailhost>mail.MyServer.com</mailhost>

        <users>

          <user name=Dave group=BuildGuru address=david.scott.peterson@gmail.com />

        </users>

        <groups>

          <group name=BuildGuru>

            <notifications>

              <notificationType>Failed</notificationType>

              <notificationType>Fixed</notificationType>

              <notificationType>Exception</notificationType>

            </notifications>

          </group>

        </groups>

      </email>

    </publishers>

  </project>

</cruisecontrol>

Removing Carriage Return + Line Feed in T-SQL

So annoyed by a CR+LF in XML values within in a table I’m looking at right now. Easily removed with…


REPLACE(REPLACE(XmlField, CHAR(10), ''), CHAR(13), '')

Creating Selenium Unit Test Suites with NUnit

When looking for a way to test our websites by using web macros, directly interacting with the rendered presentation of our sites, I ran across quite a few test suites. Both Waitr and Selenium stood out as the more stable, extensible and easy to incorporate test suites out there. Selenium, however, seemed to offer easy implementation on a .Net platform. Once properly setup, Selenium unit tests are as easy to create as opening Firefox, browsing the site you want to test and record your unit test macro as you navigate from one page to another.

Selenium comes in with a few different installation components and programs:

  • Selenium IDE – Firefox plugin used to create the unit tests.
  • Selenium Core – Core libraries for .Net/C#.
  • Selenium Remote Control -Allows for managing Selenium unit tests with multiple broswers simultaneously (includes the Selenium Core libraries).
  • Selenium Grid -Load balance your tests across multiple servers.

Installing Selenium IDE

Download and install the Selenium IDE. This will add a “Selenium IDE” option under tools in your Firefox browser.

Installing Selenium Remote Control

Download the Selenium RC installation files and extract to a location on your test server. For this example, I extracted to c:\Selenium-Remote-Control\.

Starting the Selenium Server is as easy as running “java -jar selenium-server.jar” from the directory of your Selenium Server installation. Since this is a java-based application, you may be required to download the latest version of java prior to successfully starting the Selenium Server.

Starting selenium server

Starting the Selenium Server using Java v1.6.017

If your Selenium Server output resembles something like above, then you’re in business.

Installing NUnit

Installing Selenium Server is not enough. You must also install NUnit to drive the C# generated unit tests that target the Selenium server.

Download the NUnit installation files and install the software to your test server.

Creating Your First Selenium Unit Test

1. Open Firefox

2. Go to tools and select Selenium IDE

Starting Selenium IDE

Starting the Selenium IDE

3. Once the IDE opens, it defaults to recording every action you take on a given website. Select the output that the IDE will use to generate your unit test. For this example, we’re using C#.

Choose C#

Choose C# to output your test

4. While still within Firefox, click through the website for which you want to create a unit test. Every action you take will be recorded by the IDE, with your unit tests generated immediately.

5. When done generating your test, click on the record/stop button to end the IDE. You’ll see your complete unit test within the Source tab of the Selenium IDE window.

Selenium IDE Record Actions

Record your actions in C#

Example Unit Test Generated by the Selenium IDE

Clicking through w3school’s website generated the following code:

Selenium Test Code

Snapshot of Generated Code

Steps to generate the code above:

Clicked on Next Chapter

Clicked on "Next Chapter"

Clicked on Try it Yourself

Clicked on Try it Yourself

Edited the HTML

Edited the HTML

Running The Example Test

1. Take the C# code generated by the Selenium IDE and add it as a class to a new Visual Studio project.

2. Add references to your project for the following dll’s

  • C:\Selenium-Remote-Control\selenium-dotnet-client-driver-1.0.1\nmock.dll
  • C:\Selenium-Remote-Control\selenium-dotnet-client-driver-1.0.1\nunit.core.dll
  • C:\Selenium-Remote-Control\selenium-dotnet-client-driver-1.0.1\nunit.framework.dll
  • C:\Selenium-Remote-Control\selenium-dotnet-client-driver-1.0.1\ThoughtWorks.Selenium.Core.dll
  • C:\Selenium-Remote-Control\selenium-dotnet-client-driver-1.0.1\ThoughtWorks.Selenium.IntegrationTests.dll
  • C:\Selenium-Remote-Control\selenium-dotnet-client-driver-1.0.1\ThoughtWorks.Slenium.UnitTests.dll
Selenium Project References

Selenium Project References

3. Build the solution.

4. Open NUnit. Select File > Open Project… and select the your project’s compiled assembly.

5. Within NUnit, highlight your unit test class name and click on Run.

NUnit Run

Sit back and watch the show. NUnit will kick off the unit test, which runs the compiled code generated by the Selenium IDE. You’ll see the Selenium Server output the commands in the command prompt window. Selenium Remote Control Server then opens, which triggers the opening of a browser window to run the recorded Selenium unit test. NUnit will then report back the results of the test.

Selenium in Action

Selenium in Action