Telerik blogs

Background

User Interface testing isn’t just for quality engineers. It’s vital for developers to own part of this process as well. The days of development silos are long gone (or at least should be!) The process of throwing bits “down the line” is fraught with inefficiencies.

Developers are already adopting unit testing in record numbers, and this has led to a phenomenal increase in code quality. Why should it stop there? Developers need to also take ownership of the user interface code just like the line of business code that they develop.

Is this to say that we don’t need quality engineers? Absolutely not! What I am saying is that developers should ensure that the basic elements of the user interface are correct, and the process for testing these basic elements need to be automated just like standard unit tests are automated.

Enter the Telerik Testing Framework

Telerik’s Test Studio has an extremely powerful record/replay capability. Did you know that Test Studio’s underlying Testing Framework also provides the ability for developers to write UI tests with most of the common unit testing frameworks? In this post, I am going to show you the basics of writing functional tests with MbUnit and Gallio, leveraging the power of the Telerik Testing Framework.

The System Under Test

For this example, I am going to use a standard ASP.NET MVC application.  The test is simple:

  • Click on the Log On link
  • Assert that the page changes to /Account/Logon
  • Find the User name text box, and enter the text “admin”
  • Find the Password password box, and enter the text “foo”
  • Find the Log On button, and click it
  • Verify that the resulting page contains the text “The user name or password provided is incorrect”

The Home Page

image

The Logon Page

image

The Results

image

Setting the Stage

There is a little bit of housework that needs to be done before this test can be developed. This isn’t much different than what you need to do to create a test project for standard unit tests, there are just a few more steps. You need to create a unit test project, select a unit test framework, add the Telerik Testing Framework references, and finally create a class that derives from the BaseTest abstract class provided by the Telerik Testing Framework.

Selecting a Unit Test Framework

The Telerik Testing Framework works with any .NET unit testing frameworks. I typically use MBUnit/Gallio in conjunction with the Telerik Testing Framework to leverage the Gallio report writer, which I will demonstrate in a future post.

Adding the Test Studio Framework References

There are two references that need to added to the test project.  Right click on the test project, select “Add Reference…”, click “Browse…”, then navigate to “C:\Program Files (x86)\Telerik\Test Studio\Bin\” and select:

  • Telerik.TestingFramework.Interop.dll
  • ArtOfTest.WebAii.dll

Deriving from the Test Studio BaseTest Class

Listing 1 shows the default implementation that is needed to use the Telerik Testing Framework in unit tests. To write tests leveraging the Telerik Testing Framework, this is the minimum code that needs to be implemented in the base class that TestFixtures will inherit.

public class WebAiiUITestsBase : BaseTest
{
 /// <summary> 
 /// Initialization for each test. 
 /// </summary> 
    [SetUp]
 public void MyTestInitialize()
    {
 // Initializes WebAii manager to be used by the test case. 
 // If a WebAii configuration section exists, settings will be 
 // loaded from it. Otherwise, will create a default settings 
 // object with system defaults. 
 // Pass in 'true' to recycle the browser between test methods 
        Initialize(false);
 // If you need to override any other settings coming from the 
 // config section or you don't have a config section, you can 
 // comment the 'Initialize' line above and instead use the 
 // following: 
 /*

        // This will get a new Settings object. If a configuration
        // section exists, then settings from that section will be
        // loaded
        Settings settings = GetSettings();
        // Override the settings you want. For example:
        settings.DefaultBrowser = BrowserType.FireFox;
        // Now call Initialize again with your updated settings object
        Initialize(settings);
        */
 
 // 
 // Place any additional initialization here 
 // 
    }

 /// <summary> 
 /// Clean up after each test. 
 /// </summary> 
    [TearDown]
 public void MyTestCleanUp()
    {
 // 
 // Place any additional cleanup here 
 // 
 // Shuts down WebAii manager and closes all browsers currently running 
 // after each test. This call is ignored if recycleBrowser is set 
 this.CleanUp();
    }

 /// <summary> 
 /// Called after all tests in this class are executed. 
 /// </summary> 
    [FixtureTearDown]
 public void FixtureCleanup()
    {
 // This will shut down all browsers if 
 // recycleBrowser is turned on. Else 
 // will do nothing. 
        ShutDown();
    }
}

Listing 1 – The base class for Test Fixtures

Creating your first Unit Test

Start by creating a standard Test Fixture, with two distinctive changes:

  • The fixtures must be set to Single Threaded (due to limitations in how browsers and the Windows User Interface work)
  • The fixtures must derive from our base class (created above)

Once those two changes are completed, unit tests can be added in the standard manner, as shown in Listing 2. 

[TestFixture, ApartmentState(ApartmentState.STA)]
public class LoginUITests : WebAiiUITestsBase
{
    [Test]
 public void Should_Fail_Log_In_With_Bad_Username_Or_Password()
    {
    }
}
Listing 2 – Modified Test Fixture and Single Unit Test

Starting the Browser

The first step in testing a web application is launching a browser. The Telerik Testing Framework supports a number of browsers (assuming they are installed on the system running the unit test), as shown in Figure 1.

image
Figure 1 – The Browser choices

Navigating

Once the browser is launched through the manager, the browser instance gets assigned to the ActiveBrowser property of the BaseTest class. The ActiveBrowser exposes quite a few properties and methods, and I am only going to scratch the surface in this post.

The first thing I need to do is to navigate to the website I am testing. In my particular scenario, the url is “http://localhost:3916/”. Since all of my tests will start with this address, I add a property to my base class, as in Listing 3.

protected string _coreUrl = "http://localhost:3916/";

Listing 3 – Home Page for the site under test

My test now looks like Listing 4, which is how each of my tests begin.

[Test]
public void Should_Fail_Log_In_With_Bad_Username_Or_Password()
{
    Manager.LaunchNewBrowser(BrowserType.InternetExplorer);
    ActiveBrowser.NavigateTo(_coreUrl);
}

Listing 4 – Creating the Browser and Navigating to the Start Page

You might be wondering why I don’t move those two lines into a TestSetup method.  While the full answer is too long and off topic for this post, I feel that TestSetup methods obfuscate the tests and become a problem leading to fragile tests. 

Finding Elements on the Page

The Telerik Testing Framework supplies an extremely robust mechanism for finding elements on a page. The methods are generic, which enables Test Studio to return strongly typed elements. For example, the first item that I need to find is the HTML Anchor that has the inner text “Log On”. If the element is found, the Find process will return an HTMLAnchor class that exposes (among other elements) a Click() method. The next step is to verify that the logon page is loaded, and I use the ActiveBrowser.Url to assert that condition. This is shown in Listing 5.

Find.ByContent<HtmlAnchor>("Log On", 
      FindContentType.InnerText).Click();
Assert.AreEqual(_coreUrl + "Account/LogOn", 
      ActiveBrowser.Url);
Listing 5 – Clicking an HTMLAnchor and validating the result

The next steps are to find the text box and the password text boxes, and enter the user name and password as defined in the spec. For these, we will FindByName instead of FindByContent, since we know the form values are named. With the strong typing of the Find methods, we can then set the Text property for each of the controls. The last step is to submit the entered values by finding the HTMLInputSubmit button. This code is shown in Listing 6.

Find.ByName<HtmlInputText>("Username").Text = "admin";
Find.ByName<HtmlInputPassword>("Password").Text = "foo";
Find.ByAttributes<HtmlInputSubmit>("Value=Log On").Click();

Listing 7 – Entering and submitting values

Validating the Result

The final step in our spec is to verify that the web page shows the correct error message, and we again call on the ActiveBrowser object to validate that the page contains the text that we are looking for, as shown in Listing 7.

Assert.IsTrue(ActiveBrowser.ContainsText("The user name or password provided is incorrect"));

Listing 7 – Asserting the Text in the webpage

The completed test is shown in Listing 8

[Test]
public void Should_Fail_Log_In_With_Bad_Username_Or_Password()
{
    Manager.LaunchNewBrowser(BrowserType.InternetExplorer);
    ActiveBrowser.NavigateTo(_coreUrl);
    Find.ByContent<HtmlAnchor>("Log On", FindContentType.InnerText).Click();
    Assert.AreEqual(_coreUrl + "Account/LogOn", ActiveBrowser.Url);
    Find.ByName<HtmlInputText>("Username").Text = "admin";
    Find.ByName<HtmlInputPassword>("Password").Text = "foo";
    Find.ByAttributes<HtmlInputSubmit>("Value=Log On").Click();
    Assert.IsTrue(ActiveBrowser.ContainsText("The user name or password provided is incorrect"));
}

Listing 8 – The completed test

Summary

This post merely scratched the surface of what the Test Studio Framework provides to developers. Testing really needs to become a way of life for all aspects of software development, not just the quality engineers.  Remember, if you don’t test it, your users will!

Next Steps!

Telerik’s Testing Framework is freely available for download from the product’s home page. You can immediately start writing functional tests for your HTML, Silverlight, or WPF applications!

Why not go give the Telerik Testing Framework a try?

 

Japikse
About the Author

Phil Japikse

is an international speaker, a Microsoft MVP, ASPInsider, INETA Community Champion, MCSD, CSM/ CSP, and a passionate member of the developer community. Phil has been working with .Net since the first betas, developing software for over 20 years, and heavily involved in the agile community since 2005. Phil also hosts the Hallway Conversations podcast (www.hallwayconversations.com) and serves as the Lead Director for the Cincinnati .Net User’s Group (http://www.cinnug.org). You can follow Phil on twitter via www.twitter.com/skimedic, or read his personal blog at www.skimedic.com/blog.

 

Related Posts

Comments

Comments are disabled in preview mode.