Record your Coded UI test methods

This post is the second edition of the Specflow with Coded UI Tests series

Now that we have our feature and scenarios we need to record the actions used in the scenario. In the previous step, Create a Specflow Feature file, I explained that a Scenario would normally contain multiple actions like this one.

The first step contains a sub set of actions. The full set of steps would look something like this

  1. Open the application
  2. Enter the Username and Password for a Standard User and select Login
  3. Go to Tools > Options
  4. Under Users Options select User Profiles
  5. Verify that all fields are read only
  6. Return to main screen and log out

Step 1 and 6 can be executed before and after our test runs to ensure the next test is in the correct state. Step 2 is part of the Given step, 3 and 4 are part of the And step and 5 is part of the Then step. As you can see a Specflow test may contain more than one action. Because of this there are a few things you should consider when recording your

  • Think about how you will maintain your Coded UI Test methods, this will be the part that will most likely change.
  • Think about how you can reuse Specflow steps and Coded UI Test Methods. This can be done by allowing your steps and coded ui test to receive data (Data Driven Tests)

Maintaining your Coded UI Test Methods

There are 2 aspects that i use when structuring my Coded UI Tests that will help in maintaining your tests.

  1. Create multiple UI Maps that contain only the controls and methods that relate to that region. For example you might have a GeneralUIMap, CustomersUIMap and a ShoppingCartUIMap. General will contain only the controls and methods needed for navigating to other regions of your applications like Customers and the Shopping Cart. It will also contain Launch and Shutdown Methods. CustomerUIMap will relate to any action performed within the Customer region and ShoppingCartUIMap will contain all the actions relating to the Shopping Cart region. When you have a large application separating these will help you to maintain your Coded UI Tests. It also follows the recommended way to maintain large applications as detail by Anu in this post and this post.

image

One thing to note though with this method Visual Studio has limited support for managing UIMaps which will hopefully change. Such as (I really hope they make this experience a lot better)

  1. When you create a new Coded UI Test class using the item template all recordings are placed in a file called UIMap.uitest and there is no way to change this. However when linking Coded UI tests to Specflow normally won’t use this method. The alternative is to right click the UIMap and select “Edit with Coded UI Test Builder”. We don’t need to create a Coded UI Test class because the class structure will be different when wiring it up with a Specflow feature.
  2. There is no way to move recorded methods or controls between UIMaps. However naming your UIMaps with logical areas of your application and using the recording by right clicking the UIMap and selecting “Edit with Coded UI Test Builder” will help to limit this issue.
  3. Because Coded UI Test Methods are generated when you build based on the UIMap (which is just an xml file) if you want to manually modify the method you need to move it into the code behind partial class, If the UIMap is called GeneralUIMap.uitest the partial code behind will be called GeneralUIMap.cs where as the generated code will be called GeneralUIMap.Designer.cs. Once the method is moved into the code behind you loose all GUI support that visual studio gives with the UIMapEditor, the method and all its controls just won’t show in the UI Map Editor and this means you need to maintain it in the code behind class. This isn’t really specific to this method of multiple UI Maps but its something you need to be aware of.
  1. Abstract your UIMaps with a class that resembles your application. This is basically the same code you would see in a Coded UI Test for the UIMap property. It simply instantiates the UIMap and gives you one way to access your UIMaps. This will make writing Specflow steps containing Coded UI Test Methods easier to read and write Using the structure above i would create the following class. In this example the sample application would be called “Shopper”
    image

        ///
    <summary> /// Static class for managing the UIMaps
     /// </summary>
        public static class Shopper
        {
            #region Private Members
            private static GeneralUIMap _general;
            private static CustomerUIMap _customer;
            private static ShoppingCartUIMap _shoppingCart;
            #endregion
    
            ///
    <summary> /// The UI Map used for general navigation to other UI Maps and launching
     /// and closing the application
     /// </summary>
            public static GeneralUIMap General
            {
                get { return _general ?? (_general = new GeneralUIMap()); }
            }
    
            ///
    <summary> /// The UI Map that represents any Customer actions and controls
     /// specific to Customers
     /// </summary>
            public static CustomerUIMap Customer
            {
                get { return _customer ?? (_customer = new CustomerUIMap()); }
            }
    
            ///
    <summary> /// The UI Map that represents the shopping cart actions and controls
     /// specific to the shopping cart
     /// </summary>
            public static ShoppingCartUIMap ShoppingCart
            {
                get { return _shoppingCart ?? (_shoppingCart = new ShoppingCartUIMap()); }
            }
        }
    

    By doing this we can write our Specflow step like this

        [Binding]
        public class SampleStepDefinitiond
        {
            [Given("I Have Internet Explorer Open")]
            public void GivenIHaveEnteredSomethingIntoTheCalculator()
            {
                Shopper.General.LaunchInternetExplorer();
            }
        }
    

Combining these 2 will enable you to keep maintenance of your Specflow Tests separate from the maintenance of your Coded UI Test methods and controls and will allow you to write readable step definitions. If the method of LanchingInternetExplorer changes simply rerecord that method, this will update any any scenario that it is used  and will not require any changes to the scenario.

Recording our Calculator Coded UI methods

Back to our Calculated sample

There are 3 parts to this

Record the basic actions such as Enter a number, Press the Add button and Press the Equals Button

  1. Record the action of typing a value into the calculator using the Coded UI Test Builder
    image
  2. Clean up the Recorded Controls to remove any direct reference to the value you entered, we are only interested in the action if inputting data.
    image

Create a static class that will manage our UI Maps
image

namespace SpecflowAndCodedUI.UI.UIMapLoader
{
    public static class Calculator
    {
        public static ScientificUIMap Scientific
        {
            get { return _scientific ?? (_scientific = new ScientificUIMap()); }
        }

        private static ScientificUIMap _scientific;

        public static StandardUIMap Standard
        {
            get { return _standard ?? (_standard = new StandardUIMap()); }
        }

        private static StandardUIMap _standard;
    }
}

Modifying the Method to allow it to be data driven.

There are two methods to pass data to our CodedUI Test method, The first is to move the code into the code behind so you can edit it manually which is shown below, the second is to leave the method in the UIMap and use the methods Params properties. A sample of the second method can be seen in the Assert of  specflow test in the next episode, Wire up Specflow with Coded UI Test methods

  1. Right click the recorded method in the Coded UI Test Editor and select Move Code. This will move the code into the code behind file, in this case called StandardUIMap.cs, which allows us to edit the method and allow it to be data driven (As mentioned above the alternative is to use the Params property to pass the value to the method. This works even if you  do not move the code into the code behind)
    image
  2. The result is a little messy as it copies the generated coded into the code behind giving you a Params class, Property  and private memeber that resembles the input data. This is how Coded UI Tests are generated, because we will be passing the data to the Method from our specflow step we can clean this up to simply contain the TypeAValue method, this contains the action of typing a value into the calculator. Delete the TypeAValueParams class, TypeAValueParams property and the mTypeAValueParams private member. The result should look like this
    image
  3. Modify the method to accept a string and to use that string in the place of the parameter

Before

        public void TypeAValue()
        {
            #region Variable Declarations

            WinTitleBar uICalculatorTitleBar = this.UICalculatorWindow.UICalculatorTitleBar;
            WinText inputLableValue = this.UICalculatorWindow.InputLabel.InputLableValue;

            #endregion Variable Declarations

            // Click 'Calculator' title bar
            Mouse.Click(uICalculatorTitleBar, new Point(73, 5));

            // Type 'A Value' in 'Input' label
            Keyboard.SendKeys(inputLableValue, this.TypeAValueParams.InputLableValueSendKeys, ModifierKeys.None);
        }

After

        public void TypeAValue(string inputValue)
        {
            #region Variable Declarations

            WinTitleBar uICalculatorTitleBar = this.UICalculatorWindow.UICalculatorTitleBar;
            WinText inputLableValue = this.UICalculatorWindow.InputLabel.InputLableValue;

            #endregion Variable Declarations

            // Click 'Calculator' title bar
            Mouse.Click(uICalculatorTitleBar, new Point(73, 5));

            // Type A Value in to 'Input' label
            Keyboard.SendKeys(inputLableValue, inputValue, ModifierKeys.None);
        }

The this.TypeAValueParams.InputLabelValueSendKeys was just a string that was used as the input data. Instead the method now accepts a string and uses that string in its place.

Advertisements
  1. BDD UI Automation with Specflow and Coded UI Tests « Ryan Burnham's Blog
  2. Wire up the Specflow step definitions with a Coded UI test methods « Ryan Burnham's Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: