How To: Get same test running under different environments


A while back, I got following question from a user of Coded UI Test 

We want to run the same test across multiple environments to ensure everything is still working correctly.

Dev-> Test -> UAT -> STAGE

We want to run these tests after each deploy to each environment. Each environment has as a different URL, username and password.

How can I achieve this without changing the recording or code everytime?

Well, there are number of different ways to achieve this.  One is to use environment variables to parameterize the playback code.  Let us take an example – my test is to login to Hotmail. Here I want to parameterize 3 variables – the Hotmail server, the username and the password.  I can do so by adding something like the code below to UIMap.cs file.

public UIMap()
{
    // Bind the parameters using Environment Variables.
    string testServer =
        Environment.GetEnvironmentVariable("TestServer");
    string testUserName =
        Environment.GetEnvironmentVariable("TestUserName");
    string testUserPassword =
        Environment.GetEnvironmentVariable("TestUserPassword");

    if (!string.IsNullOrEmpty(testServer))
    {
        // Change only the server name part of the URL as
        // rest is independent of the environment.
        UriBuilder urlBuilder =
            new UriBuilder(this.LoginToHotmailParams.Url);
        urlBuilder.Host = testServer;
        this.LoginToHotmailParams.Url = urlBuilder.Uri.ToString();
    }

    if (!string.IsNullOrEmpty(testUserName))
    {
        this.LoginToHotmailParams.UIWindowsLiveIDEditText =
            testUserName;
    }

    if (!string.IsNullOrEmpty(testUserPassword))
    {
        // Password is always encrypted by the recorder.
        // So encrypt the clear text password before setting.
        this.LoginToHotmailParams.UIPasswordEditPassword =
            Playback.EncryptText(testUserPassword);
    }
}

Generally, only the server name part of the URL changes across environments and hence I have used just that to parameterize.

For password, you could have clear text & set it via Playback.EncryptText() API shown above OR, you could have encrypted password and use it directly.  For encryption you can write separate program that gives you encrypted one from clear text using the Playback.EncryptText() API. Note that how secure encrypted password is depends on the key used for encryption.  The encryption key can be set using Playback.PlaybackSettings.SetEncryptionKeyLocation() API.  If you don’t call this API, the default key is used which makes encryption not really unbreakable.  Most users are typically ok with using default encryption key because these are test accounts and “everybody already know the password”.  However, if you really want to ensure that the test account password is protected, use different encryption key that is placed on a network share and the access to the network share is controlled via Windows.

Comments (16)

  1. Raj says:

    What are recommendations on how to handle multiple roles of an application. e.g. In a scenario a User1 is requesting for a leave (here IE will get opened with first user session). Now during playback we need to get IE opened with Manager user to approve his leave request.

    So what are the standards set for automating such flows…

    I would be using Test Agent to play the tests(and agent also runs under one user credential and launches IE also under same user account.

  2. sajeev k says:

    I am unable to find anything like this "this.LoginToHotmailParams.Url" in my coded UI test.

    Can you please explain something more on this one line?

    Regards,

    Sajeev.

  3. gautamg says:

    It may not be the exact same thing.  If you cannot still figure which one, paste your recording and I will take a look at this.

    Thanks.

  4. Richie says:

    Nice work. I'm finally getting the hang of coded ui architecture and how things work. I needed this post. Thanks

  5. Toral says:

    Hi,

    I had a query here. I can use something like this to generate the encrypted password

               String encrypted = Playback.EncryptText("Toral");

    But in any case, I will be exposing my password in the code. Is there a way – I dont use the real password at all.

  6. gautamg says:

    In the above example, password is got from environment variable.  You can similarly read it from some file off a network share.  You can use Windows ACL to control access to that network sharefile.

    Alternatively, you can also change the encryption key used by the Playback for encrypting the text by PlaybackSettings.SetEncryptionKeyLocation() method.  Here again, you can have the key file on a network share and use Windows to control the access to specified users only.

    Thanks.

  7. Ricardo Torres says:

    Hey, great example, this has been very useful for me.

    I have an scenario where I want to use different testing machines using the test controller and agents; and I still want to have a way to tell the agent which target environment to test, just as you did on your example. For example, I have 2 test agents and 10 environments to test, so each test agent can test any of those 10 environments at any time. The test controller decides which agent to use.

    I tried to use environment variables to define the target "TestServer", which work great when I'm running the tests on the same machine, since it has already the target environment variable SET by the build process. But if I run the tests on agent machines, those machines don't have the value set. I haven't found a way to "inject" those environment variables values to the agent machine. As stated above, I might have many test agents running and many environments, so, I need to define the environment to test in the specific agent before the test controller actually run the tests.

    I'm trying now using the setup and cleanup scripts in the testsettings; however, I still can't figure out a way of defining the "target environment" value as variable in those scripts so the test agent machine is configured appropiately before the execution of the test (ie; set the environment variable to the corresponding value)

    Any idea on how to accomplish this will be very really appreciated!

    Thanks!

  8. gautamg says:

    I am not sure I follow you completely.  Please make a detailed post at social.msdn.microsoft.com/…/threads and someone from the team will pick it up.

  9. Victor says:

    Hi I'm looking for testing a locale application with the CUIT.  I got about 5 physical machines, but with different hardware. Some of my test can only be done on specific hardware. So how can i manage that these tests are only sent to the agents running on this machine. If needed, I can set attributes for the agents in the controllers config. Is there a way?

  10. gautamg says:

    Check msdn.microsoft.com/…/ff426235.aspx.  Ignore the fact that it says this is for Load Test.

  11. katta says:

    Hi Gowtham,

    Thanks a lot for the post.

    The post resembles exactly my situation. I tries you rsolution,but its not working for me. i added code in datadriven test for password it is allwoing to enter in textbox ,but not signing in to website. could you help me out in this.

  12. gautamg says:

    Share the code – send mail at gautamg at the rate microsoft dot com.

    Thanks.

  13. Nithya says:

    I have  a csv file called pwd.csv with column name as passwrd. How can I incorporate password encryption on this one?

    Thanks in advance!

  14. gautamg says:

    Check blogs.msdn.com/…/data-driving-coded-ui-tests.aspx and blogs.msdn.com/…/more-on-data-driving-coded-ui-tests.aspx for data driving.  You can use that in conjunction with the above blog to do your work.

    Thanks.

  15. Ranbir says:

    Hi  Gautam,

    I understand what you mentioned above, but i am very new to coded ui.

    Wolud you please help mewith how I can integrate environment variables from environment to coded ui?

    Thanks

  16. gautamg says:

    Sure, give it a try and let me know if you need more help by using the "Send Email" link of this blog.