Building Ranorex Framework with Visual Studio

Vasyl Bakalets on
Test Automation engineer at ELEKS

Being a member of the presale team for the last two years, I dealt with lots of testing projects. The solution that fitted most of them was Ranorex, an out-of-the-box tool for automated functional testing. Still, some projects fell out of scope, making us more creative with testing. When working on a project like this, we decided to develop a custom test automation framework – REWA (abr. Ranorex ELEKS Web Automation), based on the integration of Ranorex Studio with Visual Studio.

Why we Decided to Integrate Ranorex Studio with Visual Studio

  • We had to test the web part of the application. It was developed on Java and the pages contained many frames/iframes of the same type.
    Our integrated approach of building Ranorex framework with Visual Studio let us handle many similar windows loaded independently from the parent window. We were also able to rethink the method to detect the application load conditions.
  • We had to perform more than 10,000 auto tests within a limited period of time. This required 5 test automation engineers working simultaneously.
    The integration of Ranorex Studio with Visual Studio allowed better team cooperation.
  • Due to the complex business logic of the app and a huge number of test cases required, we needed a specific testing environment. And with the app still in development, we were not sure about its stability.
    Our own framework allowed better flexibility of the test case execution process. Thanks to the Ranorex and Visual Studio integration, we had a code review mechanism similar to ReSharper and analogous plug-ins, with means for static code analysis.

Framework Structure

Searching for the solution of the above, we resorted to an alternative Ranorex-powered automation solution integrating its libraries into Microsoft Visual Studio (the integration process is described here). Following the integration, we split the test solution into two parts: the Framework part and the Product-specific part, with intention to use the Framework part for all our projects. The Product-specific part was supposed to be variable depending on the specific project. This approach would allow us to improve our Framework and service simultaneously for all our customers.

Unfortunately, strict NDA with the customer doesn’t allow us to show the production version of the framework. The sample presented here is for demonstration purposes only.

We moved the framework part to the REWA folder and subdivided it into two projects: REWA.Core and REWA.Core.Extensibility.

Building_Ranorex_Framework_Visual_Studio_ELEKSlabs_1

The REWA.Core project contains the test automation framework that consists of several elements.

  • BaseTestSuite, the base class for:
    • all Test Suites defining general Ranorex settings for all Test Cases (e.g., Mouse.DefaultMoveTime, Keyboard.DefaultKeyPressTime or Delay.SpeedFactor);
    • implementing ClassInitialize/ClassCleanup (preconditions for Test Suite) and StartBrowser/KillBrowser methods;
    • configuring reports (by using ReportingHelper);
      Click here to see the code. https://gist.github.com/VasylBakalets/013ccfc3e0a4558f99e6
  • ReportingHelper that implements the configuration of Ranorex Reports;
    Click here to see the code. https://gist.github.com/VasylBakalets/61d608e20fa3a97336b9
  • RanorexExtensions, a repository for extension method used to wait until frame/iframe has finished loading (the code is in the “How it works” paragraph).

The REWA.Core.Extensibility project implements a custom attribute solving the problem of tests fragility.

To make the Product-specific part of our framework as coherent as a test solution, we split it into two projects: Product Components and Product Tests. Product Components contained:

  • all reusable code (e.g. Login(String userName, String password) used in different tests to execute tests steps;
  • all input data we moved to a single storage (the *.settings file);
  • Ranorex product-specific repository created with Ranorex Spy and containing the product controls structure.

The Product Tests project hosted the tests themselves. Each file (e.g., ProductTestSuite1.cs) is the class inherited from BaseTestSuite, with [RewaTestClass] custom attribute and its own TestInitialize and TestCleanup methods for test preconditions. As soon as the tests were developed, they appeared in the MS Test Explorer, and could be run from there.

Although we used our solution for web application testing, the approach can be implemented for desktop solutions as well.

We have described only the basic functions of the framework. If you want to learn more details or you have any suggestions, write them in the comments below or contact us directly social networks.

How it Works

Frames/Iframes

Automating the web page tests, we have to handle the pages that haven’t loaded yet. To wait until the page loads, Ranorex provides a native method WaitForDocumentLoaded() that can be used for pages of WebDocument type stored in the Ranorex repository. This method works perfectly until your page structure includes frames or iframes. Since frames/iframes are loading independently from the whole page, the native method doesn’t work properly. WaitForDocumentLoaded() returns the readyState of the first frame while all other frames might still be loading.

To guarantee that all the frames are loaded, we have implemented an extension method into RanorexExtensions injecting JavaScript code to recursively find all the frames on our page and check their readyState. See the code here.

Dealing with Multiple Copies of the Same Page

With our application under test, we had to deal with lots of identical chat windows. We also needed to launch several copies of the same page for different functional roles of chat users. All these pages launched in different browsers had to be tested within one test case. Moreover, by the moment we had to test the iterative process of send message/receive and reply/switch to another client, we already had the Ranorex repository for these pages.

The only way to avoid remaking the repository for the Ranorex framework integrated with Visual Studio was to add a variable as index in the page’s xpath (but only for DOM and only for pages launched in multiple copies). Thus, the last active copy of a page is assigned the index 1. When we switch to another copy of the page, this copy becomes the last active and gets the index 1 instead of the previous copy, which is automatically assigned the index 2. To implement such behavior, the repository needed an Integer variable, but the only type of Ranorex repository variable is String.

The hack we thought of was to use the Ranorex repository variable created before and change its type to Integer. Ranorex Studio won’t allow such a trick and overwrites the variable type back to String.

string _ReportNameVar = "New report";
 
        /// <summary>
        /// Gets or sets the value of variable ReportNameVar.
        /// </summary>
[TestVariable("8cf5cd96-1d4e-49cb-b6e5-0711155c08f2")]
public string ReportNameVar
{
    get { return _ReportNameVar; }
    set { _ReportNameVar = value; }
}

But we found a solution to handle these issues. Click here to see the code for it.

After an instance of the page is started, the InitializeAgentWindow(AgentWindow type) is being called. It initializes the page with a nominal type (a name to distinguish windows), adds it to Dictionary<int, AgentWindow> agentWindows and assigns this page an index 1 to mark it as the last active window among the similar ones. Then it updates the indices of other windows. The nominal types of windows are stored in AgentWindow enum.

When we need to switch to another window, we use SwitchToAgent(AgentWindow type) method. It returns the index of the window you need to activate. Once the window becomes active, it gets the index 1 and other windows are assigned the indices from 2 and up respectively.

Fragility Issues

To make fragile tests more stable, in the course of Ranorex and Visual Studio integration, we implemented our custom attribute. It was designed for relaunching failed test several times to avoid test execution errors related with external factors (network delays, client OS load, server load, etc). We created our test class attribute RewaTestClassAttribute.cs inherited from MS TestClassExtensionAttribute. Here it is.

The custom TestClass attribute is designed to repeat the test method up to MaxAttempts times in case it fails at first attempt. Also, the MS TestClassInitializeAttribute class cannot be inherited, and BaseTestSuite ClassInitialize/ClassCleanup methods do not run while test execution. So, these methods are invoked explicitly, allowing the derived test classes to have init/cleanup functionality.

Some Cherries on Top

Teamwork. Since we used MS Visual Studio integrated with Ranorex, we received the ultimate support of TFS with awesome check-in/check-out capabilities, merge functionality and other related stuff.

All tests in one place. Our test strategy for this project implied that we should develop functional tests together with API and integration tests. The integration with Visual Studio allowed us to handle all these tests within a single test automation solution.

Conclusion

When you find out that your test automation tasks are a bit more complex than those seamlessly running Ranorex Studio, keep in mind that Ranorex Studio integrates perfectly with Visual Studio, providing more flexibility and extending functional capabilities.

Find out more about our comprehensive expertise in working with Ranorex and delivering effective automated testing solutions.

tags

Comments