问题
Visual Studio version: 2013 premium Update 4
Created a couple of test methods: Login() amd Logout()
CloseOnPlaybackCleanup set to false on ApplicationUnderTest object after invoking the App.
Created an ordered test with both the above methods added to it in that order.
When the Ordered test is invoked, the the Login method works fine and then the App gets closed.
Then the Logout method runs and fails with an error that the Window is not found.
Note: The ApplicationUnderTest object has been created as static variable in a Global class.
Could you please help me fix this issue?
回答1:
In my admittedly limited experience with CodedUI Testing what you're experiencing is the typical behavior. When a test finishes, the app closes. The only way to do what you want is to code the log on and off in the same test. The CodedUI test facility built by Microsoft doesn't seem to recognize that you have to log on and log off of web sites. The positive side of this behavior is that when you're running a batch of automated tests and a test fails, the following test will simply log on and do it's test independently of the preceeding test.
So, rather than having separate logon and logoff tests, you need to incorporate logon and logoff into all your other tests. Here's what we did here:
Using the "Add => New Item => Test => Coded UI Test", create a new test class. When prompted, select Use Existing Action Recording. This class file will be your template for all test classes on the UI. In the template, add calls to log on and log off. When you need a new test, copy the template and add your CodedUI test (right-click => Generate Code for CodedUI Test => ) between the log on and log off. Here's an example (it's pretty long):
// Description: This is a template for a CodedUI Test Case class.
//
// STEPS:
// 1) In Windows Explorer, *COPY* this file to the codedUI project folder.
// 2) In Windows Explorer, change the file name of the newly copied file.
// • Use the test case name from Microsoft Test Manager (MTM).
// • Remove all spaces.
// • Replace dashes with underscores.
// • Add the test case number from Microsoft Test Manager (MTM).
// ==> EXAMPLE: MySys_ThisIsTheNameOfTheTestCase_98765.cs
// 3) In Visual Studio, add this file to the project.
// • In Solution Explorer, right-click the project node => Add => Existing Item.
// • Select the newly renamed file and click Add.
// 4) In Visual Studio, open this newly added file.
// 5) Change the namespace to the project name.
// 6) Change the comments in the Class Summary to the Test Case ID and Test Case Name from the case in MTM.
// 7) Change the class name to the new Test Case file name (without the ".cs").
// 8) Change the class constructor's name to the new Test Case file name (without the ".cs").
// 9) In the class constructor, specify the test case number in the line
// "string TestCaseNbr = "<Test case number from MTM>";"
// ==> EXAMPLE: string TestCaseNbr = "98765");
// 10) Change the test Method name to the new Test Case file name (without ".cs"), and append "_Test" to the end.
// 11) Using the test builder, insert previously recorded test case steps from MTM.
// • Position the cursor by clicking below the line that reads "Do some work - Insert recorded steps here".
// • Use "Test" => "Generate Code for CodedUI Test" => "Use Existing Action Recording" . . .
// • OR Right-click => "Generate Code for CodedUI Test" => "Use Existing Action Recording".
// • In the dialog that appears, click the "ID" radio button.
// • Enter something from the test case name/number from MTM in the text box to the right of the ID button.
// • Click Find.
// • If more than one test appears, select the correct one.
// • Click Ok.
// 12) Comment out the recording step that relates to user login (logging in is handled by the template code).
// 13) Basic test case setup is complete.
// 14) Build the project and run the test case from Visual Studio.
//
using System;
using Login;
using System.Collections;
using Microsoft.VisualStudio.TestTools.UITesting;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace <projectName>
{
/// <summary>
/// Purpose:
/// Implements Test Case ID: <Test Case Number from MTM>
/// Test Case Name: <Test Case name from MTM>
/// </summary>
[CodedUITest]
public class CodedUI_Test_Case_Template : InitializeLoginData
{
bool testCaseFailed = false;
public CodedUI_Test_Case_Template()
{
string TestCaseNbr = "<Test case number from MTM>";
}
[TestMethod]
public void CodedUI_Test_Case_Template_Test()
{
string userID = "UserID";
string password = "Password";
try
{
// Log the user in
User user = New User(userID, password);
user.UserLogin();
// ******************************************
// **** Insert recorded steps here ****
// ******************************************
}
catch (Exception e)
{
// Write out an error message
testCaseFailed = true;
TestContext.WriteLine("Test case failed for user " + userId + " for test case " + TestCaseNbr + ".");
TestContext.WriteLine(e.ToString());
}
finally
{
// Log the user out.
user.UserLogout();
}
if (testCaseFailed)
{
Assert.Fail("Test case failed.");
}
user.UserLogout();
// The browser has to be closed from the test case file
User.browser.Close();
User.browser.WaitForControlNotExist(2000);
}
/// <summary>
/// Gets or sets the test context which provides information
/// about and functionality for the current test run.
/// </summary>
private TestContext testContextInstance;
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
private UIMap map;
public UIMap UIMap
{
get
{
if ((map == null))
{
map = new UIMap();
}
return map;
}
}
}
}
Create a separate Log On/Log Off class(es). You can probably use what you already have as the basis of this class. Here's an example, called User.cs in the Template class:
using System;
using System.IO;
using System.Drawing;
using System.Xml;
using Microsoft.VisualStudio.TestTools.UITesting;
using Microsoft.VisualStudio.TestTools.UITesting.HtmlControls;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Keyboard = Microsoft.VisualStudio.TestTools.UITesting.Keyboard;
namespace Login
{
[CodedUITest]
public class User
{
public string UserID;
public string Password;
public static BrowserWindow browser;
public static bool browserLaunched = false;
public User()
{
}
public User(string uid, string pwd)
: this()
{
UserID = uid;
Password = pwd;
}
[TestMethod]
public void UserLogin()
{
if (browserLaunched == false || Login.User.browser.Exists == false)
{
browser = BrowserWindow.Launch("http://your/login/page/url");
browser.WaitForControlEnabled(5000); // waits 5 seconds - you may need more time
browserLaunched = true;
}
HtmlEdit uIUserIDEdit = new HtmlEdit(browser);
#region Search Criteria
// This is the user ID field.
// Get these criteria from your recording of logging on to your application.
#endregion
// Click in the password field
Mouse.Click(uIUserIDEdit, new Point(10, 10));
Keyboard.SendKeys(UserID);
HtmlEdit uIPasswordEdit = new HtmlEdit(browser);
#region Search Criteria
// This is the password field.
// Get these criteria from your recording of logging on to your application.
#endregion
// Click in the password field
Mouse.Click(uIPasswordEdit, new Point(10, 10));
Keyboard.SendKeys(Password);
HtmlButton uILoginButton = new HtmlButton(browser);
#region Search Criteria
// This is the log in button.
// Get these criteria from your recording of logging on to your application.
#endregion
// Click 'Log in' button
Mouse.Click(uILoginButton, new Point(10, 10));
browser.WaitForControlReady(5000); // waits 5 seconds - you may need more time
// Verify that the 'Text' property of 'Address' text box equals 'http://your/logged/in/landing/page/url'
Uri page_uri = browser.Uri;
Assert.AreEqual("http://your/logged/in/landing/page/url", page_uri.AbsoluteUri, "Error: Failed To Log In");
}
public void UserLogout()
{
#region Search Criteria
// This is the log out button.
// Get these criteria from your recording of logging on to your application.
#endregion
// Click 'Logout' link
Mouse.Click(logout, new Point(10, 10));
browser.WaitForControlEnabled(5000); // waits 5 seconds - you may need more time
Uri page_uri = browser.Uri;
Assert.AreEqual("http://your/Loggedout/path"", page_uri.AbsoluteUri, "Error: Failed to Log Out");
// Browser Must Be Closed in Calling Test Case Class
// browser.Close();
// browser.WaitForControlNotExist(2000);
}
public static void LogOutput(string TestCaseName, string status)
{
// You can add code to log your results here.
}
#region TestContext and UIMap
/// <summary>
///Gets or sets the test context which provides
///information about and functionality for the current test run.
///</summary>
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
private TestContext testContextInstance;
public UIMap UIMap
{
get
{
if ((this.map == null))
{
this.map = new UIMap();
}
return this.map;
}
}
private UIMap map;
#endregion
}
}
We've also added logging and other administrative/overhead stuff to the log on/log off class so you don't need to manually add that to every test class.
This way each test logs on, navigates to the page to be tested, performs the test, then logs off. It's slower, but more dependable.
来源:https://stackoverflow.com/questions/32034851/coded-ui-app-gets-closed-after-each-test-even-with-closeonplaybackcleanup-set-t