QA-104 Sprint Summary

Modified on Mon, 10 Jun at 3:28 PM

XPath/Chained XPath


What is XPath?

XPath (XML Path Language) is a query language used to navigate and select elements in an XML or HTML document based on their path or structure.


Where is XPath used?

In Selenium automation, XPath is widely used for locating and interacting with web elements, especially when other locator strategies (like ID or CSS selectors) fail or are not reliable.


How is XPath used?


1. Basic XPath

  • Locate elements using their tag names, attributes, or text content.


<!-- Find an element by its tag name -->
//input

<!-- Find an element by its attribute value -->
//input[@id='username']

<!-- Find an element by its text content -->
//a[text()='Login']


2. Chained XPath

  • Combine multiple XPath expressions to create more complex and specific locators.

  • Useful when dealing with dynamic or nested elements.


<!-- Find an element within a specific parent element -->
//div[@class='container']//input[@id='username']

<!-- Find an element based on its position -->
//ul[@id='menu']/li[2]/a

<!-- Find an element using multiple conditions -->
//input[@type='text' and @placeholder='Enter your name']


XPath Axes

Different Xpath Axes available


XPath Axes are ways to traverse the XML/HTML document tree structure based on the relationship between nodes, rather than their content or attributes.


Where are XPath Axes used?


XPath Axes are commonly used when the content or attributes of elements are dynamic or cannot be used to locate them uniquely. Axes allow you to identify elements based on their structural relationship with other elements that can be located reliably.


How are XPath Axes used?

//tagname[@attribute='value']//<axis>::<tagname>

Some commonly used XPath Axes:

  • child: Selects all children of the current node. Example: 

    //div[@class='parent']/child::p

  • descendant: Selects all descendants (children, grandchildren, etc.) of the current node.Example:

    //table//descendant::td

  • following-sibling: Selects all siblings after the current node.Example: 

    //td[text()='Name']/following-sibling::td[1]

  • parent: Selects the parent of the current node. Example: 

    //input[@id='username']/parent::div

  • ancestor: Selects all ancestors (parent, grandparent, etc.) of the current node. Example: 

    //input[@id='username']/ancestor::form


Testing Frameworks (TestNG)


What is TestNG?

TestNG (Test Next Generation) is a popular open-source testing framework for Java that provides a range of features and capabilities for writing and executing tests.


Where is TestNG used?

TestNG is widely used in Selenium testing to create, organize, and run test cases and test suites. It offers advanced features like annotations, data parameterization, parallel execution, and reporting.


How is TestNG used?

1. Create Test Classes and Methods

  • Define test classes and methods annotated with `@Test`.


import org.testng.annotations.Test;

public class LoginTest {

    @Test
    public void testSuccessfulLogin() {
        // Test steps for successful login
    }

    @Test
    public void testFailedLogin() {
        // Test steps for failed login
    }
}


2. Use Annotations

  • Leverage TestNG annotations for test configuration, grouping, and execution control.


import org.testng.annotations.BeforeMethod;
import org.testng.annotations.AfterMethod;

public class BaseTest {

    @BeforeMethod
    public void setup() {
        // Setup steps (e.g., launch browser)
    }

    @AfterMethod
    public void teardown() {
        // Teardown steps (e.g., close browser)
    }
}


3. Run Tests

  • Update the dependencies block in your build.gradle


dependencies {
    // https://mvnrepository.com/artifact/org.testng/testng/7.10.2
    testImplementation 'org.testng:testng:7.10.2'
}


  • Configuring test task

    test {
        useTestNG() {
            useDefaultListeners = true
            suites "src/test/java/org/demo/testng.xml"
        }
    
        afterSuite { desc, result ->
            if (!desc.parent) {
                println "\nTEST RESULT: ${result.resultType}"
                println "TEST SUMMARY: RAN ${result.testCount} TESTS, " +
                        "${result.successfulTestCount} SUCCEEDED, " +
                        "${result.failedTestCount} FAILED, " +
                        "${result.skippedTestCount} SKIPPED"
            }
        }
    
        testLogging {
            events "PASSED", "SKIPPED", "FAILED", "STANDARD_OUT", "STANDARD_ERROR"
            exceptionFormat = 'full'
    
            // Optionally do:
            showStackTraces = true
            showStandardStreams = true
        }
    
        outputs.upToDateWhen {false}
    }


In this configuration:

  • useTestNG() tells Gradle to use the TestNG test runner.

  • useDefaultListeners = true enables the default TestNG listeners.

  • suites "src/test/java/org/demo/testng.xml" specifies the location of your testng.xml file.

  • afterSuite configures the test reporting after the test suite execution.

  • testLogging configures the test logging behavior, such as showing stack traces and standard output/error streams.

  • outputs.upToDateWhen { false } forces Gradle to always run the tests, even if nothing has changed.


  • Finally we can run tests via

    ./gradlew test

Annotations in Java/TestNG


What are Annotations in Java?

Annotations in Java are metadata tags that provide additional information about a program element (e.g., class, method, variable) to the compiler or runtime environment.


Where are Annotations used?

Annotations are widely used in various Java frameworks and libraries, including TestNG, to define configuration, behavior, and metadata for test cases and test suites.


How are Annotations used in TestNG?


1. Test Annotations

  • `@Test`: Marks a method as a test case.

  • `@BeforeMethod`: Executes before each test method.

  • `@AfterMethod`: Executes after each test method.


2. Configuration Annotations

  • `@BeforeClass`: Executes once before the first test method in the current class.

  • `@AfterClass`: Executes once after all test methods in the current class have finished.

  • `@BeforeSuite`: Executes once before all tests in the suite.

  • @AfterSuite`: Executes once after all tests in the suite have finished.


3. Test Control Annotations

  • `@Ignore`: Excludes a test method or class from execution.

  • `@Priority`: Sets the priority of a test method for execution order.

  • `@Depends`: Specifies dependencies between test methods.


4. Data Parameterization Annotations

  • `@DataProvider`: Marks a method as a data provider for test methods.

  • `@Parameters`: Injects parameter values from a data provider or testng.xml.

    import org.testng.annotations.*;
    
    public class TestExample {
    
        @Test
        public void testMethod() {
            // Test logic
        }
    
        @BeforeMethod
        public void setup() {
            // Setup steps
        }
    
        @AfterMethod
        public void teardown() {
            // Teardown steps
        }
    
        @DataProvider
        public Object[][] getData() {
            return new Object[][] {
                {"value1"}, {"value2"}
            };
        }
    
        @Test(dataProvider = "getData")
        public void parameterizedTest(String param) {
            // Test logic with parameterized data
        }
    }


Data Parameterization and Listeners


What is Data Parameterization?

Data parameterization is a technique in testing that allows you to run the same test case with different sets of input data. This approach helps in achieving better test coverage and ensuring that the application under test behaves correctly with various input scenarios.


Where is Data Parameterization used?

Data parameterization is commonly used in Selenium testing to perform data-driven testing, where test cases are executed with multiple sets of data to validate the application's behavior under different input conditions.


How is Data Parameterization used in TestNG?


1. Pass Parameters via testng.xml

  • In the testng.xml file, we can define parameters and pass them to your test methods using the @Parameters annotation.

<test name="Login Tests">
    <parameter name="username" value="admin" />
    <parameter name="password" value="password" />
    <classes>
        <class name="com.example.tests.LoginTest">
            <methods>
                <include name="testSuccessfulLogin" />
            </methods>
        </class>
    </classes>
</test>


  • We can then used the passed values in code like

import org.testng.annotations.Parameters;

public class LoginTest {
   @Test
   @Parameters({"username", "password"})
    public void testSuccessfulLogin(String username, String password) {
        // Test steps for successful login using the provided username and password
    }
}

2. Using Data Provider

  • Create a method annotated with `@DataProvider` that returns a two-dimensional array or an `Iterator` of test data.


@DataProvider
public Object[][] testData() {
    return new Object[][] {
        {"username1", "password1"},
        {"username2", "password2"},
        {"username3", "password3"}
    };
}

Note: Instead of passing hard-coded data via code, we can also create objects from Excel sheets using Apache POI


  • Annotate the test method with `@Test(dataProvider = "dataProviderName")`.

  • The test method should accept the same number of parameters as the data provider returns.


@Test(dataProvider = "testData")
public void testLogin(String username, String password) {
    // Test steps for login using the provided username and password
}

What are TestNG Listeners?

TestNG Listeners are components that allow you to capture and respond to various events during test execution, such as test start, test pass, test failure, test skip, and suite completion.


Where are TestNG Listeners used?

Listeners are used in Selenium testing projects that leverage the TestNG framework to perform additional actions or logging based on test execution events. They can be used for various purposes, such as capturing screenshots on test failures, generating custom reports, or performing cleanup tasks.


How are TestNG Listeners used?


1. Create a Listener Class

  • Implement the desired listener interface(s) provided by TestNG (e.g., `ITestListener`, `ISuiteListener`).

  • Override the corresponding event methods to define the desired behavior.


import org.testng.ITestListener;
import org.testng.ITestResult;

public class TestListener implements ITestListener {
    @Override
    public void onTestFailure(ITestResult result) {
        // Capture screenshot on test failure
        // ...
    }

    @Override
    public void onTestSkipped(ITestResult result) {
        // Log skipped tests
        // ...
    }
}

2. Register the Listener

  • In the testng.xml file, add the listener class under the `<listeners>` tag.


<suite name="Test Suite">
    <listeners>
        <listener class-name="com.example.TestListener" />
    </listeners>
    <!-- Test classes -->
</suite>


testng.xml and Extent Reports


What is testng.xml?

testng.xml is a configuration file used by the TestNG framework to define test suites, test groups, test parameters, and other execution-related settings.


Where is testng.xml used?

testng.xml is typically used in Selenium testing projects that leverage the TestNG framework. It allows you to organize and control the execution of test suites and individual test cases.


How is testng.xml used?

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Regression Suite">
    <test name="Login Tests">
        <classes>
            <class name="com.example.tests.LoginTest" />
        </classes>
    </test>

    <test name="User Tests">
        <parameter name="environment" value="staging" />
        <classes>
            <class name="com.example.tests.UserTest">
                <methods>
                    <include name="testCreateUser" />
                    <exclude name="testDeleteUser" />
                </methods>
            </class>
        </classes>
    </test>
</suite>

What are Extent Reports?

Extent Reports is an open-source reporting library for TestNG that generates detailed and customizable HTML reports for test execution results.


Where are Extent Reports used?

Extent Reports are commonly used in Selenium testing projects that leverage the TestNG framework. They provide a comprehensive and user-friendly way to visualize and analyze test results, making it easier to identify failures, track test progress, and share reports with stakeholders.


How are Extent Reports used?

1. Configure Extent Reports

  • Add the Extent Reports dependency to your project. Create an instance of the ExtentReports class and configure the report settings in a base class.


import com.relevantcodes.extentreports.ExtentReports;
import com.relevantcodes.extentreports.ExtentTest;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import java.io.File;

public class BaseTest {
    protected static ExtentReports extentReports;
    protected static ExtentTest extentTest;

    @BeforeSuite
    public void setupReport() {
        File reportsDir = new File("./reports");

        if (!reportsDir.exists()) {
            reportsDir.mkdirs();
        }

        extentReports = new ExtentReports(reportsDir + "/index.html", true);
        extentReports.loadConfig(new File(reportsDir + "/extent-config.xml"));
    }

   @AfterSuite
    public void tearDownReport() {
        if (extentReports != null) {
            extentReports.flush();
            extentReports.close();
        }
    }
}


2. Generate Test Reports


  • Within your test classes, create instances of ExtentTest and use them to log test steps, failures, and other information.


import com.relevantcodes.extentreports.LogStatus;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

public class LoginTest extends BaseTest {
    @BeforeMethod
    public void setupTest() {
        extentTest = extentReports.startTest("Login Test");
    }

    @Test
    public void testSuccessfulLogin() {
        extentTest.log(LogStatus.INFO, "Navigating to login page");
        // Test steps for successful login
        extentTest.log(LogStatus.PASS, "Login successful");
    }

    @AfterMethod
    public void teardownTest() {
        extentReports.endTest(extentTest);
    }
}

3. View and Analyze Reports

  • After test execution, open the generated HTML report file to view detailed test results, including test steps, screenshots, logs, and analysis.

Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article