munotes®

Practical 9: Identifying and Counting the Objects on a Page

Get access to whole semester resourcesSemester Pass

Chapter Twelve

Syllabus topic Module 1, "Object Identification and Counting on Web Page", "Tool: Selenium WebDriver", "Write a program to identify and count the total number of objects present on a web page including links, images, buttons, and input elements. Display categorized counts."

Pages 82 to 85 of 162

Aim

To identify and count the objects on a web page, links, images, buttons and input elements, and to display the counts by category.

What you need to know before you start

The exercise sounds like counting and is really about definitions. "How many buttons are on this page?" has more than one right answer, depending on what you mean by a button, and a program only counts what its locator describes. A good answer to this practical states each definition and shows how the count changes with it.

The questions that change the counts:

  • Is an a tag with no href a link? It looks like a tag for a link, but it goes nowhere, and a browser does not treat it as a link.
  • Is a hidden element "present"? It is in the page's HTML, but no user can see it or click it.
  • Is <input type="submit"> a button or an input? It is an input element that behaves as a button.
  • Is <input type="hidden"> an input? It is an input element that holds data and shows nothing.
  • Is an image inside a link a link, an image, or both? Both: it is two elements.

A CSS attribute selector writes such definitions exactly. a[href] means "a elements that have an href attribute". input[type=submit] means "inputs whose type is submit". :not(...) excludes a match. Every count in this chapter is one selector.

The page under test

practice/objects.php is a complete page on its own, with no shared header, so that everything counted is visible in one listing:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Objects - Practice Portal</title>
<link rel="stylesheet" href="assets/site.css">
</head>
<body>
<main>
<h1>Objects on a Page</h1>
<p>
  <a href="index.php">Home</a>
  <a href="about.php">About</a>
  <a href="login.php">Login</a>
  <a href="mailto:office@example.com">Email the office</a>
  <a href="about.php"><img src="assets/logo.png" alt="Portal logo"></a>
  <a href="results.php" class="hidden">Results</a>
  <a id="notes">Notes (an anchor with no address)</a>
</p>
<h2>Gallery</h2>
<img src="assets/campus.png" alt="Campus">
<img src="assets/library.png" alt="Library">
<img src="assets/lab.png" alt="Laboratory">
<h2>Search</h2>
<form>
  <input type="text" name="q" placeholder="Search">
  <input type="email" name="email" placeholder="Email">
  <input type="password" name="pin" placeholder="PIN">
  <input type="hidden" name="source" value="objects">
  <label><input type="checkbox" name="exact"> Exact match</label>
  <label><input type="radio" name="scope" value="all" checked> All</label>
  <label><input type="radio" name="scope" value="titles"> Titles only</label>
  <select name="dept">
    <option>All departments</option>
    <option>Computer Science</option>
  </select>
  <textarea name="notes" rows="2"></textarea>
  <button type="submit">Search</button>
  <button type="button">Print</button>
  <input type="submit" value="Go">
  <input type="button" value="Clear">
  <input type="reset" value="Reset">
</form>
</main>
</body>
</html>

The four pictures, logo.png, campus.png, library.png and lab.png in practice/assets, can be any small images: rename four pictures you already have. None of the counts depends on what the pictures show, and even a missing picture is still an img element in the page.

The expected counts, from the source

Counted by hand from the listing above, before running anything:

CategoryDefinitionSelectorCount
Anchor tagsevery a elementa7
Linksa elements with an addressa[href]6
Visible linkslinks a user can seea[href], displayed5
Imagesevery img elementimg4
Button elementsbutton tagsbutton2
Input buttonsinputs of type submit, button or resetinput[type=submit], input[type=button], input[type=reset]3
All buttonsboth of the above5
Input tagsevery input elementinput10
Entry inputsinputs a user types into or choosesinputs, not hidden and not buttons6
Other form fieldsselect and textareaselect, textarea2
munotes.in82

Practical 9: Identifying and Counting the Objects on a Page

Where each number comes from:

  • 7 anchors, 6 links, 5 visible. The a with id="notes" has no href, so it is not a link. The Results link has the class hidden, which the style sheet sets to display: none, so it is a link nobody can see.
  • 4 images. The logo inside the link is an image as well as being inside a link.
  • 5 buttons. Two button tags, and three inputs of type submit, button and reset.
  • 10 inputs, 6 for entry. The ten input tags include the hidden one and the three button types; the six left are text, email, password, the checkbox and the two radios.

The program

Create practicals/CountObjects.java:

package practicals;

import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

public class CountObjects {
    static WebDriver driver;

    static int count(String css) {
        return driver.findElements(By.cssSelector(css)).size();
    }

    static int countVisible(String css) {
        int n = 0;
        for (WebElement e : driver.findElements(By.cssSelector(css))) {
            if (e.isDisplayed()) n++;
        }
        return n;
    }

    public static void main(String[] args) {
        driver = new ChromeDriver();
        try {
            driver.get("http://localhost:8080/objects.php");
            String inputButtons = "input[type=submit], input[type=button], input[type=reset]";
            String entryInputs = "input:not([type=hidden]):not([type=submit]):not([type=button]):not([type=reset])";

            System.out.println("LINKS");
            System.out.println("  anchor tags (a)          " + count("a"));
            System.out.println("  links (a with href)      " + count("a[href]"));
            System.out.println("  visible links            " + countVisible("a[href]"));
            System.out.println("IMAGES");
            System.out.println("  img elements             " + count("img"));
            int loaded = 0;
            for (WebElement img : driver.findElements(By.tagName("img"))) {
                Object width = ((JavascriptExecutor) driver).executeScript("return arguments[0].naturalWidth;", img);
                if (((Number) width).intValue() > 0) loaded++;
            }
            System.out.println("  images that loaded       " + loaded);
            System.out.println("BUTTONS");
            System.out.println("  button elements          " + count("button"));
            System.out.println("  input buttons            " + count(inputButtons));
            System.out.println("  all buttons              " + (count("button") + count(inputButtons)));
            System.out.println("INPUT ELEMENTS");
            System.out.println("  input tags               " + count("input"));
            System.out.println("  entry inputs             " + count(entryInputs));
            System.out.println("  select and textarea      " + count("select, textarea"));

            System.out.println();
            System.out.println("The links, with what each points to:");
            List<WebElement> links = driver.findElements(By.cssSelector("a[href]"));
            for (WebElement a : links) {
                String label = a.isDisplayed() ? a.getText() : "(hidden)";
                if (label.isEmpty()) label = "(image: " + a.findElement(By.tagName("img")).getDomAttribute("alt") + ")";
                System.out.println("  " + label + " -> " + a.getDomAttribute("href"));
            }
        } finally {
            driver.quit();
        }
    }
}
LINKS
  anchor tags (a)          7
  links (a with href)      6
  visible links            5
IMAGES
  img elements             4
  images that loaded       4
BUTTONS
  button elements          2
  input buttons            3
  all buttons              5
INPUT ELEMENTS
  input tags               10
  entry inputs             6
  select and textarea      2

The links, with what each points to:
  Home -> index.php
  About -> about.php
  Login -> login.php
  Email the office -> mailto:office@example.com
  (image: Portal logo) -> about.php
  (hidden) -> results.php
munotes.in83

Practical 9: Identifying and Counting the Objects on a Page

Every count is the one worked out from the source. Three details of the program:

  • findElements is used for every count, never findElement: a category with nothing in it should count 0, not throw an exception.
  • isDisplayed() separates the hidden Results link from the five a user can see. getText() of a hidden element is empty, so the list prints "(hidden)" for it instead.
  • Images that loaded asks the browser for each picture's naturalWidth, its width in the image file itself, through JavascriptExecutor. A picture that failed to load has a natural width of 0. This is how a test finds broken images, which a count of img tags cannot: a broken image is still an img.

Why the selectors, and not the tag names alone

By.tagName("input") returns ten elements, and a program that reports "10 input elements" is right about the tags and wrong about the form, which has six fields a user fills in. By.tagName("button") returns two, and misses the three input buttons a user would also call buttons. The categorised counts MU asks for are only meaningful when the definition is stated, which is why the output labels each count with its definition and the journal should too.

Observations

CategoryExpectedProgram
Anchor tags77
Links66
Visible links55
Images44
All buttons55
Input tags1010
Entry inputs66

Result

The objects on the page were identified and counted by category: 6 links (5 visible, plus 1 anchor with no address), 4 images, all loaded, 5 buttons (2 button elements and 3 input buttons), and 10 input tags of which 6 are entry fields, with 2 more form fields. Every count agreed with the count made by hand from the page's source.

Where marks are lost

One number per category with no definition. "Buttons: 2" is wrong for a user and right for a tag count; say which.

By.tagName("a") for links. It includes the anchor with no address.

Counting hidden elements as visible. Use isDisplayed() when the question is what a user sees.

findElement to count. It throws when there are none.

Forgetting input buttons, or counting them twice, once as buttons and once as inputs, without saying so.

For the journal

Aim; the page under test; the table of definitions and selectors; the expected counts; the program; its output; the observations table; the result.

munotes.in84

Practical 9: Identifying and Counting the Objects on a Page

Quick revision

  • Counting objects is really stating definitions.
  • a counts anchors; a[href] counts links; add isDisplayed() for visible links.
  • Buttons: button tags plus input tags whose type is submit, button or reset.
  • Inputs: input counts every tag; exclude hidden and button types for entry fields.
  • findElements(...).size() counts, and returns 0 when there are none.
  • A broken image is still an img; check naturalWidth to know it loaded.

Questions you must be able to answer

1. Why do a and a[href] give different counts here? One a element has no href, so it is an anchor but not a link.

2. How does the program know the Results link is hidden? isDisplayed() returns false for it, because the page's style sheet hides its class.

3. How many buttons are on the page? Five by what a user sees: two button elements and three inputs of type submit, button and reset. Two if only button tags are counted.

4. Why is By.tagName("input") not the number of form fields? It also counts the hidden input and the three input buttons, which a user does not fill in.

5. How can a test tell that an image failed to load? Its naturalWidth, read through JavascriptExecutor, is 0.

6. Why use findElements for counting? It returns an empty list, size 0, when nothing matches; findElement would throw.

munotes.in85

The rest of this subject

These notes are cut from the University's printed syllabus. Open the syllabus itself for the same subject.

Issue
Done!