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 PageObjects 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 StepTimeoutand 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