Rayrun
← Back to QA Wiki

Definition of XPath Query

A language designed to extract and manipulate XML document data. Useful for retrieving XML data for content scanning.

Related Terms:

See also:

Thank you!
Was this helpful?

Questions about XPath Query?

Basics and Importance

  • What is XPath Query?

    XPath Query is a powerful language designed for selecting nodes from an XML document. It can be equally effective in querying HTML structures, especially when used within web automation frameworks like Selenium. XPath stands out for its ability to perform complex queries with precision, enabling testers to locate elements within a webpage's DOM with specificity.

    Here's an example of an XPath expression that selects all input elements with a name attribute containing the substring 'user':

    //input[contains(@name, 'user')]

    XPath's ability to navigate the DOM using various axes, such as ancestor, descendant, following, and preceding, provides a versatile toolkit for testers to interact with web elements in relation to their position in the DOM tree. This is particularly useful when elements lack unique identifiers or when DOM structures are dynamic.

    In test automation, XPath Queries are often used within scripts to interact with web elements, such as clicking a button or extracting text. The precision of XPath makes it invaluable for asserting the presence of elements or their states, which is crucial for verifying the functionality of web applications.

    While XPath is a cornerstone in web automation, it requires careful crafting to avoid brittle selectors that may break with UI changes. Testers must balance specificity with flexibility, often opting for relative XPath expressions that can withstand minor alterations in the DOM structure. Efficient use of XPath can significantly enhance the robustness and maintainability of automated test suites.

  • Why is XPath Query important in software automation?

    XPath Query is crucial in software test automation for its precision and flexibility in locating elements within XML and HTML documents. It enables testers to identify elements with specific attributes, text values, or hierarchical relationships, which is essential when dealing with dynamic or complex web pages where elements' attributes or positions may change.

    Using XPath, automation engineers can craft unique paths to interact with elements that lack identifiers or classes, or when other locator strategies are not viable. This is particularly useful in end-to-end (e2e) testing, where replicating user interactions with the UI is necessary.

    Moreover, XPath's ability to navigate both forwards and backwards in the DOM (Document Object Model) hierarchy allows for more sophisticated element searches, including finding a parent element based on the attributes of a child, or vice versa.

    In the context of Selenium and other web automation tools, XPath is often the go-to querying language due to its cross-browser compatibility and support for complex locators. It is a powerful tool for assertions as well, allowing testers to verify the presence, absence, or state of elements in a page.

    However, XPath queries can be brittle and slower compared to CSS selectors, especially with poorly structured HTML. To mitigate this, it's important to write efficient and resilient XPath expressions, focusing on relative paths and robust attributes.

    In summary, XPath is an indispensable tool in the test automation engineer's arsenal, providing the granularity and control needed to effectively interact with and verify UI elements in automated tests.

  • What are the basic components of an XPath Query?

    The basic components of an XPath query include:

    • Root node: The starting point of the query, denoted by /.
    • Element: The tag name of an XML/HTML element. For example, div.
    • Attribute: The property of an element, accessed with @. For example, @id.
    • Text node: The textual content within an element, accessed with text().
    • Wildcard: The * symbol, which matches any element node.
    • Predicate: Enclosed in square brackets [], predicates refine the selection by providing specific criteria.
    • Operator: Symbols like =, !=, >, <, or, and and that define conditions within predicates.
    • Function: Built-in functions like contains(), starts-with(), and count() that perform operations on nodes.
    • Axis specifier: Defines the tree relationship between nodes, such as child::, ancestor::, or following-sibling::.

    Example XPath query structure:

    //div[@class='example']//a[text()='Click Here']/@href

    In this example:

    • // selects nodes from anywhere in the document.
    • div specifies the element type.
    • [@class='example'] is a predicate filtering div elements with a class attribute of 'example'.
    • //a selects all a elements that are descendants of the div.
    • [text()='Click Here'] is another predicate, this time selecting a elements with text 'Click Here'.
    • /@href selects the href attribute of the a element.
  • What is the role of XPath Query in e2e testing?

    In end-to-end (e2e) testing, XPath Query plays a crucial role in locating and interacting with web elements. It enables testers to pinpoint specific elements within the Document Object Model (DOM) of a webpage, which is essential for simulating user interactions such as clicking buttons, entering text, and validating the presence or properties of elements.

    XPath's ability to navigate through the DOM using various axes and functions allows for dynamic and flexible element selection. This is particularly useful in e2e tests where the structure of web pages may change, requiring selectors that can adapt to these changes without breaking the tests.

    For instance, in a complex web application, elements might not have unique identifiers or consistent CSS classes. XPath can traverse the DOM to find elements based on their relationships with other elements, which is less brittle in the face of UI changes.

    Moreover, XPath's support for predicates enables testers to refine their element selection with conditions, ensuring that even elements with similar attributes can be distinguished and accurately targeted.

    In automated e2e testing frameworks like Selenium, XPath is often used to create robust locators. For example:

    driver.findElement(By.xpath("//button[text()='Submit']")).click();

    This line of code would find a button with the text 'Submit' and perform a click action, mimicking a user's interaction during the test scenario.

    Overall, XPath Query is indispensable for achieving precision and flexibility in element location strategies within e2e testing, contributing to more reliable and maintainable test suites.

  • How does XPath Query differ from other querying languages?

    XPath Query is distinct from other querying languages primarily in its specificity to XML and HTML structures. Unlike SQL, which is designed for querying relational databases, or CSS selectors, which are used for styling and selecting elements in HTML, XPath enables the selection of nodes based on a variety of criteria, including their hierarchy, attributes, and content within an XML document.

    XPath stands out with its rich set of functions and axes, allowing for complex traversals and selections that are not as straightforward in other languages. For instance, while CSS selectors can be used to navigate HTML documents, they lack the ability to traverse upwards in the document hierarchy or select nodes based on text content, both of which XPath can do with ease.

    Furthermore, XPath's ability to use predicates offers a more granular level of control over selections than what is typically available in CSS selectors. This makes it particularly powerful for scenarios where precise extraction of data is required, such as in test automation where specific elements need to be targeted.

    In contrast to JSONPath, which is used for JSON objects, XPath is designed for the structured nature of XML and cannot be directly applied to JSON. However, both share a similar concept of path expressions to navigate through elements.

    Overall, XPath's unique capabilities make it an indispensable tool in scenarios where precise navigation and selection within XML and HTML documents are necessary, particularly in the context of software test automation.

Syntax and Structure

  • What is the basic syntax of an XPath Query?

    The basic syntax of an XPath query consists of a path expression that defines the way to navigate through the elements and attributes in an XML document. Here's a simplified breakdown:

    • Absolute path: Starts with a single forward slash / indicating the root node, followed by the path to the desired element.
      /root/child/grandchild
    • Relative path: Begins with a double forward slash // which selects nodes from the current node that match the selection no matter where they are in the document.
      //grandchild
    • Predicates: Use square brackets [] to filter nodes by a condition.
      /root/child[1]
    • Attributes: Use the @ symbol to select attributes.
      //child[@attr='value']
    • Wildcards: Asterisks * match any element node.
      /root/*
    • Current node: A period . represents the current node context.
      .//child
    • Parent node: Two periods .. navigate up to the parent node.
      ../sibling

    These elements can be combined to form complex queries that precisely locate the desired nodes in an XML structure. Remember to use concise expressions and leverage specific paths and predicates for efficient querying.

  • How do you structure an XPath Query to select nodes?

    To structure an XPath query for selecting nodes, follow these guidelines:

    • Identify the starting point: Choose the context node from where the search should begin. If no context is specified, the query starts from the root node.

    • Use path expressions: Combine steps to navigate through the nodes. Steps are separated by slashes (/ for direct children, // for any descendant).

    • Select nodes by name: Specify the tag name of the desired nodes. Use * to match any node.

    • Apply predicates: Enclose predicates in square brackets [] to filter nodes based on conditions like attributes, position, or content.

    • Specify axes: Include axes to define the relationship between the current node and the nodes to be selected (e.g., ancestor, descendant, following-sibling).

    • Utilize operators: Combine conditions within predicates using operators like and, or, =, !=.

    • Incorporate functions: Use XPath functions for string manipulation, numeric calculations, or node set processing (e.g., text(), contains(), count()).

    Here's an example of a structured XPath query:

    //div[@class='container']/table//tr[td[contains(text(),'Automation')]]

    This query selects all tr elements that have a td child containing the text 'Automation' within any table that is a descendant of a div with a class attribute of 'container'.

  • What are the different types of XPath axes?

    XPath axes define a node-set relative to the current node. Here are the different types of XPath axes used in queries:

    • ancestor: Selects all ancestors (parent, grandparent, etc.) of the current node.
    • ancestor-or-self: Selects all ancestors and the current node.
    • attribute: Selects all attributes of the current node.
    • child: Selects all children of the current node.
    • descendant: Selects all descendants (children, grandchildren, etc.) of the current node.
    • descendant-or-self: Selects all descendants and the current node itself.
    • following: Selects everything in the document after the closing tag of the current node.
    • following-sibling: Selects all siblings after the current node.
    • namespace: Selects all namespace nodes of the current node.
    • parent: Selects the parent of the current node.
    • preceding: Selects all nodes that appear before the current node in the document, except ancestors, attribute nodes, and namespace nodes.
    • preceding-sibling: Selects all siblings before the current node.
    • self: Selects the current node.

    Example usage in an XPath query:

    //book/child::*

    This selects all child elements of book nodes. Test automation engineers use these axes to navigate through the XML or HTML document structure, allowing for precise location of elements for interaction and validation.

  • How do you use predicates in XPath Query?

    Predicates in XPath are used within square brackets to filter nodes by specific criteria. They refine the selection by providing additional conditions that the nodes must satisfy to be selected.

    For example, to select the third book element in a document:

    //book[3]

    You can also use predicates to filter nodes based on child node values or attributes. To select book elements with a category attribute of fiction:

    //book[@category='fiction']

    Predicates can contain functions. To select book elements with more than one author child:

    //book[count(author) > 1]

    Logical operators can be used to combine multiple conditions. To select book elements that are in the fiction category and have a price less than 10:

    //book[@category='fiction' and price<10]

    Predicates can also be nested. To select the name of the first author of all book elements:

    //book/author[1]/name

    Using predicates effectively can lead to more precise and efficient XPath queries, which is crucial in test automation for locating elements accurately and performing actions or validations on them.

  • What are XPath functions and how are they used in queries?

    XPath functions are operations that can be used within XPath expressions to perform various tasks on nodes or node-sets, strings, numbers, and booleans. They are integral to refining XPath queries and can be categorized into:

    • Node-set functions: Operate on node-sets, e.g., count(), position().
    • String functions: Manipulate strings, e.g., concat(), contains(), substring().
    • Boolean functions: Handle logical operations, e.g., not(), true(), false().
    • Number functions: Perform numerical operations, e.g., sum(), floor(), round().

    In test automation, functions are used to enhance the selection of nodes. For example, to find an element with a specific attribute value, you might use:

    //input[contains(@id, 'username')]

    Here, contains() is a string function that checks if the id attribute includes the substring 'username'.

    To select a list of elements and then find the third one in that list, you could use:

    (//div[@class='item'])[position()=3]

    In this case, position() is a node-set function that retrieves the index of a node in its context.

    Functions can be nested and combined to create complex queries. For instance, to select a checkbox that is not checked:

    //input[@type='checkbox' and not(@checked)]

    The not() function inverts the boolean result of the @checked predicate.

    Using functions correctly can greatly increase the precision and efficiency of your XPath queries in test automation scripts.

Application and Usage

  • How do you use XPath Query in Selenium for web automation testing?

    Using XPath in Selenium for web automation testing involves locating elements on a web page by their XML path. Here's a concise guide on how to implement this:

    1. Import the necessary Selenium WebDriver classes in your test script:
    import org.openqa.selenium.By;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.WebElement;
    1. Instantiate the WebDriver and navigate to the desired URL:
    WebDriver driver = new ChromeDriver();
    driver.get("http://example.com");
    1. Locate elements using the driver.findElement() method combined with By.xpath():
    WebElement element = driver.findElement(By.xpath("//tagname[@attribute='value']"));

    Replace tagname, attribute, and value with the appropriate HTML element tag, attribute name, and attribute value you wish to locate.

    1. Interact with the located element, for example, by clicking a button or retrieving its text:
    element.click();
    String text = element.getText();
    1. Chain XPath functions and predicates to refine your selection when dealing with complex HTML structures.

    2. Close the browser once your test is complete:

    driver.quit();

    Remember to handle exceptions such as NoSuchElementException to make your tests robust. Use explicit waits to ensure elements are present and interactable before attempting actions on them.

    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    WebElement dynamicElement = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//tagname[@attribute='value']")));

    By following these steps, you can effectively utilize XPath in Selenium to target and manipulate web elements for your automation testing needs.

  • What are some common use cases for XPath Query in software automation?

    XPath Query is commonly used in software test automation for the following use cases:

    • Locating Elements: Automators use XPath to pinpoint specific elements within a web page or XML document that need interaction or verification. For example, clicking a button, checking a checkbox, or validating the presence of a node.
    driver.findElement(By.xpath("//button[text()='Submit']")).click();
    • Dynamic Element Identification: When elements have dynamic IDs or classes, XPath can locate these elements using partial matches or other attributes.
    driver.findElement(By.xpath("//div[contains(@class,'dynamic-class')]"));
    • Complex DOM Traversal: XPath excels in navigating complex Document Object Models (DOM) by using axes and predicates to traverse parent, child, or sibling nodes.
    driver.findElement(By.xpath("//table[@id='data']/tbody/tr[3]/td[2]"));
    • Handling Web Tables: XPath queries can iterate through rows and columns of web tables to extract or interact with data.
    driver.findElement(By.xpath("//table[@id='data']/tbody/tr[*]/td[1]"));
    • Customized Searches: XPath's functions allow for customized searches, such as selecting elements with a specific text, attribute value, or following a particular pattern.
    driver.findElement(By.xpath("//p[starts-with(@id,'message')]"));
    • XML Data Extraction: In non-web contexts, XPath is used to extract information from XML files, which is useful for configuration, data-driven testing, or validating API responses.
    Document doc = builder.parse(new File("config.xml"));
    XPathExpression expr = xpath.compile("//settings/timeout");
    • Conditional Element Selection: XPath's ability to use conditions within predicates enables testers to select elements based on complex criteria.
    driver.findElement(By.xpath("//input[@type='checkbox' and not(@disabled)]"));

    These use cases demonstrate XPath's versatility in addressing various scenarios encountered in software test automation.

  • How can XPath Query be used to navigate XML documents?

    XPath Query can be utilized to navigate XML documents by providing a way to select and traverse nodes in the document tree. It allows for pinpointing specific elements, attributes, or text within the XML structure, enabling precise data extraction or manipulation.

    For example, to select all book elements within a library element, you would use:

    /library/book

    To further refine the selection to books with a specific author attribute, you would add a predicate:

    /library/book[@author='John Doe']

    Navigating to a child node is straightforward; if you need to select the title of each book, the query would be:

    /library/book/title

    For relative navigation, XPath provides axes such as ancestor, descendant, following, and preceding. To select all book elements that follow a book with a specific id, you might use:

    //book[@id='123']/following-sibling::book

    XPath also allows for selecting nodes based on their position. To get the first book in the library:

    /library/book[1]

    Or to select all book elements except the first:

    /library/book[position()>1]

    Using XPath in test automation, engineers can assert the presence, value, and structure of XML responses or configurations, ensuring that the software behaves as expected when interacting with XML-based data.

  • What are some challenges in using XPath Query and how can they be overcome?

    XPath queries can present several challenges in test automation:

    • Performance Issues: Complex XPath expressions can be slow, particularly with large documents. To overcome this, use more specific paths and avoid wildcards. Optimize by targeting elements with unique attributes.

    • Maintainability: XPaths can be brittle, breaking with UI changes. Use stable identifiers like id or name when possible. Employing CSS selectors where appropriate can enhance maintainability.

    • Dynamic Content: Pages with dynamic content can render XPath ineffective. Utilize functions like contains(), starts-with(), or text() to match dynamic text patterns. For dynamic IDs, partial matches with these functions can help.

    • Complexity: Writing complex XPaths can be error-prone. Break down complex queries into simpler, composable parts. Test and validate each part before combining them.

    • Namespace Handling: XML namespaces can complicate XPath queries. Use local-name() and namespace-uri() functions to handle namespaces or register namespace prefixes in your XPath engine.

    • Cross-Browser Compatibility: Different browsers may interpret XPath slightly differently. Ensure cross-browser compatibility by testing your XPaths across browsers and using tools like Selenium that abstract away some of the differences.

    • Learning Curve: XPath's flexibility and power come with complexity. Invest time in learning and practice. Use tools like XPath helper extensions to build and test queries.

    Here's an example of optimizing an XPath for better performance:

    //div[@id='content']/table//tr[td/text()='Specific Text']

    This can be optimized by avoiding the // operator if the structure is known:

    //div[@id='content']/table/tbody/tr[td='Specific Text']

    By addressing these challenges with strategic approaches, XPath can be a robust tool for locating elements in test automation.

  • How can XPath Query be used to extract data from HTML?

    XPath Query can be utilized to extract data from HTML by targeting specific elements, attributes, or text within the HTML DOM structure. Given that HTML is structurally similar to XML, XPath can be effectively applied to traverse the HTML tree and select nodes of interest.

    To extract data:

    1. Identify the HTML element containing the desired data.
    2. Construct an XPath expression that uniquely locates this element within the DOM.
    3. Execute the XPath query using a tool or library that supports XPath, such as Selenium or lxml in Python.

    For example, to extract the text from a paragraph with a specific id, you might use:

    //p[@id='unique-paragraph-id']/text()

    To retrieve an attribute value, such as the href from an anchor tag:

    //a[@class='link-class']/@href

    In test automation frameworks like Selenium, you can use these XPath expressions with methods like find_element_by_xpath() to interact with the web elements:

    WebElement element = driver.findElement(By.xpath("//p[@id='unique-paragraph-id']"));
    String text = element.getText();

    Remember to ensure that your XPath queries are precise and efficient to avoid performance issues and to target elements unambiguously. Use relative paths and predicates to narrow down selections and avoid overly complex expressions that can be brittle and hard to maintain.

Advanced Concepts

  • What are some advanced XPath functions and how are they used?

    XPath offers a variety of advanced functions that can be utilized to perform complex queries and manipulations within XML and HTML documents. Here are some examples:

    • normalize-space(): Strips leading and trailing whitespaces and replaces sequences of whitespace characters with a single space. Useful for cleaning up text nodes.

      //div[normalize-space(text()) = 'Some text']
    • contains(): Checks if the first argument string contains the second argument string.

      //div[contains(@class, 'partial-class-name')]
    • starts-with(): Determines if the first argument string starts with the second argument string.

      //div[starts-with(@id, 'prefix')]
    • substring(): Returns a part of the given string, starting at a specified position.

      //div[substring(@id, 1, 4) = 'item']
    • string-length(): Returns the length of the given string.

      //div[string-length(text()) > 10]
    • sum(): Calculates the sum of a sequence of numbers.

      sum(//input[@type='number']/@value)
    • floor(), ceiling(), and round(): Perform mathematical rounding operations on numbers.

      //div[number() > floor(1.5)]
    • translate(): Replaces characters in a string with characters in a corresponding string.

      //div[translate(text(), 'abc', 'ABC') = 'ABCText']
    • not(): Returns the boolean negation of the argument.

      //input[not(@disabled)]

    These functions enhance the ability to perform text manipulation, string comparisons, and mathematical calculations directly within XPath queries, making them powerful tools in the arsenal of test automation engineers.

  • How can XPath Query be used with namespaces in XML?

    When dealing with XML documents that utilize namespaces, XPath queries must be adjusted to correctly reference the elements within these namespaces. To do this, you must register the namespaces and use a prefix when writing your XPath expressions.

    Here's a brief guide on how to handle namespaces in XPath queries:

    1. Register the namespace: Before executing an XPath query, register the namespace with a prefix using the API provided by your XML parsing library. For example, in Java's XPath API, you can use a NamespaceContext to map prefixes to namespace URIs.

    2. Use the prefix in your XPath query: Once registered, use the prefix in your XPath expressions to reference elements in the namespace.

    <!-- Example XML with namespaces -->
    <root xmlns:ns="http://example.com/ns">
      <ns:child>Content</ns:child>
    </root>
    // Example of registering a namespace in Java
    XPath xpath = XPathFactory.newInstance().newXPath();
    xpath.setNamespaceContext(new NamespaceContextMap("ns", "http://example.com/ns"));
    1. Write the XPath expression: With the namespace registered, you can now write the XPath expression using the prefix.
    // Example of an XPath query with a namespace prefix
    String expression = "/root/ns:child";
    Node childNode = (Node) xpath.evaluate(expression, document, XPathConstants.NODE);

    Remember, the choice of prefix is arbitrary and does not have to match the prefix used in the XML document; it just needs to be consistent within your XPath query and namespace registration.

  • What is XPath Injection and how can it be prevented?

    XPath Injection is a form of attack that targets web applications that construct XPath queries from user-supplied input. Attackers manipulate these queries to gain unauthorized access to data or bypass authentication.

    Prevention involves validating and sanitizing input, using parameterized queries, and adopting a least privilege approach:

    • Input Validation: Ensure input conforms to expected formats using regular expressions or validation libraries.

    • Sanitize Input: Remove or encode potentially dangerous characters before including them in XPath queries.

    • Parameterized Queries: Use APIs that support parameterization, which separates the query structure from input values.

      // Example using a safe parameterized API
      XPathExpression expr = xpath.compile("/users/user[@name=$username]");
      expr.setParameter("username", userInput);
    • Least Privilege: Restrict XML data access rights to the minimum necessary for the application's functionality.

    • Security Libraries: Utilize libraries that provide secure methods for creating XPath queries.

    • Error Handling: Implement secure error handling that does not expose sensitive information, even when an XPath Injection attempt is detected.

    By combining these strategies, you can significantly reduce the risk of XPath Injection vulnerabilities in your software test automation.

  • What are some best practices for writing efficient XPath Queries?

    To write efficient XPath queries, follow these best practices:

    • Use specific paths: Prefer to use direct paths rather than // which searches the entire document. For example, use /html/body/div instead of //div.

    • Leverage IDs and classes: When available, use @id and @class attributes as they are typically unique and make your XPath more efficient. For instance, //*[@id='submit-button'].

    • Avoid using indexes: Indexes like /div[2] make your XPath brittle. Instead, find a unique attribute or path.

    • Minimize the use of wildcard *: Wildcards can slow down queries as they match any element. Be as specific as possible.

    • Use contains() wisely: The contains() function is helpful but can be overused. Use it when the attribute value is dynamic, e.g., contains(@class, 'partial-class-name').

    • Opt for text() when unique: If the text is unique, use it to identify the element, e.g., //a[text()='Click here'].

    • Keep it readable: While efficiency is key, ensure your XPath is still readable for maintenance purposes.

    • Use starts-with() or ends-with(): If you have dynamic content that has a consistent start or end, use these functions for better matching.

    • Cache results if reused: If you're using the same XPath in a loop or repeatedly, store the result in a variable.

    • Test your XPath: Use tools like browser developer tools to test the efficiency and correctness of your XPath before implementing it in your automation scripts.

    Here's an example of a well-structured XPath:

    /html/body//div[@class='content-wrapper']//button[@id='submit-button']

    This query is direct, uses specific attributes, and avoids unnecessary wildcards and indexes.

  • How can XPath Query be used in conjunction with other querying languages like SQL?

    XPath Query can be integrated with SQL when dealing with XML data types in databases that support XML querying and manipulation. This integration allows for the extraction and manipulation of XML data stored within SQL databases.

    For instance, in Microsoft SQL Server, you can use the nodes() method to shred XML data into relational rows and columns, and then apply XPath expressions to target specific elements or attributes. Here's an example of how you might combine XPath with SQL:

    SELECT 
        Tbl.Col.query('XPath_Expression') as Result
    FROM 
        YourTable as Tbl
    CROSS APPLY 
        Tbl.XmlColumn.nodes('XPath_Node_Selection') as T(XCol)

    In this SQL query, XPath_Expression is where you would place your XPath query to filter or select specific XML data, and XPath_Node_Selection is the XPath expression to identify the nodes that will be represented as rows.

    By leveraging XPath within SQL queries, you can perform complex queries that involve both relational and hierarchical data structures, providing a powerful tool for scenarios where XML data needs to be queried in conjunction with traditional SQL queries. This is particularly useful in scenarios like reporting, data migration, or integration tasks where XML data is stored in SQL databases.

TwitterGitHubLinkedIn
AboutQuestionsDiscord ForumBrowser ExtensionTagsQA Jobs

Rayrun is a community for QA engineers. I am constantly looking for new ways to add value to people learning Playwright and other browser automation frameworks. If you have feedback, email luc@ray.run.