Application Testing

23 Jul 2023

Application testing concepts

Concepts

Software testing is a critical process in the software development life cycle aimed at identifying and fixing defects in a software application to ensure its quality and reliability. The major components of software testing include:

By employing these different components of software testing, developers and QA teams can enhance the quality and reliability of the software, leading to a better user experience and increased customer satisfaction.

Planning and Executing

Test plans, test strategies, test runs, test cases, and other related concepts are interconnected components within the broader domain of software testing. They work together to ensure that the testing process is well-organized, effective, and comprehensive. Here’s how they are related:

  1. Test Plan:

    A test plan is a high-level document that outlines the overall approach and objectives of the testing effort for a specific project or software release. It defines the scope, objectives, timelines, resources, and deliverables of the testing process. The test plan provides a roadmap for the testing activities and serves as a reference for all stakeholders involved in testing.

  2. Test Strategy:

    A test strategy is a document that details the approach and methodologies for testing a particular project or product. It is developed based on the test plan and provides more specific guidelines on how testing will be conducted. The test strategy covers aspects like test levels, test types, test environments, test data, and the roles and responsibilities of the testing team.

  3. Test Cases:

    Test cases are specific detailed steps or procedures that testers follow to execute a particular test scenario. They are derived from requirements and design documents and are intended to validate specific functionalities or aspects of the software. Each test case includes preconditions, test steps, expected results, and sometimes post-conditions.

  4. Test Runs:

    A test run is the actual execution of a set of test cases or test scripts against the software under test. Test runs can be conducted manually by testers or automated using testing tools, depending on the test cases and the nature of the testing.

  5. Test Execution:

    Test execution is the process of running the test cases against the software to identify defects or deviations from expected behavior. Test execution involves comparing actual results with expected results and reporting any discrepancies as defects.

  6. Defects/Bugs:

    Defects or bugs are issues found during the testing process where the actual behavior of the software deviates from the expected behavior. Testers log these defects, and developers are responsible for fixing them.

  7. Defect Reporting:

    Defect reporting is the process of documenting and tracking defects found during testing. Defect reports typically include information about the defect, steps to reproduce, severity, priority, and status.

Some Details

Unit Test

et’s consider a simple password verification system that checks if a given password meets certain criteria (e.g., minimum length, presence of uppercase letters, lowercase letters, and numbers). We can create a C# unit test using a popular testing framework like NUnit to verify the correctness of the password verification system. In this example, I’ll demonstrate how to use NUnit for unit testing:

First, make sure you have NUnit installed in your C# project. You can install it via NuGet Package Manager.

Here’s an example of the password verification system:

using System;
using System.Linq;

public class PasswordVerifier
{
    public static bool VerifyPassword(string password)
    {
        // Password length should be at least 8 characters.
        if (password.Length < 8)
            return false;

        // Password should contain at least one uppercase letter.
        if (!password.Any(char.IsUpper))
            return false;

        // Password should contain at least one lowercase letter.
        if (!password.Any(char.IsLower))
            return false;

        // Password should contain at least one digit.
        if (!password.Any(char.IsDigit))
            return false;

        return true;
    }
}

Now, let’s create the corresponding NUnit test for the PasswordVerifier class:

using NUnit.Framework;

[TestFixture]
public class PasswordVerifierTests
{
    [TestCase("Abcd1234", true)]
    [TestCase("hello123", false)]
    [TestCase("ABCDE1234", false)]
    [TestCase("Abc1234", false)]
    [TestCase("Abcd1234!", false)] // Special characters are not allowed in this example.
    public void VerifyPassword_ShouldReturnCorrectResult(string password, bool expectedResult)
    {
        // Arrange

        // Act
        bool result = PasswordVerifier.VerifyPassword(password);

        // Assert
        Assert.AreEqual(expectedResult, result);
    }
}

In this test class, we use the [TestFixture] attribute to indicate that it contains test methods, and we define a test method VerifyPassword_ShouldReturnCorrectResult with multiple test cases using the [TestCase] attribute. Each test case specifies an input password and the expected result of the password verification.

When you run the NUnit tests, they will automatically execute, and you should see the test results, indicating whether the PasswordVerifier class behaves correctly according to the defined test cases.

Note: The example above is a basic illustration of unit testing for password verification. In practice, you may need to implement more sophisticated password verification algorithms and additional test cases to cover various scenarios thoroughly. Additionally, consider using a strong and secure password hashing mechanism for real-world password handling.

Coded UI Tests

In this example, we’ll create a simple C# Selenium UI test using the Selenium WebDriver to automate the testing of a web application. For demonstration purposes, we’ll use the website “http://www.example.com” and perform a basic test to ensure that the page title is correct.

Before you begin, make sure you have installed the necessary NuGet packages for Selenium WebDriver:

Selenium.WebDriver Selenium.WebDriver.ChromeDriver (for Chrome browser automation) NUnit (for unit testing) Here’s the C# code for the Selenium UI test:

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

[TestFixture]
public class ExampleComUITest
{
    private IWebDriver driver;

    [SetUp]
    public void Setup()
    {
        // Initialize the Chrome WebDriver
        driver = new ChromeDriver();
        driver.Manage().Window.Maximize();
    }

    [Test]
    public void VerifyPageTitle()
    {
        // Navigate to the target website
        driver.Navigate().GoToUrl("http://www.example.com");

        // Get the page title
        string pageTitle = driver.Title;

        // Perform the assertion to check the page title
        Assert.AreEqual("Example Domain", pageTitle, "Page title is incorrect.");
    }

    [TearDown]
    public void Teardown()
    {
        // Close the browser after the test execution is complete
        driver.Quit();
    }
}

In this example:

  1. The SetUp method is annotated with the [SetUp] attribute, which is executed before each test method. It initializes the Chrome WebDriver and maximizes the browser window.
  2. The Test method is annotated with the [Test] attribute, which denotes a test case. In this method, we navigate to the “http://www.example.com” website, retrieve the page title, and use NUnit’s Assert.AreEqual method to compare the actual page title with the expected value.
  3. The TearDown method is annotated with the [TearDown] attribute, which is executed after each test method. It quits the browser after the test execution is complete.

To run this test, you’ll need to use a testing framework runner like NUnit Test Explorer in Visual Studio or the NUnit Console Runner.

Please note that this is a basic example to showcase the structure of a C# Selenium UI test. In real-world scenarios, you will have more complex test scenarios with multiple test cases, interactions with page elements, handling different browser configurations, and waiting for page elements to load, among other considerations.