munotes®

Practical 1: Creating a Test Suite with Selenium IDE

Get access to whole semester resourcesSemester Pass

Chapter Three

Syllabus topic Module 1, "Creation of Test Suite Using Selenium IDE", "Tool: Selenium IDE (Chrome/Firefox Extension)", "Install Selenium IDE and create a test suite containing a minimum of four test cases to validate different web page formats (HTML page, XML response, JSON API output, and a dynamic form page). Execute the suite and export the automation script in WebDriver format."

Pages 14 to 25 of 162

Aim

To install Selenium IDE, to create a test suite of four test cases that validate four different web page formats (an HTML page, an XML response, a JSON API output and a dynamic form page), to execute the suite, and to export the automation script in WebDriver format.

What you need to know before you start

Selenium IDE is a record-and-playback tool for testing web pages. It runs as an add-on inside the browser. You either record what you do on a page, or type the steps in yourself, and the IDE plays them back and tells you whether the page behaved as expected. No programming is needed, which is why MU puts it first.

The IDE's words, which you will need in the journal:

  • Command. One step: open a page, click something, type into a box, assert that something is true.
  • Target. What the command acts on. For open it is an address; for click it is a locator, a way of finding one element on the page.
  • Value. A second argument when the command needs one: the text to type, or the text an assertion expects.
  • Test case. A named list of commands that checks one thing.
  • Test suite. A named group of test cases that are run together.
  • Project. Everything together, saved as one file whose name ends in .side.

Every command is one row: Command | Target | Value. This book writes each test case the same way, one command a line, so you can type it straight into the IDE.

Locators tell the IDE which element you mean. The ones used in this practical:

LocatorFindsExample
id=the element with that id attributeid=fee
css=the first element a CSS selector matchescss=h1
xpath=the first element an XPath expression matchesone cell of the office-hours table, in the test case below

An id is the best locator when a page has one, because a page should use each id only once.

Assert against verify. Both check something. When an assert fails the test case stops there. When a verify fails, the failure is recorded and the test carries on. The IDE's own description of verify text says exactly that: the test "will continue even if the verify fails".

The four page formats MU names. A web server does not only send web pages. It says what it is sending in a Content-Type header, and the four formats are four answers:

FormatWhat the server sendsContent-Type on the Practice Portal
HTML pagea page for a person to readtext/html
XML responsedata marked up with tags of its ownapplication/xml
JSON API outputdata as JavaScript Object Notation, for programsapplication/json
Dynamic form pagean HTML page whose content changes after it loads, by JavaScripttext/html
munotes.in14

Practical 1: Creating a Test Suite with Selenium IDE

The first is what the IDE was built for. The next two are data, not pages, and the IDE needs a different technique for them, which is the most instructive part of this practical. The fourth changes while you look at it, which is what waits are for.

Installing Selenium IDE: the one fact that decides the browser

MU names Selenium IDE as a "Chrome/Firefox Extension". Only one of those two still exists.

Chrome. Selenium IDE's Chrome extension was built on an old extension format, Manifest V2, which Google has removed from Chrome. Google's own timeline records that from 24 July 2025, with Chrome 138, Manifest V2 extensions were disabled for all users, who "can no longer turn them back on", and that on 31 August 2026 all remaining Manifest V2 extensions were removed from the Chrome Web Store. Users reported the Selenium IDE extension switched off in January 2025, and a Selenium project member answered on the project's own issue tracker: "v4 is an Electron app, it is not a browser extension."

Firefox. The Firefox add-on, version 3.17.4, is still published on Firefox's add-ons site, and it is what this chapter uses. Every step below was done in it.

If your laboratory has only Chrome, the Selenium project's own route is Selenium IDE 4, a separate desktop program that drives Chrome, published on the project's GitHub releases page as version 4.0.1-beta.14. It is marked beta and its installers are not code-signed, so Windows warns before running one. This book's steps and screenshots are for the Firefox add-on.

To install it in Firefox:

  1. Open Firefox and go to addons.mozilla.org.
  2. Search for Selenium IDE and open its page.
  3. Click Add to Firefox. Firefox lists the permissions it asks for; click Add.
  4. A Selenium IDE icon appears among the toolbar icons, or under the jigsaw-piece Extensions button. Pin it to the toolbar so it is always one click away.
  5. Click the icon. The IDE opens in a window of its own.
Selenium IDE's welcome window with four choices

Figure 3.1 Selenium IDE 3.17.4 opening in Firefox, as the lab's own Firefox showed it.

The version number, 3.17.4, is printed in the header. Write it in your journal.

The pages under test

Make sure the Practice Portal is running (php -S localhost:8080 router.php inside practice), then add these four files to it.

The HTML page, practice/about.php:

<?php $title = 'About'; include 'inc/top.php'; ?>
<h1>About the Practice Portal</h1>
<p id="intro">The Practice Portal is a small college website built for testing practice.</p>
<h2>Departments</h2>
<ul id="departments">
  <li>Computer Science</li>
  <li>Information Technology</li>
  <li>Commerce</li>
</ul>
<h2>Office hours</h2>
<table id="hours">
  <tr><th>Day</th><th>Time</th></tr>
  <tr><td>Monday to Friday</td><td>10:00 to 17:00</td></tr>
  <tr><td>Saturday</td><td>10:00 to 13:00</td></tr>
</table>
<?php include 'inc/bottom.php'; ?>
munotes.in15

Practical 1: Creating a Test Suite with Selenium IDE

The XML response, practice/api/notices.php. It sends XML and says so in its Content-Type header:

<?php
// api/notices.php: the college notices, as XML.
header('Content-Type: application/xml; charset=utf-8');
echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
?>
<notices>
  <notice id="1" date="2026-07-01">
    <title>Semester 5 lectures begin</title>
  </notice>
  <notice id="2" date="2026-07-15">
    <title>Journal submission for Practical 1</title>
  </notice>
  <notice id="3" date="2026-08-05">
    <title>Mid-term practical examination timetable</title>
  </notice>
</notices>

The XML declaration is printed with echo rather than written out, because <? at the start of a line means "PHP starts here" to some PHP installations.

The JSON API, practice/api/students.php, with the records it serves in practice/seed/students.json:

<?php
// api/students.php: the student list as JSON. ?roll=103 returns one student.
require __DIR__ . '/../inc/store.php';
header('Content-Type: application/json; charset=utf-8');
$students = load_records('students');

if (isset($_GET['roll'])) {
    foreach ($students as $s) {
        if ($s['roll'] === (int) $_GET['roll']) {
            echo json_encode($s);
            exit;
        }
    }
    http_response_code(404);
    echo json_encode(['error' => 'No student with that roll number']);
    exit;
}
echo json_encode(['count' => count($students), 'students' => $students]);
[
    {"roll": 101, "name": "Aarav Shah", "course": "B.Sc. CS", "city": "Mumbai", "marks": 72},
    {"roll": 102, "name": "Diya Nair", "course": "B.Sc. CS", "city": "Thane", "marks": 65},
    {"roll": 103, "name": "Kabir Khan", "course": "B.Sc. IT", "city": "Pune", "marks": 58},
    {"roll": 104, "name": "Meera Iyer", "course": "B.Sc. CS", "city": "Mumbai", "marks": 81},
    {"roll": 105, "name": "Rohan Patil", "course": "B.Com.", "city": "Nashik", "marks": 49},
    {"roll": 106, "name": "Sara D'Souza", "course": "B.Sc. IT", "city": "Mumbai", "marks": 77},
    {"roll": 107, "name": "Vivaan Joshi", "course": "B.Sc. CS", "city": "Thane", "marks": 90},
    {"roll": 108, "name": "Ananya Rao", "course": "B.Com.", "city": "Pune", "marks": 63},
    {"roll": 109, "name": "Ishaan Gupta", "course": "B.Sc. IT", "city": "Mumbai", "marks": 55},
    {"roll": 110, "name": "Zoya Sheikh", "course": "B.Sc. CS", "city": "Nashik", "marks": 84}
]

The dynamic form, practice/enquiry.php. The Year box is hidden until a course is chosen, the fee appears only then, and the room choice appears only when the hostel box is ticked. None of that is in the page the server sends; JavaScript does it in the browser:

<?php $title = 'Admission Enquiry'; include 'inc/top.php'; ?>
<h1>Admission Enquiry</h1>
<form id="enquiry">
  <label>Full name <input type="text" id="name"></label>
  <label>Email <input type="text" id="email"></label>
  <label>Course
    <select id="course">
      <option value="">-- Select --</option>
      <option>B.Sc. CS</option>
      <option>B.Sc. IT</option>
      <option>B.Com.</option>
    </select>
  </label>
  <p id="fee"></p>
  <label id="yearLabel" class="hidden">Year
    <select id="year">
      <option>FY</option>
      <option>SY</option>
      <option>TY</option>
    </select>
  </label>
  <label><input type="checkbox" id="hostel"> I need a hostel room</label>
  <div id="rooms" class="hidden">
    <label><input type="radio" name="room" id="single" value="Single"> Single room</label>
    <label><input type="radio" name="room" id="shared" value="Shared"> Shared room</label>
  </div>
  <p id="errors" class="error"></p>
  <button type="button" id="submit">Send enquiry</button>
</form>
<p id="confirmation" class="success"></p>
<script>
const fees = { 'B.Sc. CS': 'Rs. 38,000', 'B.Sc. IT': 'Rs. 36,000', 'B.Com.': 'Rs. 24,000' };
const course = document.getElementById('course');
course.addEventListener('change', function () {
  const chosen = course.value !== '';
  document.getElementById('fee').textContent = chosen ? 'Annual fee: ' + fees[course.value] : '';
  document.getElementById('yearLabel').classList.toggle('hidden', !chosen);
});
document.getElementById('hostel').addEventListener('change', function () {
  document.getElementById('rooms').classList.toggle('hidden', !this.checked);
});
document.getElementById('submit').addEventListener('click', function () {
  const name = document.getElementById('name').value.trim();
  const email = document.getElementById('email').value.trim();
  const problems = [];
  if (name === '') problems.push('Please enter your name.');
  if (!/^[^@\s]+@[^@\s]+\.[a-z]{2,}$/i.test(email)) problems.push('Please enter a valid email.');
  if (course.value === '') problems.push('Please choose a course.');
  document.getElementById('errors').textContent = problems.join(' ');
  if (problems.length > 0) return;
  const year = document.getElementById('year').value;
  let text = 'Thank you, ' + name + '. Your enquiry for ' + course.value + ' (' + year + ') has been recorded.';
  const room = document.querySelector('input[name="room"]:checked');
  if (document.getElementById('hostel').checked && room) text += ' Hostel: ' + room.value + ' room.';
  document.getElementById('enquiry').classList.add('hidden');
  document.getElementById('confirmation').textContent = text;
});
</script>
<?php include 'inc/bottom.php'; ?>
munotes.in16

Practical 1: Creating a Test Suite with Selenium IDE

The IDE window

The Selenium IDE window with its parts

Figure 3.2 The IDE with one test case open: the test list on the left, the command table in the middle, the command editor below it and the log at the bottom.

Four areas matter:

  • The left panel lists the project's test cases. Its heading is a menu: Tests, Test suites or Executing, which shows what is running.
  • The toolbar above the table: Run all tests (a triangle with lines), Run current test (a plain triangle), Step over, the speed control, and at the right the red REC button for recording.
  • The playback base URL box, which holds the start of every address. With http://localhost:8080 in it, a test can say open /about.php.
  • The command table and, under it, the Command, Target, Value and Description boxes where the selected row is edited.

At the bottom are two tabs: Log, where a run reports every step, and Reference, which explains the command in the selected row.

Step 1: a project and its base URL

  1. In the welcome window, click Create a new project.
  2. The IDE asks "Name your new project". Type Practical 1 and click OK.
  3. The project opens with one empty test case called Untitled. In the Playback base URL box, type http://localhost:8080.

Step 2: test case 1, the HTML page

Rename Untitled: hover over it in the left panel, click the three-dot button beside it, choose Rename, and call it HTML page. Then click the first empty row of the table and type each command into the Command, Target and Value boxes below it. The IDE suggests command names as you type.

Test: HTML page
open | /about.php
assert title | About - Practice Portal
assert text | css=h1 | About the Practice Portal
assert element present | id=departments
verify text | xpath=//table[@id='hours']//tr[2]/td[2] | 10:00 to 17:00
munotes.in17

Practical 1: Creating a Test Suite with Selenium IDE

Line by line:

  1. open /about.php loads the page. The IDE joins the base URL and the target.
  2. assert title checks the browser's title bar text. The title comes from inc/top.php, which adds " - Practice Portal" to the page's own title.
  3. assert text on css=h1 checks the heading.
  4. assert element present on id=departments checks the departments list exists at all.
  5. verify text reads one cell of the office-hours table: the second row, second column. It is a verify, so if it fails the test still finishes.

Why XPath for the cell: the table cells have no ids, so the locator describes the path to the cell instead. //table[@id='hours'] finds the table, //tr[2] its second row, and /td[2] that row's second cell.

Step 3: test case 2, the XML response

Add a new test case with the + button at the top of the left panel and call it XML response.

The obvious test is wrong, and it is worth seeing why. The obvious test opens the XML address and asserts the text of a notice's title:

Test: XML opened directly
open | /api/notices.php
assert text | xpath=//notice[@id='2']/title | Journal submission for Practical 1
Suite: Direct
XML opened directly

Played in the IDE, the open succeeds and the assertion fails with a message about the page itself, not about the text:

Running 'XML opened directly'
1. open on /api/notices.php OK
2. assertText on xpath=//notice[@id='2']/title with value Journal submission for Practical 1 Failed:
    can't access property "addEventListener", _win is null
'XML opened directly' ended with 1 error(s)

The reason: the IDE works by placing a small program of its own inside each page it tests, and an XML document is not a web page. Firefox shows it as a formatted tree, and there is no page window for the IDE's program to work in. The same is true of JSON, which Firefox shows in a viewer of its own.

The technique that works is to open an ordinary page of the same site and ask the browser to fetch the data, which is exactly what a real web page does. The IDE's execute async script command runs a piece of JavaScript in the page; in the IDE's own words, the script "must return a Promise", and its result "will be saved on the variable if you use the 'return' keyword". The assert command then checks that variable:

Test: XML response
open | /index.php
execute async script | return fetch('/api/notices.php').then(r => r.headers.get('Content-Type')) | type
assert | type | application/xml; charset=utf-8
execute async script | return fetch('/api/notices.php').then(r => r.text()).then(t => new DOMParser().parseFromString(t, 'application/xml').getElementsByTagName('notice').length) | noticeCount
assert | noticeCount | 3
execute async script | return fetch('/api/notices.php').then(r => r.text()).then(t => new DOMParser().parseFromString(t, 'application/xml').querySelector('notice[id="2"] title').textContent) | secondTitle
assert | secondTitle | Journal submission for Practical 1
munotes.in18

Practical 1: Creating a Test Suite with Selenium IDE

Three checks, each on a different property of the response:

  1. The format. The Content-Type header must say application/xml. A server that sent the right text with the wrong header would fail here, and many programs that read XML would refuse it.
  2. The structure. DOMParser turns the text into an XML document, and there must be exactly three notice elements.
  3. The content. The title inside the notice whose id is 2 must be the expected text.

fetch(...) asks the server for the address and returns a Promise; .then(r => r.text()) waits for the body; the arrow functions (r => ...) are JavaScript's short way of writing a small function. You do not need to write JavaScript anywhere else in this paper, and these lines can be copied as they are.

Step 4: test case 3, the JSON API

Add a test case called JSON API. The same technique, with r.json(), which reads the body as JSON and turns it into JavaScript objects:

Test: JSON API
open | /index.php
execute async script | return fetch('/api/students.php').then(r => r.headers.get('Content-Type')) | type
assert | type | application/json; charset=utf-8
execute async script | return fetch('/api/students.php').then(r => r.json()).then(d => d.count) | count
assert | count | 10
execute async script | return fetch('/api/students.php?roll=103').then(r => r.json()).then(s => s.name) | name
assert | name | Kabir Khan

Again three checks: the header says JSON, the count field of the full list is 10, and asking for roll number 103 alone returns the student named Kabir Khan. The IDE's own description of assert says the variable's value "will be converted to a string for comparison", which is why a number, 10, can be compared with the text 10.

Step 5: test case 4, the dynamic form

Add a test case called Dynamic form. This one fills in the enquiry form the way a person would:

Test: Dynamic form
open | /enquiry.php
type | id=name | Priya Sharma
type | id=email | priya@example.com
select | id=course | label=B.Sc. CS
wait for element visible | id=year | 5000
assert text | id=fee | Annual fee: Rs. 38,000
select | id=year | label=TY
click | id=hostel
wait for element visible | id=shared | 5000
click | id=shared
click | id=submit
assert text | id=confirmation | Thank you, Priya Sharma. Your enquiry for B.Sc. CS (TY) has been recorded. Hostel: Shared room.

The two wait for element visible lines are what make this a test of a dynamic page. The Year box does not exist on screen until a course is chosen, and the room choices do not exist until the hostel box is ticked. Each wait holds the test until the element can be seen, for at most the Value, 5000 milliseconds. Without them, a test run at full speed can reach for an element in the moment before the page's JavaScript has shown it.

munotes.in19

Practical 1: Creating a Test Suite with Selenium IDE

select chooses from a dropdown. label=B.Sc. CS picks the option whose visible text is B.Sc. CS.

Step 6: the suite

A test suite is what MU asks for, and four separate test cases are not yet one.

  1. Open the left panel's heading menu and choose Test suites. The IDE already shows one called Default Suite.
  2. Click + and name the new suite Page formats.
  3. Hover over the suite, click its three-dot button, and choose Add tests.
  4. Tick the four test cases and click Select.
Suite: Page formats
HTML page
XML response
JSON API
Dynamic form
The suite's menu: Add tests, Rename, Delete, Settings and Export

Figure 3.3 Each suite has its own menu; Add tests is how test cases are put into it.

The suite's Settings hold its timeout, and whether its tests run in parallel or share one browser session. Leave them as they are for this practical.

Step 7: execute the suite

Click the arrow beside the suite to open it, click the first test case inside it, then click Run all tests in suite (the triangle with lines).

If you click Run before selecting a test case inside the suite, the IDE answers with a message instead of running: "To play a suite you must select a test case from within that suite." That message is where a lot of laboratory time goes.

The IDE opens a new Firefox window, plays each test case in it, and writes every step into the Log tab. This is the whole log of the suite, as the IDE printed it (the IDE also shows the time of day beside each line):

Running 'HTML page'
1. open on /about.php OK
2. assertTitle on About - Practice Portal OK
3. assertText on css=h1 with value About the Practice Portal OK
4. assertElementPresent on id=departments OK
5. verifyText on xpath=//table[@id='hours']//tr[2]/td[2] with value 10:00 to 17:00 OK
'HTML page' completed successfully
Running 'XML response'
1. open on /index.php OK
2. executeAsyncScript on return fetch('/api/notices.php').then(r => r.headers.get('Content-Type')) with value type OK
3. assert on type with value application/xml; charset=utf-8 OK
4. executeAsyncScript on return fetch('/api/notices.php').then(r => r.text()).then(t => new DOMParser().parseFromString(t, 'application/xml').getElementsByTagName('notice').length) with value noticeCount OK
5. assert on noticeCount with value 3 OK
6. executeAsyncScript on return fetch('/api/notices.php').then(r => r.text()).then(t => new DOMParser().parseFromString(t, 'application/xml').querySelector('notice[id="2"] title').textContent) with value secondTitle OK
7. assert on secondTitle with value Journal submission for Practical 1 OK
'XML response' completed successfully
Running 'JSON API'
1. open on /index.php OK
2. executeAsyncScript on return fetch('/api/students.php').then(r => r.headers.get('Content-Type')) with value type OK
3. assert on type with value application/json; charset=utf-8 OK
4. executeAsyncScript on return fetch('/api/students.php').then(r => r.json()).then(d => d.count) with value count OK
5. assert on count with value 10 OK
6. executeAsyncScript on return fetch('/api/students.php?roll=103').then(r => r.json()).then(s => s.name) with value name OK
7. assert on name with value Kabir Khan OK
'JSON API' completed successfully
Running 'Dynamic form'
1. open on /enquiry.php OK
2. type on id=name with value Priya Sharma OK
3. type on id=email with value priya@example.com OK
4. select on id=course with value label=B.Sc. CS OK
5. waitForElementVisible on id=year with value 5000 OK
6. assertText on id=fee with value Annual fee: Rs. 38,000 OK
7. select on id=year with value label=TY OK
8. click on id=hostel OK
9. waitForElementVisible on id=shared with value 5000 OK
10. click on id=shared OK
11. click on id=submit OK
12. assertText on id=confirmation with value Thank you, Priya Sharma. Your enquiry for B.Sc. CS (TY) has been recorded. Hostel: Shared room. OK
'Dynamic form' completed successfully
munotes.in20

Practical 1: Creating a Test Suite with Selenium IDE

Read it the way an examiner will. Each test case starts with a Running line and ends with completed successfully; each numbered line is one command, with the target and value it was given, and OK means it passed. The command names in the log are the IDE's internal ones, assertTitle for "assert title" and so on.

The IDE after the suite has run

Figure 3.4 After the run: every test case in the suite ticked green, and the end of the log below it.

Step 8: save the project

Click the Save project button at the top right (or press Ctrl+S). Firefox asks where to save; save it as practical-1.side in your practical folder. The .side file is plain text in JSON, and holds the project's name, its base URL, every test case with every command, and every suite. It is also what the command-line runner in Practical 2 plays.

Step 9: export the automation script in WebDriver format

MU's last instruction is to "export the automation script in WebDriver format". WebDriver is Selenium's programming interface, the one every later practical uses from Java; "WebDriver format" means code that does through WebDriver what the IDE did.

  1. In the Test suites view, open the suite's three-dot menu and choose Export.
  2. The IDE asks you to "Select language". It offers C# NUnit, C# xUnit, Java JUnit, JavaScript Mocha, Python pytest and Ruby RSpec. Choose Java JUnit.
  3. Leave the three boxes below unticked (origin tracing comments, step descriptions as comments, and Selenium Grid).
  4. Click Export, and save the file.
The Export dialog with its six languages and three options

Figure 3.5 Java JUnit is the one this book uses: every later practical is in Java.

This is the file the IDE wrote, exactly:

munotes.in21

Practical 1: Creating a Test Suite with Selenium IDE

// Generated by Selenium IDE
import org.junit.Test;
import org.junit.Before;
import org.junit.After;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.core.IsNot.not;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Alert;
import org.openqa.selenium.Keys;
import java.util.*;
import java.net.MalformedURLException;
import java.net.URL;
public class PageformatsTest {
  private WebDriver driver;
  private Map<String, Object> vars;
  JavascriptExecutor js;
  @Before
  public void setUp() {
    driver = new FirefoxDriver();
    js = (JavascriptExecutor) driver;
    vars = new HashMap<String, Object>();
  }
  @After
  public void tearDown() {
    driver.quit();
  }
  @Test
  public void hTMLpage() {
    driver.get("http://localhost:8080/about.php");
    assertThat(driver.getTitle(), is("About - Practice Portal"));
    assertThat(driver.findElement(By.cssSelector("h1")).getText(), is("About the Practice Portal"));
    {
      List<WebElement> elements = driver.findElements(By.id("departments"));
      assert(elements.size() > 0);
    }
    assertThat(driver.findElement(By.xpath("//table[@id=\'hours\']//tr[2]/td[2]")).getText(), is("10:00 to 17:00"));
  }
  @Test
  public void xMLresponse() {
    driver.get("http://localhost:8080/index.php");
    vars.put("type", js.executeAsyncScript("var callback = arguments[arguments.length - 1];return fetch(\'/api/notices.php\').then(r => r.headers.get(\'Content-Type\')).then(callback).catch(callback);"));
    assertEquals(vars.get("type").toString(), "application/xml; charset=utf-8");
    vars.put("noticeCount", js.executeAsyncScript("var callback = arguments[arguments.length - 1];return fetch(\'/api/notices.php\').then(r => r.text()).then(t => new DOMParser().parseFromString(t, \'application/xml\').getElementsByTagName(\'notice\').length).then(callback).catch(callback);"));
    assertEquals(vars.get("noticeCount").toString(), "3");
    vars.put("secondTitle", js.executeAsyncScript("var callback = arguments[arguments.length - 1];return fetch(\'/api/notices.php\').then(r => r.text()).then(t => new DOMParser().parseFromString(t, \'application/xml\').querySelector(\'notice[id=\"2\"] title\').textContent).then(callback).catch(callback);"));
    assertEquals(vars.get("secondTitle").toString(), "Journal submission for Practical 1");
  }
  @Test
  public void jSONAPI() {
    driver.get("http://localhost:8080/index.php");
    vars.put("type", js.executeAsyncScript("var callback = arguments[arguments.length - 1];return fetch(\'/api/students.php\').then(r => r.headers.get(\'Content-Type\')).then(callback).catch(callback);"));
    assertEquals(vars.get("type").toString(), "application/json; charset=utf-8");
    vars.put("count", js.executeAsyncScript("var callback = arguments[arguments.length - 1];return fetch(\'/api/students.php\').then(r => r.json()).then(d => d.count).then(callback).catch(callback);"));
    assertEquals(vars.get("count").toString(), "10");
    vars.put("name", js.executeAsyncScript("var callback = arguments[arguments.length - 1];return fetch(\'/api/students.php?roll=103\').then(r => r.json()).then(s => s.name).then(callback).catch(callback);"));
    assertEquals(vars.get("name").toString(), "Kabir Khan");
  }
  @Test
  public void dynamicform() {
    driver.get("http://localhost:8080/enquiry.php");
    driver.findElement(By.id("name")).sendKeys("Priya Sharma");
    driver.findElement(By.id("email")).sendKeys("priya@example.com");
    {
      WebElement dropdown = driver.findElement(By.id("course"));
      dropdown.findElement(By.xpath("//option[. = 'B.Sc. CS']")).click();
    }
    {
      WebDriverWait wait = new WebDriverWait(driver, 5);
      wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("year")));
    }
    assertThat(driver.findElement(By.id("fee")).getText(), is("Annual fee: Rs. 38,000"));
    {
      WebElement dropdown = driver.findElement(By.id("year"));
      dropdown.findElement(By.xpath("//option[. = 'TY']")).click();
    }
    driver.findElement(By.id("hostel")).click();
    {
      WebDriverWait wait = new WebDriverWait(driver, 5);
      wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("shared")));
    }
    driver.findElement(By.id("shared")).click();
    driver.findElement(By.id("submit")).click();
    assertThat(driver.findElement(By.id("confirmation")).getText(), is("Thank you, Priya Sharma. Your enquiry for B.Sc. CS (TY) has been recorded. Hostel: Shared room."));
  }
}

How to read it:

  • It is a JUnit test class. JUnit is a Java testing framework; @Before runs before each test, @Test marks a test, @After runs after it.
  • setUp() starts Firefox with new FirefoxDriver(), because the IDE was running in Firefox. An export made from IDE 4 in Chrome says ChromeDriver instead.
  • Each test case became one @Test method. The IDE built the Java names from the test names: "HTML page" became the method hTMLpage and the suite "Page formats" became the class PageformatsTest. Name your tests in plain words and the Java names follow.
  • open became driver.get(...) with the base URL joined on; assert title became assertThat(driver.getTitle(), is(...)); type became sendKeys; execute async script became js.executeAsyncScript(...), with the IDE adding the callback that plays the Promise's role in Java.
  • assert element present became a block ending in assert(elements.size() > 0);. That is Java's own assert statement, and Java ignores it unless assertions are switched on when the program is started.
munotes.in22

Practical 1: Creating a Test Suite with Selenium IDE

Before you try to run this file, read chapter six. The export was written for Selenium 3, and two of its lines use a form of WebDriverWait that Selenium 4 no longer has; compiled against today's Selenium they are errors. Chapter six sets up Java and Maven, compiles this very file, shows both errors, and fixes them.

Recording instead of typing

Everything above can also be recorded. Click REC, give the base URL when asked, and the IDE opens a browser window and writes a command for every click and every piece of typing you do in it. Click the red button again to stop. Assertions are added afterwards, by typing them in or by right-clicking an element in the recorded page and choosing a Selenium IDE assertion.

Recording is quick, but it records exactly what you did, including every misclick, and it chooses its own locators. For a practical that has to be explained in the journal, typing the commands is clearer, which is why this chapter types them.

Observations

Test casePage formatCommandsChecks madeResult
HTML pageHTML5title, heading, element present, table cellpassed
XML responseXML7Content-Type, number of notices, one titlepassed
JSON APIJSON7Content-Type, record count, one recordpassed
Dynamic formdynamic HTML12fee appears, fields appear, confirmation textpassed

Opening the XML address directly and asserting on it failed with the IDE's own error message, which is why the XML and JSON tests fetch their data from an ordinary page.

Result

A Selenium IDE 3.17.4 project with four test cases, one for each page format MU names, was created and grouped into the suite Page formats. The suite was executed and all four test cases passed. The suite was exported in WebDriver format as a Java JUnit class.

Where marks are lost

Trying to install the Chrome extension. It is switched off in Chrome and gone from the store. Use Firefox, or Selenium IDE 4 on a Chrome-only machine.

Asserting on an XML or JSON page directly. It fails with an error about the page, not the data. Fetch the data from an ordinary page and assert on the result.

Running a suite with no test selected. Select a test case inside the suite first.

No base URL. A test that says open /about.php needs the base URL to know which site.

Leaving out the waits on the dynamic form. The test may pass once and fail the next time.

Writing only the commands. The journal needs the log too: it is the proof the suite was executed.

munotes.in23

Practical 1: Creating a Test Suite with Selenium IDE

Exporting and stopping. Name the language you exported to, and keep the exported file; chapter six runs it.

For the journal

Aim; tool and version (Selenium IDE 3.17.4 in Firefox); the four pages under test and their formats; the four test cases as command tables; the suite and its members; the log of the run; the observations table; the exported Java file; the result.

Quick revision

  • Selenium IDE: record and playback in the browser. Command, Target, Value.
  • Test case: named list of commands. Suite: named group of test cases. Project: the .side file.
  • Chrome disabled Manifest V2 extensions from Chrome 138 (24 July 2025); the IDE's Chrome extension is gone. Firefox add-on 3.17.4 still installs.
  • Base URL plus open /about.php gives the full address.
  • Assert stops the test on failure; verify records it and carries on.
  • XML and JSON: open an ordinary page, execute async script with fetch, then assert the stored variable.
  • Dynamic pages: wait for element visible before touching what appears later.
  • Run a suite: select a test inside it, then Run all tests in suite.
  • Export: suite menu, Export, Java JUnit. The export was written for Selenium 3.

Questions you must be able to answer

1. What are the three parts of a Selenium IDE command? The command itself, the target it acts on, and a value when it needs one, such as the text to type or the text expected.

2. What is the difference between a test case and a test suite? A test case is one named list of commands that checks one thing. A suite is a named group of test cases run together.

3. Why does this chapter use Firefox and not Chrome? Selenium IDE's Chrome extension was built on Manifest V2, which Chrome disabled for all users from Chrome 138 in July 2025. The Firefox add-on still installs.

4. What is the difference between assert text and verify text? If assert text fails, the test stops. If verify text fails, the failure is recorded and the test continues.

5. Why not open the XML address and assert on it directly? Because the IDE cannot work inside an XML document; the attempt fails with an error about the page. Fetching the XML from an ordinary page of the same site and checking the result works.

6. What does execute async script do with return? It runs the JavaScript in the page, waits for the Promise it returns, and saves the result in the variable named in the Value.

7. What would happen without the wait for element visible lines? The test could try to use the Year box or the room choice before the page's JavaScript had shown them, and fail on some runs and not others.

munotes.in24

Practical 1: Creating a Test Suite with Selenium IDE

8. What does "export in WebDriver format" produce here? A Java JUnit class in which every test case is a @Test method that does the same steps through Selenium WebDriver.

9. The exported Java does not compile with Selenium 4. Why? It uses new WebDriverWait(driver, 5), the Selenium 3 form with a number of seconds. Selenium 4 takes a Duration instead.

munotes.in25

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!