Monthly Archives: February 2011

Selenium smoke testing using sitemap

It seems to me that if you have a smaller sized site, its probably useful to run selenium against all the sitemap.xml files, just to make sure all the pages work and don't immediately come up with errors - a very basic smoke test.

After spending 15 minutes googling and not finding anything exactly what I was looking for, I thought I would jot down a bit of code in case anyone else finds it useful.

 

private static string baseUrl = "http://site.com";
private static string sitemapRelativeUrl = "/google-sitemap.aspx";
private ISelenium selenium;

[TestFixtureSetUp]
public void SetupTest()
{
selenium = new DefaultSelenium("localhost", 4444, "*chrome", baseUrl);
selenium.Start();
}

[TestFixtureTearDown]
public void TeardownTest()
{
selenium.Stop();
}

/// <summary>
/// Get a navigator for the sitemap
/// </summary>
/// <returns></returns>
private XPathNavigator GetSitemapNavigator()
{
System.Xml.XmlReader xmlReader = new System.Xml.XmlTextReader(baseUrl + sitemapRelativeUrl);
System.Xml.XPath.XPathDocument doc = new System.Xml.XPath.XPathDocument(xmlReader);
var nav = doc.CreateNavigator();
return nav;
}

/// <summary>
/// Get a namespace manager for the sitemap
/// </summary>
/// <param name="namespaceAlias"></param>
/// <returns></returns>
private XmlNamespaceManager GetSitemapManager(XPathNavigator nav, string namespaceAlias)
{
XmlNamespaceManager manager = new XmlNamespaceManager(nav.NameTable);
manager.AddNamespace(namespaceAlias, "http://www.sitemaps.org/schemas/sitemap/0.9");
return manager;
}

/// <summary>
/// Make sure that the sitemap can be loaded and has entries
/// </summary>
[Test]
public void LoadSitemapAndCheckQuery()
{
var nav = GetSitemapNavigator();
var manager = GetSitemapManager(nav, "sitemap");
Assert.IsTrue(nav.Select("//sitemap:loc", manager).Count > 0);
}

/// <summary>
/// Load up each of the sitemap pages
/// </summary>
[Test]
public void LoadAllSitemapPages()
{

List<string> ExpectedRedirects = new List<string>();
ExpectedRedirects.Add(string.Format("{0}/url.aspx", baseUrl));

var nav = GetSitemapNavigator();
var manager = GetSitemapManager(nav, "sitemap");
XPathNodeIterator iterator = nav.Select("//sitemap:loc", manager);
if (iterator.Count > 0)
{
Uri url = null;
while (iterator.MoveNext())
{
try
{
if (Uri.TryCreate(iterator.Current.InnerXml, UriKind.RelativeOrAbsolute, out url))
{
selenium.Open(url.ToString());
string currentBodyText = selenium.GetBodyText();

Assert.IsFalse(currentBodyText.IndexOf("Error parsing XSLT file:") >= 0, string.Format("Error parsing XSLT File url: {0}", url));
Assert.IsFalse(currentBodyText.IndexOf("Error reading XSLT file:") >= 0, string.Format("Error reading XSLT File url: {0}", url));
Assert.IsFalse(currentBodyText.IndexOf("Server Error in '/' Application.") >= 0, string.Format("Server error url: {0}", url));

// Unless we are expecting the page to redirect, throw an error if it does
if (!ExpectedRedirects.Contains(url.ToString()))
Assert.AreEqual(url.ToString().Replace("'", "%27"), selenium.GetLocation(), "{0} was redirected to {1}", url.ToString(), selenium.GetLocation());
}
}
catch (Exception ex)
{
Assert.Fail(string.Format("Exception found. Last url: {0} Exception: {1}", url, ex));
}
}
}
}

Umbraco deeplinking (aka loading content node on login)

I spent at least 10 minutes googling without an answer, since I didn't know the keyword 'deeplinking', so in case anyone else is interested:

How do you load a content node in Umbraco via a url?

/umbraco/umbraco.aspx?app=content&rightAction=editContent&id={nodeId}

Seems like this syntax can be used for accessing anything in the umbraco cms.  Quite useful!

Deploying to Umbraco

How do you deploy Umbraco?

 

Up until this point, I was either working on the occasional file which could just be copied or just working via the cms website.  But when you have a larger deployment, the ordering of items becomes important.  So here's my initial checklist.  Now to figure out how to automate more of this.

 

Standard Deployment steps:

1) Backup files from environment

2) Create any new Relation Types in Umbraco CMS

3) Create any new Data Types in Umbraco CMS

4) Create any new masterpages in Umbraco CMS

5) Import any new Doc Types in Umbraco CMS (order is important)

6) Create any Dictionary Items

7) Alter Doc Types to allow for updated Templates / Structure

8) Copy files to environment

9) Create Macros

10) Create nodes

11) Update nodes

Trac & Milestones

From my understanding, with Agile, you want very small iterations.  Release often and frequently.

However, there is always a bit of admin to do beforehand.  Dev environments need to be setup, some type of project plan is usually required, etc.

Most of my development setup is complete, I have a workstation with Visual Studio & Sql Server and I have a server with SVN.  I did have to install Trac on my linux server, which although wasn't very complicated, still took 1/2 hour to get everything correct.

I don't want to overdue the project management, rather just a basic area to keep track of how things are progessing and a place to organise future enhancements.

In keeping it simple, I have the following milestones setup:

  • Intial Website where the user should be able to create an account, login, upload their laugher
  • Better Website Features where the user can rate other people's laughter and play a guessing game
  • Basic Facebook integration - as I don't know much about facebook integration, I will fill this in later, but its enough for now to know reach is needed
  • Improved website design - I'm focusing on funcationality first as design is usually easy to plug in later on.  I'm not a designer, so even an improved design will still be a bit crap, but I should be able to at least get it looking clean and simple.
  • IOS application - again, I don't know much about this, so will leave it to later

So now the focus is to enter in the tickets for the first milestone and creating a basic website.

I know that my BDD is very weak, so research on that as well as research on Azure will be the first tasks.

Project planning complete for now.  Once research is done, I should be able to flesh out the tickets a bit more and put some times down.

#devchallenge Announcement

With about a month to spare, I have decided to set myself a bit of a challenge and launch a site laughterbank.com that I've been meaning to do for awhile.

Laugherbank will be a simple website to upload your laughter (mp3 type recording), listen to other people's laughter and rate them (on the funniness scale).

To make it interesting, I want to upgrade my skillset a bit and learn some new technoogies that I've been meaning to pick up.  So I plan on using/doing the following:

  • I'm finally going to try using twitter (#devchallenge) and see if there's any use in it.  Also, will finally use my blog beyond just technical notes for myself.
  • Asp.Net MVC - v3 beta is out, so it appears to be the future. Time to get onboard.
  • TDD - I've created and used unit tests, but its always been after the fact.  Time to see how creating the test beforehand actually works in a project.
  • BDD - I've never used it before - lets see how it works.
  • Continous build - I've used it before and its good, so its about time to have it running in my environment.
  • Azure hosting - Its the new thing.  I'm sure the scability is good, but I've heard there are some tricks to get a site running with low costs.  Lets see how feasibile this is.  If its too expensive, then I'll host it on my windows vps and perhaps move it to amazon aws if the traffic ramps up.
  • Agile Development - With myself as the only team member, I don't think daily scrums are necessary, but there can definitely be apsects of scum applied even to a personal project.  I'll be using trac to manage this project.
  • IOS - I signed up to the apple developer network about a year ago.  Its finally time to get an app out there.
  • Facebook App - I'm about 5 years late on this one, but its a good way to get lots of traffice for a social network application.
  • And if time, a Windows 7 mobile app and Android app would be good as well.

So, off I go.  Wish me luck and hope to hear some comments.

Remote Debugging

There always seems to be a bit of confusion setting up remote debugging in a cross domain environment.  In my current contract, there is the domain we log into (domain1), and then the development domain (domain2) which we have control over. Perhaps not all of these items are required and it is definitely not a secure method, but if they are set, then it should work.

Domain1

==

LM1 (Local machine)

User1 (your login account)

 

Domain2

==

RM1 (Remote machine to be debugged)

 

* On RM1, create local account RM1\User1  Assign to local administrators group.

* Make sure that Domain2\Administrator has the same password as LM1\Administrator.  Also, neither account should be locked out.

* Turn off firewalls on both machines (make sure to do in the windows firewall setting - the service still needs to run)

* Login to RM1 as Domain2\Administrator

* Start (install in necessary) the Remote Debug Monitor (run as an app, not as a service).

** Tools/Permissions, Add RM1\User1 with Debug permissions.

** Tools/Options, set server name to: RM1\User1@RM1

* On LM1, Visual Studio, Attach to Process, Transport Default, Qualifier = RM1\User1@RM1.  Note that @RM1 can be replaced by @RM1_IPAddress, however, it's better to add RM1 to the hosts file.

WinMerge Settings

WinMerge is a great diff tool.
A few options to change (Edit/Options)

Compare: Ignore Carriage Return Differences
System: Add to explorer context Menu + Enable advanced menu + Include subfolders by default
External editor: C:\Program Files\Notepad++\notepad++.exe
Backup File: Untick File Backup

Tortoise

Tortoise has a few settings that will improve performance and useability.

The first is to only use the icon overlay in a specific folder (and subfolders). I put all my local files under c:\Working Docs.
Go to the settings menu, Look And Feel, Icon Overlays and under include path type in something like c:\Working Docs\*

I also tend to use Diff quite a bit, so under settings, Look and Feel, untick Diff, and it will now show up in the main context menu instead of the sub-context menu.

Finally, I find WinMerge a much easier app to use than TortosieMerge. Provided WinMerge is installed, go to Settings/External Programs, Select External and type in C:\Program Files\WinMerge\WinMergeU.exe (or the relivent path).

Accessing Underlying Data in DataBound Event

I always forget how to access the underlying data in a DataBind Event. Example:

protected void userListItem_Bound(Object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataRowView currentRow = (DataRowView)e.Row.DataItem;
string currentUser = (string)currentRow["Username"];
}
}

FindControlR

FindControlR is a very useful method to include in an Asp.Net project. If you don't know which control holds a control, you can use a parent control (such as form) to find it.