Coded UI Testing HOL
Coded UI Testing HOL
Hands-On-Lab (HOL)
Wednesday, July 18, 2012 Visual Studio ALM Rangers Casey OMara, Richard Albrecht, Tim Star, Richard Fennell, Christofer Lf Microsoft Corporation
Visual Studio ALM Rangers This content was created by the Visual Studio ALM Rangers, a special group with members from the Visual Studio Product Team, Microsoft Services, Microsoft Most Valued Professionals (MVPs) and Visual Studio Community Leads.
Page 2
Page 4
Table of Tables
Table 1 - Hands-On-Lab Software Requirements .............................................................................................................................. 8 Table 2 - Suggested focus and time map .......................................................................................................................................... 9
Page 7
Coded UI Tests, which we released in Visual Studio 2010, has seen a lot of adoption. It provided a very effective and powerful model for functional UI Testing. It gives a lot of flexibility to the user for building her test projects. As the complexity of applications that are being tested increases, it becomes more and more important to follow a structured approach to building Coded UI Tests. Users have been asking for guidance on how to structure their Coded UI Tests so that it can scale to large projects and teams. The Visual Studio ALM Rangers are a group of people who have a lot of experience in building real-life Coded UI Tests for large projects. They have come together to build a detailed guidance document for building Coded UI Tests. This hands-on-lab provides a very useful companion for the Coded UI Test guidance. It walks through two scenarios which will help the practitioner in understanding the steps required to build Maintainable Coded UI Tests and update them when the UI changes.
Mathew Aniyan (Senior Program Manager, Visual Studio ALM)
Prerequisites
To complete the basic and advanced hands-on-lab walk-through scenarios you need the following environment: or A single server (physical or virtual) environment that has the following software installed and configured: Software Operating System IIS SQL Server Visual Studio 2012 Team Foundation Server 2012 Version Windows Server 2008 R2 IIS7 SQL Server 2008 R2 2012 2012 Shipped as part of operating system. Enterprise edition recommended. Note Visual Studio 2012 Release Candidate Virtual Image http://blogs.msdn.com/b/briankel/archive/2011/09/16/visualstudio-11-application-lifecycle-management-virtual-machine-and-hands-on-labs-demo-scripts.aspx
Topic Exercise #1a or #1b: Step 1 Context Step 2 Start Visual Studio Step 3 Adding UI Maps and Recording Navigation Step 4 Adding Validations Step 5 Building Test Cases Step 6 Making our tests robust Total Exercise #1
Duration in minutes
Page
10 10 25 10 10 25 90
Exercise #2: Step 1 Context Step 2 Create Project Step 3 Add Test Case Step 4 Verify UI Map Step 5 Update UI Map Total Exercise #2 5 10 10 5 5 35 82 82 85 95 97
Exercise #3 Step 1 Context Step 2 Create Project Step 3 Create the Test Steps Step 4 Checking the Test Works Step 5 Breaking the Test Step 6 Enabling the HTML Logger Step 6 Fixing the Test Total Exercise #3 TOTAL 160 5 5 5 5 5 5 5 35 100 100 101 103 104 105 107
Table 2 - Suggested focus and time map We wish you a pleasant and interesting journey! Copyright 2012 Microsoft Corporation Page 9
Page 10
Page 11
Page 12
Page 13
Figure 5 - Microsoft Visual Studio 2012 in Programs Menu 2. If this is the first time launching Visual Studio for this user, you will be prompted to Choose Environment Settings. Choose the settings that are most appropriate to the kind of development that you do and click the Start Visual Studio button. You will see the following environment once Visual Studio has initialized successfully:
3.
Page 14
Figure 6 - Microsoft Visual Studio 2012 Startup Environment 4. 5. 6. Take the opportunity to explore the Getting Started, Guidance and Resources, and Latest News tabs. Create a new project. Select the Blank Solution template from The Other Project Types, Visual Studio Solutions, name the solution FabrikamFiber.Web.Tests and place it in the <HOL_PATH> directory:
Page 15
Figure 7 - Installed Templates 7. Select the solution in Solution Explorer, right-click and Choose File, Add, New Project.
Figure 8 - Add New Project Menu 8. Choose Coded UI Test Project from Visual C#\Test Projects and name the new project FabrikamFiber.Web.Tests.CUITests:
Page 16
Figure 9 - Installed Test Templates 9. Click Cancel when prompted and the resulting projects should look as follows:
Figure 10 - Solution Explorer 10. Right click on the FabrikamFiber.Web.Tests.CUITests project and select Add, New Folder. 11. Name The new folder UIMaps 12. Repeat the process and add a folder named Utility Copyright 2012 Microsoft Corporation Page 17
REVIEW We have started Visual Studio, selected the appropriate profile if needed, explored the new home page, and created a new test project with a couple folders.
Page 18
What we want to do now is to record the UI actions for several different pages in the Fabrikam website. We are going to make a separate map for each page of the site.
This is the test case we are going to exercise: Navigate to the Fabrikam Intranet site. Add a new Ticket Validate the ticket is added correctly Delete The Ticket
1.
Add a new UI Map Right click on the UI Maps folder and select Add, New Item.
Figure 12 - Add New Item 2. From the resulting dialog, select Coded UI Test Map, change the name to something meaningful like DashboardUIMap and click the Add button.
Page 19
NOTE The Coded UI Test Builder is launched and displayed in the lower right hand corner of your screen.
Page 20
ALERT | WARNING It is important to type the URL into the Internet Explorer address bar rather than using a shortcut or copy and paste. When the test is executed on a different machine, the shortcuts may not exist.
7.
Click the Generate Code button and add a method name as LaunchBrowserAndNavToFabrikamDashboard, then click Add and Generate. Best practice is to add a comment for each generated method, this step will be omitted in future steps for brevity.
Figure 15 - Generate Method With Comment 8. Next click record again and click on the Create New button.
Figure 16 - Create New Ticket 9. Click the Generate Code button on the Coded UI Test Builder and enter CreateNewTicket then click Add and Generate. Page 21
NOTE Next we will generate the UI map for our Create Test Ticket page. The key here is that we do not want or need to launch internet explorer again, we want to resume at the spot where we left off. If you already closed the browser, before recording we will open IE -> navigate to the Fabrikam Site, and click the create new button.
10. Because this is a different page and we want to interact with it independent of the other pages, we are going to create a new UI Map. Close the Coded UI builder if it is open then to create the UI Map, right click on the UI Maps folder and select Add, New Item 11. From the resulting dialog, select Coded UI Test Map, change the name to something meaningful like CreateTicketUIMap.uitest and click the Add button. 12. Again, the Coded UI builder is launched. Click the record button ->Fill in the ticket details as seen in Figure 18, click Create, then click generate code In the Coded UI Test Builder.
Page 22
Figure 18 - New Sample Ticket 13. Enter CreateSampleTicket and click Add and Generate.
Page 23
Figure 19 - Generate New Sample Ticket Method 14. Close the coded UI Builder. 15. That brings us to the next page which we will call the Ticket Details page. On this page we are interested only validating the contents of the ticket and returning to the dashboard. Again go to solution explorer in visual studio, right click on the UI Maps folder and select Add, New Item 16. From the resulting dialog, select Coded UI Test Map, change the name to something meaningful like TicketDetailUIMap.uitest and click the Add button. Again, the Coded UI Test builder is launched. 17. Click the record button -> Click the Back to list link.
Page 24
Figure 20 - Return to List 18. Click the Generate Code Button and type in the name ReturnToList -> click Add and Generate.
Page 25
Figure 21 - Generate Return to List Method 19. Close the Coded UI test builder. 20. There is two more clean-up step we want to record. First we are going to delete the new ticket from the Tickets page. This is a new page so we are going to add another UI Map. 21. Again go to solution explorer in visual studio, right click on the UI Maps folder and select Add, New Item 22. From the resulting dialog, select Coded UI Test Map, change the name to something meaningful like TicketsUIMap.uitest and click the Add button. Again, the Coded UI Test builder is launched. 23. Click the record button -> Click the ticket ref link corresponding to the Ticket we just added.
Figure 22 - Service Ticket Ref Link 24. Click Generate Code -> Enter OpenTicket for the name -> Click Add and Generate. Copyright 2012 Microsoft Corporation Page 26
Figure 23 - Generate Open Ticket code 25. Close the CodedUI Test Builder. 26. Right Click on the TicketDetailUIMap and select Edit With Coded UI Test Builder. Press Record and click the delete Link. Click the Generate code button and Name the method NavigateToDeletePage.
Figure 24 - Generate Delete Navigation 27. Close the CodedUI Test Builder. 28. Finally add one more UI Map called DeleteUIMap.uitest. Press Record and click the Delete Button. Click Generate Code and enter the following:
Page 27
Figure 25 - Generate Delete Ticket ALERT | WARNING The final thing we want to do with our UI Maps is to close the Browser. This is important as eventually these tests should be automated and run as part of a build. During the test run we dont want to have multiple browsers open 1) because eventually we will run out of memory and 2) this can really mess up our tests depending on how the site manages session.
29. Close the CodedUI Test Builder. 30. We are going to close the browser from the Dashboard window. In Solution Explorer, highlight the DashboardUIMap.UITest, right-click, select Edit With Coded UI Test Builder. The recorder is launched.
Page 28
Figure 26 - Edit Existing UI Map 31. Press Record 32. Close The Browser Window 33. Click Generate Code -> Enter CloseBrowser for the name -> Click Add and Generate. REVIEW We have broken down our site under test into several pages. We have added a Coded UI Map for each page, and we have recorded some navigation steps.
Now that we have completed recording our navigation steps, we want to start validating the contents of the pages.
1. Before beginning we want to have a sample ticket ready for validation. If the sample ticket from the previous step does not exist, repeat sub-steps 1 12 of step 3 to create a sample ticket and leave the browser open to the details page. We will be validating the contents of the fields outlined in red as in Figure 27.
Page 29
Figure 27 - Details page validation. 2. To begin adding our validations we want to modify the TicketDetailUIMap. To launch the coded UI Test Builder, right click on TicketDetailUIMap.uitest and select Edit With Coded UI Test Builder The first thing we want to do is validate the Title value. Drag the crosshair control on the Coded UI Test Builder onto the web page until the ticket area is highlighted in blue, then release the left mouse button.
3.
Page 30
Figure 28 - Adding an assertion 4. This is a lot more HTML than we want to validate so we are going to use the arrowed control selector at the top of the assertion dialog to help us get more granular.
Figure 29 Add Assertions Dialog 5. This control selector will help us move through the control tree when simply dragging and dropping the cross hairs is not granular enough. Clicking the up arrow (or typing Alt +up arrow) will bring us to the highlighted controls parent. Similarly, clicking the down arrow (or typing Alt +down arrow) will bring us to the highlighted controls child, clicking the left arrow (or typing Alt +left arrow) will bring us to the highlighted controls previous sibling, and clicking the right arrow (or typing Alt +right arrow) will bring us to the highlighted controls next sibling. To go from highlighting the ticket area to just the title field we need to start with the ticket area highlighted, then click the down arrow once, then the right arrow 3 times.
6.
Page 31
Figure 30 Validate Ticket Title 7. In the add Assertion dialog, scroll down until the Inner Text property is visible. Highlight the Inner Text row and click the Add Assertion button
Figure 31 - Defining Assertion 8. Populate the Add Assertion dialog as follows and click OK.
Page 32
Figure 32 - Add Assertion Details 9. Click the Generate Code button, fill out the dialog as follows and click Add and Generate.
Figure 33 - Generate Assertion Code Details 10. Repeat steps 3 through 6 (using an increasing number of down arrow clicks in the control selector)for the Escalation level, Description, and Created By values naming the assertions AssertEscalationLevel, AssertDescription, and AssertCreatedBy respectively. Take care to be on the Inner Text property when you add the assertion and for now we are going to leave the Comparison Value field at the default value.
Page 33
Figure 34 - Details REVIEW We have learned how to add Assertions or validations to our tests. Assertions are used to inspect the values of control properties as a part of the Coded UI Test.
Figure 35 - Rename Coded UI Test Class 2. 3. Best practice dictates we rename CodedUITest1.cs to something meaningful, enter the name FabrikamFiberTests.cs (It is important to keep the .cs extension and click yes when prompted). Add the following usings to the top of the cs file so that we can access our UI Maps.
FabrikamFiber.Web.Tests.CUITests.UIMaps.CreateTicketUIMapClasses; FabrikamFiber.Web.Tests.CUITests.UIMaps.DashboardUIMapClasses; FabrikamFiber.Web.Tests.CUITests.UIMaps.DeleteUIMapClasses; FabrikamFiber.Web.Tests.CUITests.UIMaps.TicketDetailUIMapClasses; FabrikamFiber.Web.Tests.CUITests.UIMaps.TicketsUIMapClasses;
4. 5.
Change the generated test method from CodedUITestMethod1 to CreateNewTicket Type the following code
[TestMethod] public void CreateNewTicket() { DashboardUIMap dashboardPage= new DashboardUIMap(); CreateTicketUIMap createTicketPage = new CreateTicketUIMap(); TicketDetailUIMap ticketDetailPage = new TicketDetailUIMap(); TicketsUIMap ticketsListPage = new TicketsUIMap(); DeleteUIMap deletePage = new DeleteUIMap(); dashboardPage.LaunchBrowserAndNavToFabrikamDashboard(); dashboardPage.CreateNewTicket(); createTicketPage.CreateSampleTicket(); ticketDetailPage.AssertTicketTitle(); ticketDetailPage.AssertEscalationLevel(); ticketDetailPage.AssertDescription(); ticketDetailPage.AssertCreatedBy(); ticketDetailPage.ReturnToList(); ticketsListPage.OpenTicket(); ticketDetailPage.NavigateToDeletePage(); deletePage.DeleteTicket(); }
6.
Right-click the test method in test explorer and select Debug Selected Tests.
Page 35
Figure 36 Debug Test 7. If we would have started the test with a fresh database, the test would have passed but because we added and deleted a ticket as a part of recording the test, the generated Ticket Reference was not what the generated code expected because the Ticket ID has changed so we should see the following error.
Figure 37 - Expected Error 8. In the next step we will customize our code to make it more robust.
REVIEW We have assembled a test case from our recorded navigations and assertions. We have also seen how brittle the generated code can be.
Page 36
Selecting the correct item from the list. 1. The first thing we will do is modify the UI Map to select the correct link regardless of how the application generates the Link Reference. Open TicketsUIMap.Designer.cs and locate the OpenTicket method. Notice the generated code is telling the execution engine to use the mouse to click a link referred to as UIA014111Hyperlink.
Figure 38 - Hyperlink Click 2. Right click on UIA014111Hyperlink at the end of the declaration line and select Go To Definition
Figure 39 - Finding the search criteria 3. Inspect the Search Criteria section of the code.
Page 37
Figure 40 - Hyperlink Search Criteria 4. The generated code is telling the search engine to find the first control with the inner text of A014111 (The SearchProperties are ANDED together) in a window titled Service Tickets in a control with any of the attributes delineated in the Filter Properties (These items are ORED together). The problem is that depending on how many times we have run the test, the inner text may be different (because the ID is different). We want to modify the generated code so the test can access the ID of the ticket we created. Add the following property to the TicketDetailUIMap.cs
5.
6.
using Microsoft.VisualStudio.TestTools.UITesting.HtmlControls;
7. Modify The Coded UI Test As Follows
[TestMethod] public void CreateNewTicket() { DashboardUIMap dashboardPage= new DashboardUIMap(); CreateTicketUIMap createTicketPage = new CreateTicketUIMap(); TicketDetailUIMap ticketDetailPage = new TicketDetailUIMap(); TicketsUIMap ticketsListPage = new TicketsUIMap(); DeleteUIMap deletePage = new DeleteUIMap(); string newId=string.Empty; dashboardPage.LaunchBrowserAndNavToFabrikamDashboard(); dashboardPage.CreateNewTicket(); createTicketPage.CreateSampleTicket(); //Extract the ticket Id newId = ticketDetailPage.CurrentId; ticketDetailPage.AssertTicketTitle(); ticketDetailPage.AssertEscalationLevel();
Page 38
8.
(Do NOT perform this step) Conceptually we want to modify the search and filter properties for the UIA014111Hyperlink code as follows:
9.
If we do that, we would lose our changes the next time the TicketsUIMap.designer.cs is regenerated so we will go into TicketsUIMap.cs and add the following code to Overload the OpenTicket method and modify the search criteria for the hyperlink we are trying to click.
public void OpenTicket(string ID) {
#region Variable Declarations HtmlHyperlink uIA014111Hyperlink = this.UIServiceTicketsWindowWindow.UIServiceTicketsDocument.UIContentCustom.UIA014111Hyperlink; #endregion //Change the search criteria - Remove the logic we want to change uIA014111Hyperlink.SearchProperties.Remove(HtmlHyperlink.PropertyNames.InnerText); uIA014111Hyperlink.FilterProperties.Remove(HtmlHyperlink.PropertyNames.AbsolutePath); uIA014111Hyperlink.FilterProperties.Remove(HtmlHyperlink.PropertyNames.Href); uIA014111Hyperlink.FilterProperties.Remove(HtmlHyperlink.PropertyNames.TagInstance); //Add it back in with the changes uIA014111Hyperlink.SearchProperties[HtmlHyperlink.PropertyNames.InnerText] = "A0141" + ID; uIA014111Hyperlink.FilterProperties[HtmlHyperlink.PropertyNames.AbsolutePath] = string.Format("/ServiceTickets/Details/{0}", ID); uIA014111Hyperlink.FilterProperties[HtmlHyperlink.PropertyNames.Href] = string.Format("http://localhost:16535/ServiceTickets/Details/{0}", ID); uIA014111Hyperlink.FilterProperties[HtmlHyperlink.PropertyNames.TagInstance] = string.Format("href=\"/ServiceTickets/Details/{0}\"", ID);
Page 39
using Microsoft.VisualStudio.TestTools.UITesting.HtmlControls;
11. We need to add similar logic to parameterize the Delete hyper link. Add the following code to TicketDetailUIMap.cs
public void NavigateToDeletePage(string ID) { #region Variable Declarations HtmlHyperlink uIDeleteHyperlink = this.UIDetailsWindowsInternWindow.UIDetailsDocument.UIContentCustom.UIDeleteHyperlink; #endregion //Change the search criteria - Remove the logic we want to change uIDeleteHyperlink.FilterProperties.Remove(HtmlHyperlink.PropertyNames.AbsolutePath); uIDeleteHyperlink.FilterProperties.Remove(HtmlHyperlink.PropertyNames.Href); //Add it back in with the changes uIDeleteHyperlink.FilterProperties[HtmlHyperlink.PropertyNames.AbsolutePath] = string.Format("/ServiceTickets/Delete/{0}", ID); uIDeleteHyperlink.FilterProperties[HtmlHyperlink.PropertyNames.Href] = string.Format("http://localhost:16535/ServiceTickets/Delete/{0}", ID); // Click 'Delete' link Mouse.Click(uIDeleteHyperlink, new Point(53, 15)); }
12. Rerun the test and the test should now be passing again.
Overriding Assertions 13. All of the Assertions we performed were looking for hard coded values. If we were logged in as someone else, for example, the Created By field would different and therefore our test would fail. To make assertions more robust we want to override all of our assertions. This may be done in the Coded UI Test. For example, the following change will modify the Ticket Title to be A New Ticket
DashboardUIMap dashboardPage= new DashboardUIMap(); CreateTicketUIMap createTicketPage = new CreateTicketUIMap(); TicketDetailUIMap ticketDetailPage = new TicketDetailUIMap(); TicketsUIMap ticketsListPage = new TicketsUIMap(); DeleteUIMap deletePage = new DeleteUIMap(); string newId=string.Empty; dashboardPage.LaunchBrowserAndNavToFabrikamDashboard(); dashboardPage.CreateNewTicket(); createTicketPage.CreateSampleTicketParams.UITitleEditText = "A New Ticket Title"; createTicketPage.CreateSampleTicket(); //Extract the ticket Id newId = ticketDetailPage.CurrentId; ticketDetailPage.AssertTicketTitleExpectedValues.UIItemCustomInnerText= "A New Ticket Title"; ticketDetailPage.AssertTicketTitle(); ticketDetailPage.AssertEscalationLevel(); ticketDetailPage.AssertDescription(); ticketDetailPage.AssertCreatedBy(); ticketDetailPage.ReturnToList(); ticketsListPage.OpenTicket(newId);
Page 40
Data Driven Tests The test case is starting to look much more robust. Now we want to get rid of the hard coded magic strings we are passing in to our methods. We are going to use a CSV file to execute the method multiple times. 14. 15. 16. 17. Right click the FabrikamFiber.Web.Tests.CUITests.csproj project and select Add.., New Folder and name it DataSources. Right click the DataSources Folder and select Add, NewItem In the General tab, select the Text File and name it datasource.csv Enter the following into the new file
Row,Title,ExpectedTitle,EscalationLevel,ExpectedEscalationLevel,ExpectedDescription,ExpectedCreatedBy "1","First Title","First Title","Level 2","Level 2","This is a sample ticket","Drew Robbins" "2","Second Title","Second Title","Level 1","Level 1","This is a sample ticket","Drew Robbins" "3","Third Title","Third Title","Level 3","Level 3","This is a sample ticket","Drew Robbins"
18. Modify the attribute on the test case as follows to add a connection to the data source (no line breaks within a string):
[DeploymentItem("C:\\HOL\\FabrikamFiber.Web.Tests\\FabrikamFiber.Web.Tests.CUITests\\DataSources\\data source.csv"), DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\datasource.csv", "datasource#csv", DataAccessMethod.Sequential), TestMethod]
19. Modify the Coded UI Test to use the Data Source Values rather than the strings for parameters.
[DeploymentItem("C:\\HOL\\FabrikamFiber.Web.Tests\\FabrikamFiber.Web.Tests.CUITests\\DataSources\\data source.csv"), DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\datasource.csv", "datasource#csv", DataAccessMethod.Sequential), TestMethod] public void CreateNewTicket() { DashboardUIMap dashboardPage = new DashboardUIMap(); CreateTicketUIMap createTicketPage = new CreateTicketUIMap(); TicketDetailUIMap ticketDetailPage = new TicketDetailUIMap(); TicketsUIMap ticketsListPage = new TicketsUIMap(); DeleteUIMap deletePage = new DeleteUIMap(); string newId = string.Empty; dashboardPage.LaunchBrowserAndNavToFabrikamDashboard(); dashboardPage.CreateNewTicket(); //Send data source Values in createTicketPage.CreateSampleTicketParams.UITitleEditText = TestContext.DataRow["Title"].ToString(); createTicketPage.CreateSampleTicketParams.UIEscalationLevelComboBoxSelectedItem = TestContext.DataRow["EscalationLevel"].ToString(); createTicketPage.CreateSampleTicket(); //Extract the ticket Id newId = ticketDetailPage.CurrentId; //Set the expected values ticketDetailPage.AssertTicketTitleExpectedValues.UIItemCustomInnerText = TestContext.DataRow["ExpectedTitle"].ToString(); ticketDetailPage.AssertEscalationLevelExpectedValues.UIItemCustom1InnerText = TestContext.DataRow["ExpectedEscalationLevel"].ToString(); ticketDetailPage.AssertDescriptionExpectedValues.UIItemCustom2InnerText = TestContext.DataRow["ExpectedDescription"].ToString(); ticketDetailPage.AssertCreatedByExpectedValues.UIItemCustom3InnerText = TestContext.DataRow["ExpectedCreatedBy"].ToString();
Page 41
20. Retry the test and it should pass without error. Also Notice that the test will execute once per row of data in our Data Source. Ensuring the Application Under Test closes If through the course of this lab you have made any mistakes and the test execution failed you may have noticed that the browser was left open. This can be a big problem in an automated environment as the test agent can run out of memory or in a web application there can be a problem running multiple sessions on the same machine. To combat this we will use good error handling techniques. 21. Wrap your test case in either a try/catch/finally block or a using pattern as the application will always close when the test executes outside of debug mode. 22. Add a little error handling and we are done:
public void CreateNewTicket() { DashboardUIMap dashboardPage = new DashboardUIMap(); CreateTicketUIMap createTicketPage = new CreateTicketUIMap(); TicketDetailUIMap ticketDetailPage = new TicketDetailUIMap(); TicketsUIMap ticketsListPage = new TicketsUIMap(); DeleteUIMap deletePage = new DeleteUIMap(); string newId = string.Empty; try { dashboardPage.LaunchBrowserAndNavToFabrikamDashboard(); dashboardPage.CreateNewTicket(); //Send data source Values in createTicketPage.CreateSampleTicketParams.UITitleEditText = TestContext.DataRow["Title"].ToString(); createTicketPage.CreateSampleTicketParams.UIEscalationLevelComboBoxSelectedItem = TestContext.DataRow["EscalationLevel"].ToString(); createTicketPage.CreateSampleTicket(); //Extract the ticket Id newId = ticketDetailPage.CurrentId; //Set the expected values ticketDetailPage.AssertTicketTitleExpectedValues.UIItemCustomInnerText = TestContext.DataRow["ExpectedTitle"].ToString(); ticketDetailPage.AssertEscalationLevelExpectedValues.UIItemCustom1InnerText = TestContext.DataRow["ExpectedEscalationLevel"].ToString(); ticketDetailPage.AssertDescriptionExpectedValues.UIItemCustom2InnerText = TestContext.DataRow["ExpectedDescription"].ToString(); ticketDetailPage.AssertCreatedByExpectedValues.UIItemCustom3InnerText = TestContext.DataRow["ExpectedCreatedBy"].ToString(); ticketDetailPage.AssertTicketTitle(); ticketDetailPage.AssertEscalationLevel(); ticketDetailPage.AssertDescription(); ticketDetailPage.AssertCreatedBy(); ticketDetailPage.ReturnToList(); ticketsListPage.OpenTicket(newId);
Page 42
}
REVIEW We have added custom code, parameterization, Data Binding, Error Handling and discussed the use of CopyFrom to make our test cases more robust.
Note
As an alternative to using the Try / Catch / Finally block to ensure your browser window closes, you may also use the TestInitialize and TestCleanup attributes as outlined in the next HOL.
Refactor for increased maintainability Just as the code that goes into the product or solution that youre going to ship test code is also code which needs to be refactored and shaped according to recommended patterns and principles in order to ensure re-use, maintainability and readability. Move UI Map initializations to base class The test makes use of five different UI Maps. Theres a good chance that more tests will have similar initialization of UI Ma ps. In order to simplify the re-use and get rid of repetitive code blocks lets move the initialization of the UI Maps to a base class and then derive from it (make sure to add the UI Map using statements to the class as well).
public class FabrikamUITest { Protected DashboardUIMap Protected CreateTicketUIMap Protected TicketDetailUIMap Protected TicketsUIMap Protected DeleteUIMap
= = = = =
public DashboardUIMap DashboardPage { get { return dashboardPage; } } public CreateTicketUIMap CreateTicketPage { get { return createTicketPage; } } public TicketDetailUIMap TicketDetailPage { get { return ticketDetailPage; } } public TicketsUIMap TicketsListPage { get { return ticketsListPage; } } public DeleteUIMap DeletePage { get { return deletePage; } }
Page 43
Parameterize action and assert methods In order to make the test implementation more resilient to change its a good practice to move the assignment of control property values into the action methods. Create new parameterized methods for the CreateSampleTicket and the four assertion methods in their UIMap classes just as we previously did with the OpenTicket method. Then move the assignments of control property values in to the corresponding methods.
public partial class CreateTicketUIMap { public void CreateSampleTicket(string title, string escalationLevel) { CreateSampleTicketParams.UITitleEditText = title; CreateSampleTicketParams.UIEscalationLevelComboBoxSelectedItem = escalationLevel; CreateSampleTicket(); } }
Page 44
End result We should now have a test method thats looking like below. Its more readable and weve moved things to base class for reuse. This should result in a test suite that has a good amount of maintainability.
[DeploymentItem("C:\\HOL\\FabrikamFiber.Web.Tests\\FabrikamFiber.Web.Tests.CUITests\\DataSources\\datasour ce.csv"), DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\datasource.csv", "datasource#csv", DataAccessMethod.Sequential), TestMethod] public void CreateNewTicket() { string newId = string.Empty; try { DashboardPage.LaunchBrowserAndNavToFabrikamDashboard(); DashboardPage.CreateNewTicket(); CreateTicketPage.CreateSampleTicket( title: Bind("Title"), escalationLevel: Bind("EscalationLevel") ); newId = TicketDetailPage.CurrentId; TicketDetailPage.AssertTicketTitle(expected: Bind("ExpectedTitle")); TicketDetailPage.AssertEscalationLevel(expected: Bind("ExpectedEscalationLevel")); TicketDetailPage.AssertDescription(expected: Bind("ExpectedDescription")); TicketDetailPage.AssertCreatedBy(expected: Bind("ExpectedCreatedBy")); TicketDetailPage.ReturnToList(); TicketsListPage.OpenTicket(newId); TicketDetailPage.NavigateToDeletePage(); DeletePage.DeleteTicket(); } finally { DashboardPage.CloseBrowser(); } }
Page 45
Page 46
Page 47
Page 48
Page 49
Figure 46 - Microsoft Visual Studio 2012 in Programs Menu 15. If this is the first time launching Visual Studio for this user, you will be prompted to Choose Environment Settings. Choose the settings that are most appropriate to the kind of development that you do and click the Start Visual Studio button. 16. You will see the following environment once Visual Studio has initialized successfully:
Page 50
Figure 47 - Microsoft Visual Studio 2012 Startup Environment 17. Take the opportunity to explore the Getting Started, Guidance and Resources, and Latest News tabs. 18. Create a new project, as shown in Figure 48 - Create New Project:
Figure 48 - Create New Project 19. Select the Blank Solution template from The Other Project Types, Visual Studio Solutions, name the solution FabrikamFiber.Web.Tests and place it in the <HOL_PATH> directory:
Page 51
Figure 49 - Installed Templates 20. Select the solution in Solution Explorer, right-click and Choose File, Add, New Project.
Figure 50 - Add New Project Menu 21. Choose Coded UI Test Project from Visual C#\Test Projects and name the new project FabrikamFiber.Web.Tests.CUITests:
Page 52
Figure 51 - Installed Test Templates 22. Click Cancel when prompted and the resulting projects should look as follows:
Figure 52 - Solution Explorer 23. 24. 25. 26. Right click on the FabrikamFiber.Web.Tests.CUITests project and select Add, New Folder. Name The new folder UIMaps Repeat the process and add a folder named Utility The resulting projects should look as follows
Page 53
REVIEW We have started Visual Studio, selected the appropriate profile if needed, explored the new home page, and created a new test project with a couple folders.
Page 54
What we want to do now is to record the UI actions for several different pages in the Fabrikam website. We are going to make a separate map for each page of the site.
This is the test case we are going to exercise: Navigate to the Fabrikam Intranet site. Add a new Ticket Validate the ticket is added correctly Delete The Ticket
34. Add a new UI Map Right click on the UI Maps folder and select Add, New Item.
Figure 54 - Add New Item 35. From the resulting dialog, select Coded UI Test Map, change the name to something meaningful like DashboardUIMap and click the Add button.
Page 55
NOTE The Coded UI Test Builder is launched and displayed in the lower right hand corner of your screen.
Page 56
ALERT | WARNING It is important to type the URL into the Internet Explorer address bar rather than using a shortcut or copy and paste. When the test is executed on a different machine, the shortcuts may not exist.
40. Click the Generate Code button and add a method name as LaunchBrowserAndNavToFabrikamDashboard, then click Add and Generate. Best practice is to add a comment for each generated method, this step will be omitted in future steps for brevity.
Figure 57 - Generate Method With Comment 41. Next click record again and click on the Create New button.
Page 57
Figure 58 - Create New Ticket 42. Click the Generate Code button on the Coded UI Test Builder and enter CreateNewTicket then click Add and Generate.
Page 58
43. Because this is a different page and we want to interact with it independent of the other pages, we are going to create a new UI Map. To create the UI Map, right click on the UI Maps folder and select Add, New Item
Figure 60 - Add New Item 44. From the resulting dialog, select Coded UI Test Map, change the name to something meaningful like CreateTicketUIMap.uitest and click the Add button.
Page 59
Figure 61 - Coded UI Test Template 45. Again, the Coded UI builder is launched. Click the record button ->Fill in the ticket details as seen in Figure 62 click Create, then click generate code In the Coded UI Test Builder.
Page 60
Figure 62 - New Sample Ticket 46. Enter CreateSampleTicket and click Add and Generate.
Figure 63 - Generate New Sample Ticket Method 47. Close the coded UI Builder.
Page 61
49. From the resulting dialog, select Coded UI Test Map, change the name to something meaningful like TicketDetailUIMap.uitest and click the Add button. Again, the Coded UI Test builder is launched.
Page 62
Figure 65 - Coded UI Test Template 50. Click the record button -> Click the Back to list link.
Figure 67 - Generate Return to List Method 52. Close the Coded UI test builder. 53. There is two more clean-up step we want to record. First we are going to delete the new ticket from the Tickets page. This is a new page so we are going to add another UI Map. 54. Again go to solution explorer in visual studio, right click on the UI Maps folder and select Add, New Item
55. From the resulting dialog, select Coded UI Test Map, change the name to something meaningful like TicketsUIMap.uitest and click the Add button. Again, the Coded UI Test builder is launched. 56. Click the record button -> Click the ticket ref link corresponding to the Ticket we just added.
Page 64
Figure 69 - Service Ticket Ref Link 57. Click Generate Code -> Enter OpenTicket for the name -> Click Add and Generate.
Figure 70 - Generate Open Ticket code 58. Right Click on the TicketDetailUIMap and select Edit With Coded UI Test Builder. Press Record and click the delete Link. Click the Generate code button and Name the method NavigateToDeletePage.
Figure 71 - Generate Delete Navigation 59. Finally add one more UI Map called DeleteUIMap.uitest. Press Record and click the Delete Button. Click Generate Code and enter the following: Copyright 2012 Microsoft Corporation Page 65
Figure 72 - Generate Delete Ticket ALERT | WARNING The final thing we want to do with our UI Maps is to close the Browser. This is important as eventually these tests should be automated and run as part of a build. During the test run we dont want to have multiple browsers open 1) because eventually we will run out of memory and 2) this can really mess up our tests depending on how the site manages session.
60. We are going to close the browser from the Dashboard window. In Solution Explorer, highlight the DashboardUIMap.UITest, right-click, select Edit With Coded UI Test Builder. The recorder is launched.
Figure 73 - Edit Existing UI Map 61. Press Record 62. Close The Browser Window 63. Click Generate Code -> Enter CloseBrowser for the name -> Click Add and Generate. REVIEW We have broken down our site under test into several pages. We have added a Coded UI Map for each page, and we have recorded some navigation steps. Copyright 2012 Microsoft Corporation Page 66
Now that we have completed recording our navigation steps, we want to start validating the contents of the pages.
11. Before beginning we want to have a sample ticket ready for validation. If the sample ticket from the previous step does not exist, repeat sub-steps 1 12 of step 3 to create a sample ticket and leave the browser open to the details page. We will be validating the contents of the fields outlined in red as in Figure 74.
Figure 74 - Details page validation. 12. To begin adding our validations we want to modify the TicketDetailUIMap. To launch the coded UI Test Builder, right click on TicketDetailUIMap.uitest and select Edit With Coded UI Test Builder
Page 67
Figure 75 - Modify UI Map 13. Drag the crosshair control on the Coded UI Test Builder onto the web page until the title value field is highlighted in blue, then release the left mouse button
Figure 76 - Adding an assertion 14. The add Assertion dialog becomes visible, scroll down until the Display Text property is visible. Highlight the Display Text row and click the Add Assertion button
Page 68
Figure 77 - Defining Assertion 15. Populate the Add Assertion dialog as follows and click OK.
Figure 78 - Add Assertion Details 16. Click the Generate Code button, fill out the dialog as follows and click Add and Generate.
Page 69
Figure 80 - Details REVIEW We have learned how to add Assertions or validations to our tests. Assertions are used to inspect the values of control properties as a part of the Coded UI Test.
Page 70
Figure 81 - Rename Coded UI Test Class 7. 8. Best practice dictates we rename CodedUITest1.cs to something meaningful, enter the name FabrikamFiberTests.cs (It is important to keep the .cs extension and click yes when prompted). Add the following usings to the top of the cs file so that we can access our UI Maps.
FabrikamFiber.Web.Tests.CUITests.UIMaps.CreateTicketUIMapClasses; FabrikamFiber.Web.Tests.CUITests.UIMaps.DashboardUIMapClasses; FabrikamFiber.Web.Tests.CUITests.UIMaps.DeleteUIMapClasses; FabrikamFiber.Web.Tests.CUITests.UIMaps.TicketDetailUIMapClasses; FabrikamFiber.Web.Tests.CUITests.UIMaps.TicketsUIMapClasses;
9. Change the generated test method from CodedUITestMethod1 to CreateNewTicket 10. Type the following code
[TestMethod] public void CreateNewTicket() { DashboardUIMap dashboardPage= new DashboardUIMap(); CreateTicketUIMap createTicketPage = new CreateTicketUIMap(); TicketDetailUIMap ticketDetailPage = new TicketDetailUIMap(); TicketsUIMap ticketsListPage = new TicketsUIMap(); DeleteUIMap deletePage = new DeleteUIMap(); dashboardPage.LaunchBrowserAndNavToFabrikamDashboard(); dashboardPage.CreateNewTicket(); createTicketPage.CreateSampleTicket(); ticketDetailPage.AssertTicketTitle(); ticketDetailPage.AssertEscalationLevel(); ticketDetailPage.AssertDescription(); ticketDetailPage.AssertCreatedBy(); ticketDetailPage.ReturnToList(); ticketsListPage.OpenTicket(); ticketDetailPage.NavigateToDeletePage(); deletePage.DeleteTicket(); }
9.
Press F5 to begin debugging. If we would have started the test with a fresh database, the test would have passed but because we added and deleted a ticket as a part of recording the test, the generated Ticket Reference was not what the generated code expected because the Ticket ID has changed so we should see the following error.
Page 71
Figure 82 - Expected Error 10. In the next step we will customize our code to make it more robust.
REVIEW We have assembled a test case from our recorded navigations and assertions. We have also seen how brittle the generated code can be.
Selecting the correct item from the list. 23. The first thing we will do is modify the UI Map to select the correct link regardless of how the application generates the Link Reference. Open TicketsUIMap.Designer.cs and locate the OpenTicket method. Notice the generated code is telling the execution engine to use the mouse to click a link referred to as UIA014111Hyperlink.
Figure 83 - Hyperlink Click 24. Right click on UIA014111Hyperlink and select Go To Definition
Page 72
Figure 84 - Finding the search criteria 25. Inspect the Search Criteria section of the code.
Figure 85 - Hyperlink Search Criteria 26. The generated code is telling the search engine to find the first control with the inner text of A014111 (The SearchProperties are ANDED together) in a window titled Search Tickets in a control with any of the attributes delineated in the Filter Properties (These items are ORED together). The problem is that depending on how many times we have run the test, the inner text may be different. We want to modify the generated code so the test can access the ID of the ticket we created. 27. Add the following property to the TicketDetailUIMap.cs
public string CurrentId { get { return (((string)((this.UIDetailsWindowsInternWindow.UIDetailsDocument).GetProperty(HtmlDocument.PropertyNames.Pa geUrl))).Split('='))[1]; } }
Page 73
29. Conceptually we want to modify the search and filter properties for the UIA014111Hyperlink code as follows:
Figure 86 - Hyperlink Search and Filter Properties 30. If we do that, we would lose our changes the next time the TicketsUIMap.designer.cs is regenerated so we will go into TicketsUIMap.cs and add the following code to Overload the OpenTicket method and modify the search criteria for the hyperlink we are trying to click.
public void OpenTicket(string ID) { #region Variable Declarations HtmlHyperlink uIA014111Hyperlink = this.UIServiceTicketsWindowWindow.UIServiceTicketsDocument.UIMainCustom.UIA014111Hyperlink; #endregion //Change the search criteria - Remove the logic we want to change uIA014111Hyperlink.SearchProperties.Remove(HtmlHyperlink.PropertyNames.InnerText); uIA014111Hyperlink.FilterProperties.Remove(HtmlHyperlink.PropertyNames.Href); uIA014111Hyperlink.FilterProperties.Remove(HtmlHyperlink.PropertyNames.TagInstance); uIA014111Hyperlink.FilterProperties.Remove(HtmlHyperlink.PropertyNames.ControlDefinition);
Page 74
Overriding Assertions 31. All of the Assertions we performed were looking for hard coded values. If we were logged in as someone else, for example, the Created By field would different and therefore our test would fail. To make assertions more robust we want to override all of our assertions. This may be done in the Coded UI Test. For example, the following change will modify the Ticket Title to be A New Ticket
DashboardUIMap dashboardPage= new DashboardUIMap(); CreateTicketUIMap createTicketPage = new CreateTicketUIMap(); TicketDetailUIMap ticketDetailPage = new TicketDetailUIMap(); TicketsUIMap ticketsListPage = new TicketsUIMap(); DeleteUIMap deletePage = new DeleteUIMap(); string newId=string.Empty; dashboardPage.LaunchBrowserAndNavToFabrikamDashboard(); dashboardPage.CreateNewTicket(); createTicketPage.CreateSampleTicketParams.UITitleEditText = "A New Ticket Title"; createTicketPage.CreateSampleTicket(); //Extract the ticket Id newId = ticketDetailPage.CurrentId; ticketDetailPage.AssertTicketTitleExpectedValues.UISampleTicketPaneDisplayText = "A New Ticket Title"; ticketDetailPage.AssertTicketTitle(); ticketDetailPage.AssertEscalationLevel(); ticketDetailPage.AssertDescription(); ticketDetailPage.AssertCreatedBy(); ticketDetailPage.ReturnToList(); ticketsListPage.OpenTicket(newId); ticketDetailPage.NavigateToDeletePage(); deletePage.DeleteTicket();
Data Driven Tests The test case is starting to look much more robust. Now we want to get rid of the hard coded magic strings we are passing in to our methods. We are going to use a CSV file to execute the method multiple times. 32. 33. 34. 35. Right click the FabrikamFiber.Web.Tests.CUITests.csproj project and select Add.., New Folder and name it DataSources. Right click the DataSources Folder and select Add, NewItem In the General tab, select the Text File and name it datasource.csv Enter the following into the new file
Row,Title,ExpectedTitle,EscalationLevel,ExpectedEscalationLevel,ExpectedDescription,ExpectedCreatedBy "1","First Title","First Title","Level 2","Level 2","This is a sample Ticket","Drew Robbins" "2","Second Title","Second Title","Level 1","Level 2","This is a sample Ticket","Drew Robbins" "3","Third Title","Third Title","Level 3","Level 2","This is a sample Ticket","Drew Robbins"
36. Modify the attribute on the test case as follows to add a connection to the data source: Copyright 2012 Microsoft Corporation Page 75
37. Modify the Coded UI Test to use the Data Source Values rather than the strings for parameters.
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\datasource.csv", "datasource#csv", DataAccessMethod.Sequential), DeploymentItem("FabrikamFiber.Web.Tests.CUITests\\DataSources\\datasource.csv"), TestMethod] public void CreateNewTicket() { DashboardUIMap dashboardPage= new DashboardUIMap(); CreateTicketUIMap createTicketPage = new CreateTicketUIMap(); TicketDetailUIMap ticketDetailPage = new TicketDetailUIMap(); TicketsUIMap ticketsListPage = new TicketsUIMap(); DeleteUIMap deletePage = new DeleteUIMap(); string newId=string.Empty; dashboardPage.LaunchBrowserAndNavToFabrikamDashboard(); dashboardPage.CreateNewTicket(); //Send data source Values in createTicketPage.CreateSampleTicketParams.UITitleEditText = TestContext.DataRow["Title"].ToString(); createTicketPage.CreateSampleTicketParams.UIEscalationLevelComboBoxSelectedItem = TestContext.DataRow["EscalationLevel"].ToString(); createTicketPage.CreateSampleTicket(); //Extract the ticket Id newId = ticketDetailPage.CurrentId; //Set the expected values ticketDetailPage.AssertTicketTitleExpectedValues.UISampleTicketPaneDisplayText=TestContext .DataRow["ExpectedTitle"].ToString(); ticketDetailPage.AssertEscalationLevelExpectedValues.UILevel2PaneDisplayText=TestContext.D ataRow["ExpectedEscalationLevel"].ToString(); ticketDetailPage.AssertDescriptionExpectedValues.UIThisisasampleTicketPaneDisplayText=Test Context.DataRow["ExpectedDescription"].ToString(); ticketDetailPage.AssertCreatedByExpectedValues.UIDrewRobbinsPaneDisplayText = TestContext.DataRow["ExpectedCreatedBy"].ToString(); ticketDetailPage.AssertTicketTitle(); ticketDetailPage.AssertEscalationLevel(); ticketDetailPage.AssertDescription(); ticketDetailPage.AssertCreatedBy(); ticketDetailPage.ReturnToList(); ticketsListPage.OpenTicket(newId); ticketDetailPage.NavigateToDeletePage(); deletePage.DeleteTicket(); }
38. Try to run the test by pressing F5 39. We get the following error because deployment is not enabled:
Page 76
Figure 87 - Error Message 40. To Enable Deployment double click the local.testsettings file. If you do not have a local.testsettings file manually add the file by right clicking on the solution and select Add New Item, Test Settings and give the file name as local.testsettings. 41. On the Deployment Tab check the Enable deployment check box and click the Apply Button.
Figure 88 - Enable Deployment 42. Retry the test and it should pass without error. Also Notice that the test will execute once per row of data in our Data Source. Ensuring the Application Under Test closes If through the course of this lab you have made any mistakes and the test execution failed you may have noticed that the browser was left open. This can be a big problem in an automated environment as the test agent can run out of memory or in a web application there can be a problem running multiple sessions on the same machine. To combat this we will use good error handling techniques. 43. Wrap your test case in either a try/catch/finally block or a using pattern as the application will always close when the test executes outside of debug mode. 44. Add a little error handling and we are done: Copyright 2012 Microsoft Corporation Page 77
REVIEW We have added custom code, parameterization, Data Binding, Error Handling and discussed the use of CopyFrom to make our test cases more robust.
Page 78
Refactor for increased maintainability Just as the code that goes into the product or solution that youre going to ship test code is also code which needs to be refactored and shaped according to recommended patterns and principles in order to ensure re-use, maintainability and readability. Move UI Map initializations to base class The test makes use of five different UI Maps. Theres a good chance that more tests will have similar initialization of UI Maps. In order to simplify the re-use and get rid of repetitive code blocks lets move the initialization of the UI Maps to a base class and then derive from it.
public class FabrikamUITest { private DashboardUIMap private CreateTicketUIMap private TicketDetailUIMap private TicketsUIMap private DeleteUIMap
= = = = =
public DashboardUIMap DashboardPage { get { return dashboardPage; } } public CreateTicketUIMap CreateTicketPage { get { return createTicketPage; } } public TicketDetailUIMap TicketDetailPage { get { return ticketDetailPage; } } public TicketsUIMap TicketsListPage { get { return ticketsListPage; } } public DeleteUIMap DeletePage { get { return deletePage; } } } public class FabrikamFiberTests : FabrikamUITest { //implementation omitted }
Page 79
DataRow helper method The test is now becoming more readable which naturally fosters maintainability and re-use. Theres one more thing that we should do though before we finish this. We have a fair amount of calls to the TestContext.DataRow indexer to get the data values. Lets add a helper method to our base class to simplify those calls. First we need to move the TestContext property to the base class and then we add a method called Bind which returns the specified row value. In FabrikamUITest base class
public string Bind(string columnName) { return TestContext.DataRow[columnName].ToString(); }
Page 80
Page 81
Exercise 2
Step 1: Context
This Hands on labs focuses on Coded UI Changes in the SDLC cycle. We will attempt to focus mainly on how to identify change, and then how to deal with that change in your automation. This hands on labs will focus on the practical application of how to deal with change in your test cases. This HOL has been designed around MVC 4 web site available on the Visual Studio 2012 Release Candidate Download. Navigate to http://asp.net/vnext for more information. We will be dealing mainly with the UI and Visual Studio 2012 as it pertains to Unit Test Explorer, Coded UI and Unit tests.
Figure 89 - New Project MVC4 1. 2. 3. Start by opening a new Project Under Templates -> C# find ASP.NET MVC 4 Web Application a. If you cannot locate or do not have MVC4 you can visit http://asp.net/vnext Name your Project and Solution and choose a location
Page 82
Figure 90 - MVC4 Project Options 4. 5. 6. Choose Internet Application View Engine Choose ASPX Create a Unit test project and click OK
Page 83
7. 8. 9.
If you build (F5) and run your application you should see the following webpage in Figure 91 Take note of the web address http://localhost: (some number) you will need this later. Lets go ahead and add a new user that we can log in with later.
Figure 92 - Register 10. Click on Register up in the upper right hand corner. Fill out the information in Figure 92. Copyright 2012 Microsoft Corporation Page 84
2.
Figure 94 - Add a CodedUI Test Project 3. 4. 5. Right click the solution and select add project You can type Coded into the upper right search box and youll get a list like Figure 94 Select Coded UI Test Project - Visual C# Page 85
Figure 95 - Start Coded UI Test Builder 7. 8. 9. If you didnt select record a new coded UI test after adding the Coded UI Test Project you can select it by right clicking your project / method and you can bring up the Generate Code for Coded UI Test -> Use Coded UI Test Builder. Start your recording and open Internet Explorer. Generate Code and Save this as OpenExplorer.
Figure 96 - MVC4 Webpage 10. Next Restart recording and go to the webpage http://localhost: (number) 11. Save and Generate code according to Figure 97 GoToHomePage
Page 86
Figure 97 - Add and Generate Code 23. After generating that code start recording again and click Login from the upper right.
Figure 98 - Login Window 12. Fill out the login information with the information we registered from above. 13. Do not remember or save this password. Rerunning this test case later will fail if you do so.
Page 87
Figure 99 - Generate Login Code 14. Save the Login information as LogIn and generate code according to Figure 99 15. After logging in you should see Hello name! Log off in the upper right corner. 16. Drag the crosshairs over the login name.
Figure 100 - InnerText Assertion 17. Go down to the InnerText Property and youll see the text as listed above. 18. You can right click add assertion on that line, or you can select it on the button above in the same window.
Page 88
Figure 101 - Assert Validation 19. Make sure the comparison value and message look like Figure 101
Figure 102 - Validation saved 20. Assertion(s) have been added will have a check mark next to them like Figure 102
Page 89
Figure 103 - Assertion Code Generation 32. Add and Generate code naming the method VerifyUserLoggedIn and give it a brief description. (Figure 103)
Figure 104 - Close Explorer 21. Lastly start recording and close the explorer window. 22. Save and Generate the code from this and call it Close Explorer (Figure 104)
Page 90
Figure 105 - Project Methods 23. Close the Recorder and you should come back to your Coded UI test which should look like Figure 105
Page 91
Figure 106 - Uncomment Test Attributes 24. 25. 26. 27. Expand the #region Additional test attributes Uncomment out TestInitalize() and TestCleanup() as seen in Figure 106 You will want to move this.UIMap.OpenExplorer() into the TestInitalize() block Next move this.UIMap.CloseExplorer() into the TestCleanup code block
Page 92
Figure 107 - Code Moved into attributes 28. Your test case should now look like Figure 107 with only the 3 pieces of our test case broken out in the method and the open and close moved into attributes.
Page 93
Figure 108 - Unit Test Explorer 29. Run your test cases by selecting Unit Test -> Windows -> Unit Test Explorer 30. Next Run all test cases or you can select the one test case you want to run, and just run that selected test. 31. You should see pass results like Figure 108.
Page 94
Figure 109 - Locate all controls 1. 2. 3. Double click your UI map in the project and you can see the UI Actions and UI Control Map. Open the webpage you want to validate and right click that on the UI map Locate all the controls under UIHomePageMyASPNETMVCDocument (Figure 110)
Figure 110 - UI Control Map Locate controls 4. You should validate all the Hyperlinks, buttons, and text boxes as seen in Figure 111. Page 95
Figure 111 - Change Log in to Log in here 6. 7. Now lets open up LoginUserControl.ascx from the MVC solution Youll want to locate the line:
<li><%: Html.ActionLink(Log in, Login, Account, routevalue.
8.
Change the first parameter Log in to Log in here (See Figure 111)
Figure 112 - Failed Test Case 9. After changing that line rebuild your application 10. Re-run your test case and youll now see that it fails to find that object because it no longer is the same. (See Figure 112) (The new HTML Logger is very useful for troubleshooting in scenarios like this. The new HTML log contains actionable information which allows you to identify the issue quicker and act upon it.)
Page 96
Page 97
3.
Now you should be able to open the web page, and then in your UI Map you can locate the UILoginButton, and it will successfully find that object.
Figure 116 - Locate Ui Properties 4. Locate all objects they should now all be located, and check marks next to them.
Page 98
Figure 117 - Updated test case passing 5. Re-run your test case it will now pass.
REVIEW We have shown how to manage references in Code-UI tests to make them more robust to changes in the code under tests .
Page 99
This HOL has been designed around connecting to MDSN from a Visual Studio 2012 Release Candidate based Code UI test. It does not require any specific VM.
Figure 118 - New Project Coded UI Test project 4. The project will be created, including a new Code UI test class.
Page 100
1.
2.
In this HOL the test will connect to MSDN and search for entries on Coded UI testing then check the title of the first option returned. In line with best practice for Coded UI tests we will create this test as three separately recorded steps and an assertion, as opposed to one recording. When the project is created you will be prompted as to how you wish to create the test steps. Select the record actions option. If this dialog has been closed it can be accessed from the Test-> Generate Code for Coded UI Tests menu option.
3.
Press the OK button on the dialog and the Test Builder tool will be shown.
Figure 120 - Test Builder 4. Press the record button (left most) a. Load Internet Explorer from the Windows Start menu b. Press the pause button (what was the record button) th c. Press the generate code button (4 button on Test Builder tool) and provide the Method name LoadBrowser. d. Finally press the Add and Generate button.
Page 101
Figure 121 - Add a Method 5. The next step can now be recorded. a. Press the record button again b. In the loaded browser enter the URL http://msdn.microsoft.com. c. Repeat the process of pausing the recorder and generating the Method, this time called NavigateToMSDN. Next record the step to search for the term Coded UI. a. Press the record button again. b. In the loaded browser enter Coded UI in the search dialog. c. Repeat the process of pausing the recorder and generating the Method, this time called SearchMSDN. Finally we need to add an assertion to make sure the search returned results. a. Press the add assertions button (the cross hairs) and drag the cursor over the first item in the returned search results
6.
7.
Figure 122 - Adding the assertion b. Press the add assertion button in the properties dialog to add an assertion on InnerText
Page 102
Figure 123 - Add Assertion property Once the assertion is added, press the Add and Generate code button again. Provide a name for the new assertion method CheckValue to complete the code required for the test. You can now close the Code UI Test Builder tool c.
8.
Figure 124 - Test Explorer 12. The test should run, a browser window open, and the search done. This may take up to 10-15 seconds.
Note
In a test for production code, it is good practice to make sure your Coded UI test unloads the browser at the end of the test to make sure the test machine is ready for the next test run.
Page 103
/// <summary> /// Parameters to be passed into 'NavigateToMSDN' /// </summary> [GeneratedCode("Coded UITest Builder", "11.0.50522.1")] public class NavigateToMSDNParams { #region Fields /// <summary> /// Go to web page 'http://msdn.microsoft.com/' /// </summary> public string UINewTabWindowsInterneWindowUrl = "http://typomsdn.microsoft.com/"; #endregion }
Note
The generated variable name UINewTabWindowsInterneWindowUrl in your the code may not be same as in the shown sample.
15. Rebuild the project, and rerun the test using the Test Explorer. A browser window should be opened but using the incorrect Url hence the page cannot be displayed
Figure 125 - Incorrect Url used in Browser Copyright 2012 Microsoft Corporation Page 104
Note
As the QTAgent32.exe.config file is in the Program Files (x86) folder structure, by default, due to UAC security you wont be able to save the file unless the editor you open it with is running with Administrator privileges.
19. Set the level of EqtTraceLevel switch to greater than 0 as shown below. In this HOL we set it to the highest level 4
the top of the file .. <system.diagnostics> <switches> <!-- You must use integral values for "value". Use 0 for off, 1 for error, 2 for warn, 3 for info, and 4 for verbose. --> <add name="EqtTraceLevel" value="4" /> </switches>
Copyright 2012 Microsoft Corporation Page 105
Note
In the RC build of Visual Studio 2012 as well as setting the EqtTraceLevel to greater than 0 you also had to set the EnableHtmlLogger key to true
<appSettings> <add key="StopTestRunCallTimeoutInSeconds" value="5"/> <add key="LogSizeLimitInMegs" value="20"/> <add key="CreateTraceListener" value="no"/> <add key="GetCollectorDataTimeout" value="300"/> <add key="EnableHtmlLogger" value="true"/> </appSettings>
20. Save the QTAgent32.exe.config file 21. Return to Visual Studio and re-run the failed test. You do not need to restart Visual Studio as the QTAgent32 process is respawned whenever the test is run, hence picking up the new config entry. The test should fail again, but when you scroll down and select the output link you should find extra files attached to the test.
Figure 127 - HTML Logger Attachments 22. As well as the screenshot PNG files you should see a UITestActionLog.Html file. If you click this link, the log file will be opened. This provides a detailed log including screenshots of the test
Page 106
Figure 128 - HTML Action Logger Output 23. Note that this failing test now took around 60 seconds. The extra logging steps do slow the test execution.
Figure 129 - A passing test 27. Click on the UITestActionLog.html file to see the details Copyright 2012 Microsoft Corporation Page 107
REVIEW We have shown how to enable the HTML Action Logger in Coded UI tests to make the debugging of the test easier.
References
Visual Studio ALM Rangers Site
http://msdn.microsoft.com/teamsystem/ee358786.aspx http://www.tinyurl.com/almrangers
Page 108