Checkpoint Lab — Selenium IDE, Record/Playback, and Migration to Maintainable Code
Complete the chapter by producing both a disposable Selenium IDE learning artifact and a maintainable WebDriver test, proving the migration with a controlled markup break and an auditable evidence packet.
Learning objectives
- Record and inspect one local IDE flow without real credentials or production targets.
- Predict and verify a controlled locator failure caused by v1→v2 markup.
- Repair the learning artifact and migrate to maintainable Python WebDriver.
- Compare IDE and WebDriver responsibilities using observable evidence.
- Clean all disposable state and define what artifact is retained.
1. Checkpoint contract and preflight
Use only http://127.0.0.1:8826. Required baseline:
Python 3.10+, selenium==4.47.0 for the migrated test, a
supported local Chromium-family browser, Selenium Manager, and the
currently installed Selenium IDE build. Grid is not required. Paid
browser clouds and enterprise identity are outside the mandatory
path.
Preflight checks:
- verify
/healthreports v1/v2; - record the IDE build and Selenium/browser versions separately;
- confirm the target is loopback and contains only synthetic data;
- create a disposable working/evidence directory;
- confirm no personal browser profile is selected.
2. Predict before execution
Write at least these predictions before touching v2:
-
DOM: the Save button generated-looking ID will
change between v1 and v2 while
data-testid=save-profileremains; -
recording: a copy using
id=save-profile-427will fail at the click on v2; - browser/session: the migrated test will create a fresh WebDriver session/profile and dispose it afterward;
- evidence: the first failed locator and repaired selector will be preserved as different records rather than overwritten.
3. Execute: record, inspect, and retain one learning artifact
Start the fixture, record the v1 flow, stop recording immediately, and inspect all commands. Save the project only inside the disposable checkpoint workspace. Do not commit it yet.
Create a small review table with each command, target, value
sensitivity, state changed/read, and whether the target is approved
for migration. If your IDE picked a stable locator, create a
copy of the learning test that uses
id=save-profile-427 so the failure injection remains
deterministic.
{
"id": "academy-ide-migration",
"version": "2.0",
"name": "IDE Migration Learning Artifact",
"url": "http://127.0.0.1:8826",
"tests": [{
"id": "profile-flow",
"name": "save profile v1",
"commands": [
{"command": "open", "target": "/v1", "value": ""},
{"command": "type", "target": "id=display-name", "value": "Ada"},
{"command": "click", "target": "id=save-profile-427", "value": ""},
{"command": "wait for element visible", "target": "css=[data-testid='status']", "value": "3000"},
{"command": "assert text", "target": "css=[data-testid='status']", "value": "saved:Ada"}
]
}],
"suites": [],
"urls": ["http://127.0.0.1:8826/v1"]
}
4. Break and diagnose v2
Point the copied learning flow at /v2. Capture the
first failure before changing anything. Confirm the DOM contains the
stable data-testid selector and does not contain the
old ID. Classify this as a locator/test defect, not a browser, Grid,
synchronization, or AUT business failure.
Repair the copied IDE target to
css=[data-testid='save-profile'] and replay only the
smallest scenario. Do not add pause commands.
5. Migrate and verify independently
Create the maintainable WebDriver test from the scenario intent—not by copying every recorded command. Use the same architecture as Lesson 2:
import unittest
from pathlib import Path
import tempfile, shutil
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
BASE_URL = "http://127.0.0.1:8826"
class ProfilePage:
NAME = (By.CSS_SELECTOR, "[data-testid='display-name']")
SAVE = (By.CSS_SELECTOR, "[data-testid='save-profile']")
STATUS = (By.CSS_SELECTOR, "[data-testid='status']")
def __init__(self, driver):
self.driver = driver
def open(self, variant="v2"):
self.driver.get(f"{BASE_URL}/{variant}")
WebDriverWait(self.driver, 3).until(
lambda d: d.find_element(*self.STATUS).text == "idle"
)
return self
def save_name(self, name):
field = self.driver.find_element(*self.NAME)
field.clear(); field.send_keys(name)
self.driver.find_element(*self.SAVE).click()
WebDriverWait(self.driver, 3).until(
lambda d: d.find_element(*self.STATUS).text.startswith(("saved:", "error:"))
)
def status(self):
return self.driver.find_element(*self.STATUS).text
class ProfileFlowTest(unittest.TestCase):
def setUp(self):
self.profile = Path(tempfile.mkdtemp(prefix="ide-migration-"))
options = webdriver.ChromeOptions()
options.add_argument("--headless=new")
options.add_argument(f"--user-data-dir={self.profile}")
self.driver = webdriver.Chrome(options=options)
def tearDown(self):
try:
self.driver.quit()
finally:
shutil.rmtree(self.profile, ignore_errors=True)
def test_save_profile(self):
page = ProfilePage(self.driver).open("v2")
page.save_name("Ada")
self.assertEqual("saved:Ada", page.status())
if __name__ == "__main__":
unittest.main()
Run it against v2. Record the Selenium version, returned
browser/version, session ID, URL, final status, test-runner result,
and cleanup outcome. If the run fails, capture first-failure
evidence before quit().
6. Compare the two artifacts
The following table organizes the key choices and evidence for Compare the two artifacts. Use it together with the surrounding prose so the rows serve as a comparison aid rather than standalone rules.
| Concern | IDE learning artifact | Maintainable WebDriver test |
|---|---|---|
| Locator | Recorder-selected then curated manually. | Stable selector lives near page service and is code-reviewed. |
| Synchronization | IDE wait command depends on current command/build capability. | Explicit state wait expresses the condition the assertion needs. |
| Fixture | Interactive IDE/browser project context. | Test fixture owns driver/profile and cleanup. |
| Assertion | Recorded assertion command. | Test owns business assertion and failure meaning. |
| Diagnostics | Interactive playback/logs. | Unique first-failure evidence plus session/version/URL state. |
| Data/config | Literal synthetic learning values. | Configuration/data can be parameterized and secret-injected by framework/CI. |
| CI readiness | Not the production gate. | Runnable by the project’s provider-neutral test command/headless or Grid path. |
7. Evidence packet and migration rationale
Your checkpoint packet must contain:
- IDE build/version and Selenium/browser versions;
- sanitized command/target/value review;
- the old generated-looking locator and new stable locator;
- v1/v2 DOM evidence relevant to that selector;
- first failed playback/translation evidence;
- migrated test output, session ID, URL, final status, and optional failure screenshot;
- cleanup result;
- a short rationale explaining why the IDE artifact is learning material rather than the CI gate.
Do not include passwords, tokens, cookies, personal profiles, production URLs, or unrelated full page source.
8. Cleanup and retention
Stop the loopback fixture. Quit every WebDriver session. Delete temporary browser profiles, exported downloads, and scratch recordings. Retain only the sanitized learning artifact if it has educational value; otherwise retain the migration rationale and production WebDriver code. A recording must not become an unreviewed duplicate source of truth.
If a paid browser cloud or managed enterprise platform is later introduced, preserve the same boundary: IDE exploration is optional; authoritative execution, secrets, evidence, lifecycle, and gating belong to the maintained test/infrastructure stack.
9. What Chapter 26 adds to the operating model
The production browser-automation model now has a controlled intake path for recorded interactions. Teams can prototype quickly without normalizing recorder weaknesses: every recording is inspected, sensitive values are excluded, locator/wait semantics are reviewed, and durable intent migrates into the same abstraction, fixture, evidence, security, capacity, and CI disciplines built in earlier chapters.
Chapter 27 builds directly on this outcome by integrating Selenium with pytest, JUnit, TestNG, NUnit, and language bindings, making test-framework lifecycle and reporting choices explicit rather than inheriting them accidentally from an IDE exporter.
Knowledge checks
Answer from the operating model, then reveal the explanation.
Your recorder selected a stable data-testid. Must you manufacture a brittle production locator to prove the chapter?
No. Use the stable locator in the real migration. For the controlled failure exercise, change only a disposable copy of the learning artifact so the failure is deterministic and harmless.
The repaired IDE test passes v2. What still must be proved?
The migrated WebDriver test must independently pass with its own session/configuration/assertion/evidence/cleanup; IDE success is not sufficient.
Which artifact should gate CI?
The maintained WebDriver/test-framework suite, not an unreviewed interactive recording.
A recorder captured a real password accidentally. Can redaction make the project safe to keep?
Treat the credential as exposed according to organizational policy, remove it from artifacts/history, rotate/revoke if real, and rebuild the learning artifact with synthetic data. Do not rely on cosmetic redaction alone.
Why bridge next to framework integration?
Once intent is migrated from IDE commands into code, framework lifecycle, parameterization, reporting, parallelism, and binding conventions become the next explicit design layer.
Summary and next bridge
- Record only disposable, authorized flows and inspect the artifact before trusting it.
- Use controlled markup change to distinguish locator brittleness from timing or product failure.
- Migrate scenario intent into stable selectors, explicit waits, fixtures, assertions, and diagnostics.
- Retain IDE artifacts only as sanitized learning/prototyping material.
- Use maintained WebDriver/framework code as the CI-quality evidence source.
Chapter 27 moves from migration into explicit framework integration across pytest, JUnit, TestNG, NUnit, and Selenium language bindings.
Primary references and version notes
- Selenium downloads — current stable WebDriver client/Grid release baseline.
- SeleniumHQ/selenium-ide — current Selenium IDE repository, installation model, and release history.
- Selenium IDE releases — verify the exact IDE build before relying on UI or export behavior.
- Selenium IDE Code Export — official export workflow and documented target frameworks.
- Selenium IDE Commands — documented command semantics including element waits and assertions.
- WebDriver waits — synchronization principles used after migration.
- Page Object Models — service-oriented abstraction and component composition used in the migrated design.
The WebDriver examples pin selenium==4.47.0 and
Python 3.10+. Selenium Manager remains the normal local
driver-resolution path. Selenium IDE is versioned separately: the
SeleniumHQ repository currently marks
v4.0.1-beta.14 as its latest GitHub release,
published July 20, 2024. Official IDE Code Export documentation
lists C# NUnit, Java JUnit, JavaScript Mocha, and Python pytest,
but the mandatory course path still verifies the installed IDE
build and migrates manually so recorded/exported code is never
treated as authoritative architecture.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.