Interactions
Replacing text on a control
❌ Don't: Select and replace text with a double click
Emulating what the end user would do is a good practice, but QualityMate already performs similar steps under the hood and these are therefore not necessary.
PageObject.TextBox.Click(MouseButton.Left, ClickType.Single);
PageObject.TextBox.Click(MouseButton.Left, ClickType.Double);
PageObject.TextBox.SendKeys("Hello World");
✔️ Do: Use the control's Text property
Setting the control's Text property will yield the same result and be significantly more readable.
PageObject.TextBox.Text = "Hello World";
✔️ Do: Select and SendKeys in masked text boxes
For masked text box uses the SendKeys method instead of Text
property. Remember to select the entire text before sending the keys.
PageObject.MaskedTextBox.SendKeys("[" + Keys.CTRL + "a]"); // Select all the text
PageObject.MaskedTextBox.SendKeys("maskedtext");
Repeated step sequences
❌ Don't: Repeat step sequences in code
Don't repeat yourself. Repeated code is bug-prone and difficult to maintain.
PageObject.NameTextBox.Text = "Hello";
PageObject.LastNameTextBox.Text = "World";
PageObject.Button.Click();
// elsewhere in the code
PageObject.NameTextBox.Text = "Hola";
PageObject.LastNameTextBox.Text = "Mundo";
PageObject.Button.Click();
✔️ Do: Abstract repeated steps into page objects
If a repeated sequence of steps makes use of a single PageObject
, that functionality should be moved into the PageObject
:
// PageObject.cs
public void FillForm(string name, string lastName)
{
this.NameTextBox.Text = name;
this.LastNameTextBox.Text = lastName;
this.Button.Click();
}
✔️ Do: Abstract repeated steps into a private method
If you repeat steps within the same test case file, abstract them into a private method in that test case's class:
// TestCaseFile.cs
private void TestCaseScript(UiExecutionController controller)
{
string fullUserName = this.GetFullUserName(controller);
}
private void Login(UiExecutionController controller)
{
string fullUserName = this.GetFullUserName(controller);
}
private string GetFullUserName(UiExecutionController controller)
{
// code which obtains the full user name
}
✔️ Do: Create a utility class with commonly used steps
If a repeated sequence makes use of multiple PageObject
s in multiple test case files, abstract them into a static utilities class with a static public method with the repeated steps:
// TestCaseFile.cs
private void TestCaseScript(UiExecutionController controller)
{
string fullUserName = TestUtils.GetFullUserName(controller);
}
// TestCaseFile2.cs
private void AnotherTestCaseScript(UiExecutionController controller)
{
string fullUserName = TestUtils.GetFullUserName(controller);
}
// TestUtils.cs
public static string GetFullUserName(UiExecutionController controller)
{
// code which obtains the full user name
}
Awaiting for the application to respond
❌ Don't: Use System.Threading.Thread.Sleep
Thread.Sleep
is not necessary in QualityMate. It will slow down the execution of your tests and make them fragile because you're not guaranteed that the application will be in the expected state after awaiting.
Thread.Sleep(5000);
PageObject.Button.Click();
❌ Don't: Use a try / catch to retry failed steps
Retrying with a try
/ catch
clause causes code duplication and unnecessary verbosity.
try
{
PageObject.Button.Click();
}
catch
{
PageObject.Button.Click();
}
✔️ Do: Simply use the framework
Control interactions and validations have built-in retrying.
// this will re-attempt to perform the Click and Validate until:
// - they work
// - one of the steps times out
PageObject.Button.Click();
PageObject.Button.Validate(self => self.Text == "Hello");
✔️ Do: Adjust the step and execution timeouts
Retrying in QualityMate doesn't happen forever. Steps and tests timeout according to the StepTimeout
and ExecutionTimeout
configuration parameters respectively. You can find more information about how to set these on Setting Up the Configuration.
✔️ Do: Use the Retry static class
If you must await on code that's not an interaction or a validation, use the Retry
static class. You can find more information about it on Retries.
Finding child controls
❌ Don't: Cast to a concrete implementation and use concrete methods
Casting a control to it's concrete implementation defeats the purpose of QualityMate: you'll have to modify that code upon changing technologies. Concrete control implementations are not meant to be used by clients.
// this will break on a technology that doesn't support ConcreteControl
Selector selector = new("#label_selector");
(parentControl as ConcreteControl).FindControl(selector);
✔️ Do: Use the Find method
The IElement.Find
method has the same functionality as casting to a concrete implementation without requiring a cast. Most control interfaces in QualityMate implement IElement
.
// parentControl is a Control which implements IElement
ILabel label = parentControl.Find<ILabel>("#label_selector");
Last updated
Was this helpful?