Archive for the 'Unit Testing' 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; 
            output = p.StandardOutput.ReadToEnd(); 
        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); 
            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:

public class UITest 
    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…