Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Xenon

0.00/5 (No votes)
6 Nov 2014 1  
Xenon is a framework which helps you to write stable acceptance tests

Introduction

Xenon is a framework which helps to write stable (non flakey) acceptance tests with a fluent API. We currently only support Selenium browser automation, but we will implement more if required.

The advantage of using this framework is that you don't have to worry about your page taking time to load, or your elements being dynamically added to the page. All this is handled internally using pre and post waits. These waits do not slow down because as soon as the element appears on the page it will interact with. If you want to wait upon something out of the ordinary, you can do this using custom pre and post waits.

Background

We wrote this framework as there was one issue that kept annoying us on our build server. Our tests passed and failed whenever they felt like it. We would spend ages trying to fixing the tests only to find a few days later they were failing again.

We then came up with Xenon to make our tests consistently pass with great success. Now all our tests pass all the time (unless we broke something) and we hope that it can do the same for you.

Using the Code

Setting up Xenon

Installing

You can either download the source code from our GitHub repo here and compile it yourself. You also install it from nuget:

As currently selenium is the only supported browser automation framework, we recommend that you use Xenon.Selenium as Xenon only contains the core code and would require you to manually implement the browser automation side.

Configuring

To use selenium, you must setup a couple of things (only needs to be done once):

Setting up the options
XenonTestOptions.Options = new XenonTestOptions
{
    //This is required as we did no make Xenon framework depend on any particular test framework
    //So you have to specify you test frameworks assert method
    Assert.Method = (passed, message) => Assert.IsTrue(passed, message),

    //This is optional and specifies how many seconds Xenon should wait for something to happen
    //By default this is 5
    WaitForSeconds = 10
}

Testing

Writing a Test (Basic)

To write a simple but reliable test is easy using our fluent API. As demonstrated below (we will use selenium in this example and search for something on Google):

void TestMethod(){
    //This setups the browser so that it can be used in the test
    var browser = new SeleniumXenonBrowser( new ChromeDriver() );
    new XenonTest( browser )
        .GoToUrl( "http://www.google.co.uk" )
        .EnterText( "[name='q']", "Xenon is amazing" )
        .Click( "[name='btnG']" )
        .Assert( a => a.PageContains( "results") );
}

This test will now reliably pass even if going to the results page takes a while as Xenon will give the browser a chance to go to that page before failing.

Writing this test is fine for simple tests but when tests get more complicated, we created Screens which are explained below.

Writing a test (Using Screens)

To write more complex tests, you can use screens. These allow you to reuse common code throughout all of your tests. To create a screen, you write a class that inherits from XenonScreen as demonstrated below:

public class GoogleHomeScreen : XenonScreen<GoogleHomeScreen>{
    public GoogleHomeScreen( IXenonBrowser browser ) : base( browser ){
        GoToUrl( "http://www.google.co.uk" );
    }

    public GoogleSearchResultsScreen Search( string text ){
        return EnterText( "input[name='q']" )
            .Click( "[name='btnK']" )
            .Switch<GoogleSearchResultsScreen>();
    }
}

public class GoogleSearchResultsScreen : XenonScreen<GoogleSearchResultsScreen>{
    public GoogleSearchResultsScreen( IXenonBrowser browser ) : base( browser ){}
} 

You can the write your test as follows:

void TestMethod(){
    new GoogleHomeScreen( new SeleniumXenonBrowser( new ChromeDriver() )
        .Search( "Xenon is the best" )
        .Assert( a => a.PageContains( "results" ) );
}

Using Assertion API

The assertion API is one of the core parts of Xenon it can be used in multiple places throughout the framework. It allows you to assert on multiple things using fluent syntax. When ever this is used Xenon always gives your Assert method time to pass in case the browser is taking its time for some reason.

It can be for a customPreWait and customPostWait in all XenonTest/XenonScreen methods which makes it extremely usefull if say clicking a button should wait for a Ajax call to complete and output data to the page before continuing.  

new XenonTest( //browser )
    .Click( "#loadData", customPostWait: a => a.PageContains( "Data Loaded" ) );

It can also be using in the Assert method of Xenon test method to make sure the current page state matches what is expected. A big advantage of the Assert method is that it can be used at multiple points throught your test, so that you can make sure that it is progressing as expected.

new XenonTest( //browser )
    .GoToUrl( "http://www.google.co.uk" )
    .Assert( a => a.PageContains( "Google" ) )
    .EnterText( "[name='q']", "Xenon is amazing" )
    .Click( "[name='btnG']" )
    .Assert( a => a.PageContains( "results") );

If the assertion api does not contain the type of assertion you are looking for all is not lost. As there is a CustomAssertion method which allow you write your own assertion using the browser directly. Using this does not affect the reliabilty of your test.

Assert( a => a.CustomAssertion( b => b.Url == "www.google.co.uk", "Custom message on failure" ) );

Notes

If you would like to view our source code, you can access it at our GitHub repo here.

If you have any recommendations or questions, please leave a comment below or an issue on GitHub.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here