What is all this for!!!

Benefits of test automation

  1. Ensuring high reliability:
    • Bugs and defects in software code are an inevitable part of development.
    • Automated testing allows you to quickly and repeatably identify problems in the early stages of development.
    • This contributes to the high reliability and stability of the software.
  2. Reduced development cycle time:
    • Manual testing is time consuming.
    • Automated tests can be quickly executed, even in the case of several tens or hundreds of test scenarios.
    • This reduces the overall development cycle time and speeds up the delivery of the product to the market.
  3. High speed and accuracy:
    • Automated tests run significantly faster than the same manual tests.
    • The absence of a human factor and the repeatability of actions guarantee high testing accuracy.
  4. Improving team productivity:
    • Manual testing can be a monotonous and time-consuming process.
    • Automation frees testers from routine and allows them to focus on more creative and analytical tasks.
  5. Early identification of problems:
    • Automation allows real-time testing throughout the development process.
    • This helps to identify and resolve problems early, which reduces the cost of fixing defects later on.
  6. Ensuring compatibility and scalability:
    • Automated tests allow you to quickly check the functionality of software on various configurations and platforms.
    • This is especially important in today’s environment of multiple devices and browsers.

The role of Selenium and C# in creating reliable automated tests

Imagine that automated tests are special tools that help you check if a program is working correctly. Such tests are especially useful for websites, and here’s why.

Selenium is like a powerful detective that can notice what is happening on a web page. It can find buttons, text boxes, dropdowns, and more. And C# is a language in which you can “talk” to Selenium and give commands to it.

Together Selenium and C# are like a dynamic duo. They allow us to create tests that will check the website for errors. For example, we can tell them to “click” the “Login” button and check that the correct message is then displayed. It’s like checking that all the buttons on your remote control are working properly.

Web Element Manipulation

When creating robust automated tests, you need to interact with web elements such as buttons, text boxes, and dropdowns. In this process, Selenium provides tools for finding and interacting with elements on the page, while C# gives you the ability to efficiently manage these elements.

Click on the “Login” button on the login page

IWebElement loginButton = driver.FindElement(By.Id("login-button"));
loginButton.Click();

Entering text in the search field

IWebElement searchBox = driver.FindElement(By.Name("search"));
searchBox.SendKeys("Selenium testing");

Selecting the “Black” option from the drop-down list of colors

IWebElement colorDropdown = driver.FindElement(By.Id("color-selector"));
SelectElement colorSelect = new SelectElement(colorDropdown);
colorSelect.SelectByText("Black");

Login to the site and check for successful authorization

using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;

[TestFixture]
public class LoginTests
{
    IWebDriver driver;

    [SetUp]
    public void SetUp()
    {
        driver = new ChromeDriver();
        driver.Navigate().GoToUrl("https://www.example.com/login");
    }

    [Test]
    public void TestSuccessfulLogin()
    {
        IWebElement usernameInput = driver.FindElement(By.Id("username"));
        IWebElement passwordInput = driver.FindElement(By.Id("password"));
        IWebElement loginButton = driver.FindElement(By.Id("login-button"));

        usernameInput.SendKeys("myUsername");
        passwordInput.SendKeys("myPassword");
        loginButton.Click();

        IWebElement welcomeMessage = driver.FindElement(By.CssSelector(".welcome-message"));
        Assert.AreEqual("Welcome, User!", welcomeMessage.Text);
    }

    [TearDown]
    public void TearDown()
    {
        driver.Quit();
    }
}

Create Structured Tests

Structuring tests improves their manageability and readability. C# provides the means to create structured test classes and namespaces.

Organizing test methods using classes

public class TestSuite
{
    [Test]
    public void TestLogin()
    {
        // Your authorization test code
    }

    [Test]
    public void TestSearch()
    {
        // Your search test code
    }
}

Using Namespaces to Separate Test Functionality

namespace TestSuite.Authentication
{
    // Authorization Tests
}

namespace TestSuite.Search
{
    // Search Tests
}

Grouping tests into suites using attributes

[TestFixture("Chrome")]
[TestFixture("Firefox")]
public class CrossBrowserTests
{
    private string browser;

    public CrossBrowserTests(string browser)
    {
        this.browser = browser;
    }

    [Test]
    public void TestHomePage()
    {
        // Your code for testing the main page
    }
}

Also, Selenium and C# help us to wait for important things to happen on a web page. For example, we can tell them to wait until the desired item is loaded before continuing. It’s like giving yourself some time to wait for your friend to come to the meeting.

Expectation Management

Expectations play a key role in creating stable automated tests. Selenium and C# together provide tools for efficient wait management.

Waiting for an element to load using explicit wait

Explicit waits allow you to wait for a certain state of an element before interacting with it. In this example, we will wait for the Submit button to become clickable.

IWebElement sendButton = driver.FindElement(By.Id("send-button"));

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(ExpectedConditions.ElementToBeClickable(sendButton));

sendButton.Click();

Waiting for an element to exist using implicit wait

Implicit waits are automatically applied to all WebDriver actions that wait for an element on the page for a certain amount of time. In this example, we will expect an element with id “result” to appear on the page.

driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);

IWebElement resultElement = driver.FindElement(By.Id("result"));
string resultText = resultElement.Text;

Waiting for element to disappear after removal

It is often necessary to wait for an element to disappear after some action. In this example, we will expect the element with the class “loading-spinner” to disappear after the page loads successfully.

IWebElement loadingSpinner = driver.FindElement(By.ClassName("loading-spinner"));
// Assume that the download completes and the element disappears after a few seconds

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.ClassName("loading-spinner")));

// Continuing the test after download is complete

Waiting for an element’s value to change after an action

Sometimes you want to wait for an element to change its value after some action. In this example, we’ll wait for the text on the button to change to “Done” after it’s clicked.

IWebElement button = driver.FindElement(By.Id("action-button"));
button.Click();

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(ExpectedConditions.TextToBePresentInElement(button, "Готово"));

Waiting for an element to exist before performing an action

Checking for the presence of an element before performing an action can prevent errors related to the absence of an element on the page.

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement element = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("element-id")));

element.Click();

Waiting for an element to be in the frame

If the element is inside a frame, it must first be toggled and then wait applied.

driver.SwitchTo().Frame("frame-name");

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement elementInFrame = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("element-id")));

elementInFrame.Click();

// Return to the main page after completing the actions in the frame
driver.SwitchTo().DefaultContent();

Waiting for an asynchronous loading of an element

Sites with asynchronous loading may require a special wait to correctly check for the existence of elements.

IWebElement asyncLoadedElement = driver.FindElement(By.Id("async-loaded-element"));

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(driver => asyncLoadedElement.Displayed && asyncLoadedElement.Enabled);

asyncLoadedElement.Click();

Using expectations in automated tests allows you to create stable and reliable scenarios, taking into account possible delays in loading elements and changing states on web pages.

And one more advantage: we can create tests so that they can work with different data. This is useful because we can check that the program works well with different options. It’s like we checked that your new backpack holds both books and food well.

Parameterization of tests

Parameterization allows you to create generic tests that can be applied to different scenarios.

Passing Parameters to a Test Method

[TestCase("user1", "password1")]
[TestCase("user2", "password2")]
public void TestLogin(string username, string password)
{
    // Your code for testing authorization with different credentials
}

Using configuration files to store settings

string username = ConfigurationManager.AppSettings["username"];
string password = ConfigurationManager.AppSettings["password"];
// Your code for testing authorization with parameters from the configuration file

Framework integration

Framework integration makes it easy to create and run tests.

Integration with the NUnit framework

[TestFixture]
public class NUnitTests
{
    [Test]
    public void TestMethod()
    {
        // Your code for testing
    }
}

Integration with the MSTest framework

[TestClass]
public class MSTestTests
{
    [TestMethod]
    public void TestMethod()
    {
        // Your code for testing
    }
}

Using xUnit Attributes

public class XUnitTests
{
    [Fact]
    public void TestMethod()
    {
        // Your code for testing
    }
}

Finally, thanks to Selenium and C#, we can control what happens when something goes wrong. For example, if the button does not appear on the page, we can say that this is normal and there is no need to be scared. It’s like knowing that even if the weather isn’t exactly perfect, you can still find a way to have fun.

Exception Handling

Exception handling allows you to effectively manage possible errors during test execution.

Using the try-catch construct to handle an exception ElementNotVisibleException

try
{
    IWebElement element = driver.FindElement(By.Id("hidden-element"));
    element.Click();
}
catch (ElementNotVisibleException ex)
{
    // Your code to handle the exception
}

Handling WebDriverExceptionwhen the connection to the browser is lost

try
{
    driver.FindElement(By.Id("element-id")).Click();
}
catch (WebDriverException ex)
{
    // Your code to handle the exception
}

And so, we can create reliable and accurate tests for websites. They help us to make sure that the program works correctly and users will not run into trouble. It’s like we have our own research team that keeps track of the quality of our web adventures.

Use Assertto check if element exists before interacting

IWebElement element = driver.FindElement(By.Id("element-id"));
Assert.NotNull(element, "Element not found");
element.Click();

In conclusion, I would like to say that we have only looked a little into the amazing world of possibilities that Selenium and the C# programming language provide us. We’ve covered just a small part of how combining Selenium’s ability to interact with and manipulate web elements with the flexibility of the C# programming language gives you powerful tools to create robust automated tests.

Try, experiment and enjoy the results that will help you to ensure the high quality of your software product.