Roslyn + Selenium: Scripty C# Powering Browser Automation
24 July, 2013Selenium makes black box style integration testing really easy. Current perception is that UI testing is brittle and generally a maintenance concern. There is an implicit cost of writing/updating, compiling, and deploying c# scripted web UI test code. However, the Roslyn project can be leveraged to stream line this process.
As amazing as it sounds, the Roslyn project establishes the compiler as an API. I had originally heard about it on herding code 146 and immediately thought about how it could improve an existing Selenium based testing utility I had created. The fork resulted in CSharpWebScripter. For the purpose of this post the fork serves two purposes:
- A basic demonstration on how an application can leverage the Roslyn API to compile, execute, and interact with arbitrary .csx files.
- A simple automatable mechanism for authoring and evaluating compiler-free C# functional web tests.
File drop deploy
The code below is C# in a .csx file, drop it in a directory, when the exe is invoked, Selenium executes the web driver code in FireFox. When its time to add another test, drop another file, and both get executed on the next exe invocation. Maintenance against UI updates, functional changes, and bugs in test code, become a script edit and file drop.
Making .csx feel scripty
One goal here is to leverage existing C# language constructs, such that coding .csx feels light weight and expressive. I think this has been a goal in the evolution of C# and anticipate an emergent style around .csx coding. Here, I move as much Selenium web driver boilerplate (which isn't much) into the WebInteraction class definition. The delegate pattern is leveraged such that the bulk of the .csx script file is expressed in a lambda. Also, to futher reduce keystrokes, the class implements a fluent style method signature.
A simple interaction with Roslyn
With the Roslyn API a compiler and runtime can be instantiated, complete with any references required. In order to keep the .csx lighter, a few calls to ImportNamespace are made. The Execute method returns an instance of WebInteractionResult, this object is called a host object and servers as a container to transfer any data we want out of the executed .csx, and into the compiling app.
Automating, reporting, and wrapping up
The source also includes an NUnit test project. It leverages NUnit's TestCaseSource feature that enables n number of .csx files to be reported on as if they were a compiled test. It works well enough, however after implementing it, I am curious to see how other testing frameworks go about it.
In conclusion, by combining Selenium, Roslyn, and NUnit, we have a simple automatable mechanism for authoring and evaluating compiler-free C# functional web tests.