Archive for the 'C#' Category

Run Watir Tests from within Visual Studio

I have been having a bit of a play with the Watir Ruby web UI testing framework and after a bit of jiggery pokery I’ve managed to get it all going inside of Visual Studio. Here’s how…

You will need to install:

I had a bit of trouble getting Watir to install on Windows XP using the Windows installer but I think that was due to having installed Ruby using InstantRails. Once I installed it using the Ruby Windows installer it worked OK. On Vista however the installer wasn’t playing nicely at all. To install on Vista required the use of RubyGems which basically involves typing:

    gem install watir

… at the command line. Simple as that. One thing to note is that if you install Watir using the ‘gem’ approach you need to add the line:

    require ‘rubygems’

at the top of your test ruby files before adding:

    require ‘watir’

Thanks to my Ruby (tor)mentor Dave Verwer for that gem. (oh dear…)

Ruby in Steel (worst name ever competition winner 2007) will allow you to debug your Watir tests and edit them with all of the Visual Studio goodness in place.

Once you have all that in order you need a bit of code to hook your Ruby scripts into the usual NUnit/TestDriven way of things. You have two options (writing it yourself being a third). Either go ‘the whole hog’ and try and get this article on Code Project running or use the code below, adapted from Scott Hanselman’s efforts to do the same thing. (I say ‘adapted’. I mean added the ‘directoryPath’ argument as Scott’s version seemed to need the .rb files to be put in the bin, so to speak)

public class WatirAssert 
{ 
    public static void TestPassed(string rubyFileName, 
    string directoryPath) 
    { 
        string output = String.Empty; 
        using (Process p = new Process()) 
        { 
            p.StartInfo.UseShellExecute = false; 
            p.StartInfo.RedirectStandardOutput = true; 
            p.StartInfo.FileName = "ruby.exe"; 
            p.StartInfo.Arguments = rubyFileName; 
            p.StartInfo.WorkingDirectory = directoryPath; 
            p.Start(); 
            output = p.StandardOutput.ReadToEnd(); 
            p.WaitForExit(); 
        } 
        Console.Write(output); 
        Trace.Write(output); 
        Regex reg = new Regex(@"(?<tests>\d+)\stests,\s(?<assertions>\d+)\sassertions,\s(?<failures>\d+)\sfailures,\s(?<errors>\d+)\serror\s", RegexOptions.Compiled); 
        Match m = reg.Match(output); 
        try 
        { 
            int tests = int.Parse(m.Groups["tests"].Value); 
            int assertions = int.Parse(m.Groups["assertions"].Value); 
            int failures = int.Parse(m.Groups["failures"].Value); 
            int errors = int.Parse(m.Groups["errors"].Value); 
            if (tests > 0 && failures > 0) 
            { 
                Assert.Fail(String.Format("WatirAssert: Failures {0}", failures)); 
            } 
            else if (errors > 0) 
            { 
                Assert.Fail(String.Format("WatirAssert: Errors {0}", errors)); 
            } 
        } 
        catch (Exception e) 
        { 
            Assert.Fail("WatirAssert EXCEPTION: " + e.ToString()); 
        } 
    } 
}

Where you stick this is entirely up to you but you need to be able to reference it from your unit tests so you could put it in its own assembly or just add the class to your unit test project.

Once you have all that sorted out you can now add a .NET unit test such as the following:


[TestFixture] 
public class UITest 
{ 
    [Test] 
    public void LoginTests() 
    { 
       WatirAssert.TestPassed("login_tests.rb", @"C:MyAppWatirTestDirectoryUI Tests\"); 
    } 
}

In this example “login_tests.rb” is the name of the Ruby script file containing the Watir test (or tests) and the directoryPath argument is the directory containing said Ruby file.

Now, using TestDriven.NET we can right-click on the above code in VS and run the test. We can add a break point to the C# code and right-click to debug through the test. As we have Ruby in Steel installed we can also use Visual Studio to edit the Ruby file and whilst doing so we can add breakpoints in the Ruby and step into the executing Ruby with the debugger.

Oh joy…

Whilst I am on the topic I have to say that I think Ruby is rubbish. It is supposed to be the language of the Gods and it can’t even tell that when I add a semi-colon at the end of EVERY SODDING LINE, I didn’t mean to do it. Couldn’t it just ignore them for me if it is supposed to be so clever…

Generic Methods… Now there’s a thing

Like the rest of the .NET world I have been soaking up the classes in the System.Collections.Generic namespace which have saved me a shed load of lines of custom collection code.

The other day I was writing some CodeSmith templates and needed a class to represent a property that could be hydrated from an XmlNode. And thus I began…

private XmlNode _propNode; 

public string Name 

{ 

    get 

    { 

        string attName = "name"; 

        //check the attribute exists 

        if (_propNode.Attributes[attName] != null) 

            //it does so return it 

            return _propNode.Attributes[attName].Value; 

        //it doesn't so return an empty string 

        return string.Empty; 

    } 

}

After the first few properties I realised I needed to refactor the XmlNode reading out as I was going to have about 20 properties that did the same thing. The problem was that the Value property of the Attribute returns a string so I was going to have to do some type conversion and so would need a method for each type string, int and bool that I needed. I seemed to recall reading about Generic methods and so I investigated… As it turns out I ended up wrapping this method with a method for each type anyway but I discovered Generic methods along the way which I’d not taken advantage of before.

public void GetAttributeValue<T>(ref T attValue, 

    XmlNode nodeToParse, string attName) 

{ 

    //check the attribute exists 

    if(nodeToParse.Attributes[attName] != null) 

    { 

        //get the string value 

        string strVal = nodeToParse.Attributes[attName].Value; 

        //set the attributeValue that has  

        //been passed in by reference, casting it 

        //from an object using the Generic parameter 

        //and using its own type to perform the conversion 

        attValue = (T)Convert.ChangeType(strVal, 

            typeof(attValue)); 

        attValue = (T)Convert.ChangeType(strVal, 

            typeof(T)); 

    } 

}

You can’t specify a Generic return type so you get the value out by passing in an argument by reference. So, you call this method like so:

public bool IsPrimaryKey 

{ 

    get 

    { 

        //set your default value here 

        //that is returned if the attribute 

        //doesn't exist 

        bool returnVal = false; 

        //call the method specifying the type 

        GetAttributeValue<bool>(ref returnVal, 

            _propNode, "isPrimaryKey"); 

        return returnVal; 

    } 

}

This allowed me to use the same method for all of the types of parameter I wanted to fill from the XmlNode’s attributes.

In the end this didn’t save me a great deal of code from doing it without using Generics and I still ended up casting the return value from an object so there would be no performance benefit either (not that performance was an issue here) but it is definitely an interesting language feature that I am sure I will find more uses for…