A4Q Selenium Tester Mock Exam #5 — Questions & Answers
Every question in this mock exam, with the correct answer marked and a written rationale behind each option below — for reading and review, not a timed run.
What is the difference between driver.close() and driver.quit() in Selenium WebDriver?
close() closes the current window; quit() ends the session and closes all windows.
Correct: quit() also disposes the driver process, while close() leaves the session alive if other windows remain.
They are identical; both end the WebDriver session.
Wrong: close() does not end the session when other windows are open.
close() ends the session; quit() closes one window.
Wrong: the roles are reversed.
quit() only clears cookies; close() clears the cache.
Wrong: neither method is about cookies or cache.
close() closes only the current browser window/tab; quit() ends the whole WebDriver session and closes every window.
When findElement() cannot locate a matching element, what happens?
It throws a NoSuchElementException.
Correct: this is the defined behaviour for a single-element lookup that fails.
It returns null.
Wrong: WebDriver throws an exception rather than returning null.
It returns an empty list.
Wrong: that is the behaviour of findElements(), not findElement().
It waits forever until the element appears.
Wrong: without an explicit/implicit wait it fails immediately.
findElement() throws NoSuchElementException immediately; findElements() returns an empty list instead.
A price label is rendered as: <span id="total" data-amount="49.90">€49.90</span>. Your test must read the raw numeric value 49.90 (not the formatted text). Which call returns exactly 49.90?
element.getAttribute("data-amount")
Correct: reads the data-amount attribute, which holds the unformatted 49.90.
element.getText()
Wrong: returns the visible text '€49.90', including the currency symbol.
element.getAttribute("value")
Wrong: a span has no value attribute, so this returns null.
element.getTagName()
Wrong: returns 'span', the element's tag name.
getText() returns the visible '€49.90'. The raw number lives in the data-amount attribute, read with getAttribute("data-amount").
Selenium 4 communicates with browsers using which standardised protocol?
The W3C WebDriver protocol.
Correct: Selenium 4 dropped the JSON Wire Protocol in favour of the W3C standard.
The legacy JSON Wire Protocol.
Wrong: that protocol was used by Selenium 3 and earlier, removed in Selenium 4.
FTP.
Wrong: FTP is a file-transfer protocol, unrelated to browser automation.
SMTP.
Wrong: SMTP is an email protocol.
Selenium 4 is fully W3C WebDriver compliant; the legacy JSON Wire Protocol was removed.
A test class runs 12 test methods. Each method needs a fresh, isolated browser session, and no window may be left open after the suite finishes even if a test fails. Where should you instantiate and where should you dispose the driver?
Create the driver in @BeforeEach and call quit() in @AfterEach.
Correct: per-method setup gives isolation; teardown after each test guarantees cleanup even on failure.
Create once in @BeforeAll and quit in @AfterAll.
Wrong: a shared session across 12 tests breaks isolation (state leaks between tests).
Create in @BeforeEach but call quit() only at the end of each test body.
Wrong: if a test fails before that line, quit() never runs and windows leak.
Rely on the JVM to close the browser on exit.
Wrong: the browser/driver process is not cleaned up automatically and orphaned processes remain.
Per-test isolation requires creating the driver in a per-method setup (@BeforeEach) and calling quit() in a per-method teardown (@AfterEach), which runs even after failures.
You want to count how many <li> items are in a list, and the count may legitimately be zero. Which method should you use?
findElements(...).size()
Correct: returns 0 for no matches instead of throwing, ideal for counting.
findElement(...) in a loop until it fails.
Wrong: relying on an exception for a normal zero-count is fragile and slow.
getPageSource().length()
Wrong: this measures HTML length, not the number of list items.
getTitle().length()
Wrong: unrelated — returns the length of the page title string.
findElements() returns a List that can be empty (size 0) without throwing, so you can safely count matches including zero.
Which statement about driver.getWindowHandle() and driver.getWindowHandles() is correct?
getWindowHandle() returns a single String; getWindowHandles() returns a Set of Strings.
Correct: singular gives the current handle, plural gives all handles as a Set.
Both return a List in a guaranteed order.
Wrong: getWindowHandles() returns an unordered Set, not an ordered List.
getWindowHandle() opens a new window.
Wrong: it only returns the current handle; it opens nothing.
getWindowHandles() switches focus to the last window.
Wrong: it only returns handles; switching requires switchTo().window(handle).
getWindowHandle() (singular) returns the current window's handle as a String; getWindowHandles() (plural) returns a Set of all open handles.
Which TWO capabilities were introduced or standardised in Selenium 4? (Select TWO)
Relative (friendly) locators such as above(), below(), toLeftOf().
Correct: relative locators are a Selenium 4 feature.
Native Chrome DevTools Protocol (CDP) access.
Correct: Selenium 4 exposes CDP for network, geolocation and console features.
Recording tests as video by default.
Wrong: WebDriver does not record video; that needs external tooling.
Automatic generation of locators from screenshots.
Wrong: no such feature exists in Selenium 4.
Selenium 4 added relative (friendly) locators and native Chrome DevTools Protocol access, and adopted the W3C WebDriver standard.
Which CSS selector matches an element with id "submit-btn"?
#submit-btn
Correct: '#' selects by id.
.submit-btn
Wrong: '.' selects by class, not id.
submit-btn
Wrong: a bare token selects by tag name; there is no <submit-btn> tag.
*submit-btn
Wrong: this is not valid CSS syntax for an id.
In CSS, '#' targets an id, so #submit-btn matches id="submit-btn". '.' targets a class.
Given this markup: <input class="form-control" name="email" type="email"> and several other inputs share class="form-control". You need a locator that uniquely identifies the email field. Which is best?
css=input[name='email']
Correct: the name attribute is unique, giving a stable, precise match.
css=.form-control
Wrong: this class is shared, so it matches several inputs, not just email.
css=input
Wrong: matches every input on the page.
css=input.email
Wrong: there is no class 'email'; the token 'email' is the name attribute, not a class.
The class is shared, so it is not unique. The name attribute 'email' is unique, so css=input[name='email'] reliably targets it.
A page has a link rendered as <a href="/logout">Log out</a>. Several links exist, but only this one has the exact text 'Log out'. Which XPath selects it by its visible text?
//a[text()='Log out']
Correct: matches the anchor whose text equals 'Log out'.
//a[@text='Log out']
Wrong: there is no 'text' attribute; visible text is a text node, not an attribute.
//a[@href='Log out']
Wrong: this matches on the href value, which is '/logout', not the text.
//text()='Log out'
Wrong: this is not a valid element-selecting XPath expression.
//a[text()='Log out'] matches an <a> whose text node equals 'Log out' exactly. normalize-space() would also work if surrounding whitespace were a concern.
Which CSS selector matches an <a> whose href attribute ends with '.pdf'?
a[href$='.pdf']
Correct: '$=' means 'ends with'.
a[href^='.pdf']
Wrong: '^=' means 'starts with', not ends with.
a[href*='.pdf']
Partly matches but '*=' means 'contains' anywhere, so it also matches '.pdf.html'.
a[href='.pdf']
Wrong: requires the href to equal '.pdf' exactly.
The '$=' operator in CSS matches an attribute value that ends with the given substring: a[href$='.pdf'].
Element: <button class="btn primary" data-test="save">Save</button>. Which TWO locators correctly and uniquely match this button (assuming data-test values are unique)? (Select TWO)
css=button[data-test='save']
Correct: data-test is unique and stable, an ideal locator.
//button[text()='Save']
Correct: matches the button by its exact visible text 'Save'.
css=.btn
Wrong: 'btn' is a generic shared class, likely matching many buttons.
css=#save
Wrong: the button has no id attribute, so '#save' matches nothing.
css=button[data-test='save'] uses the unique data-test attribute; //button[text()='Save'] matches its exact text. css=.btn is shared and .primary.btn syntax targets the class combo but 'primary' may not be unique; the id form is invalid because there is no id.
In Selenium 4, you want to find the input field located immediately above a label with id 'password'. Which relative locator expression is correct?
with(By.tagName("input")).above(By.id("password"))
Correct: this is the Selenium 4 relative-locator API for 'above'.
By.above("input", "password")
Wrong: By has no 'above' factory method; relative locators use with().
By.cssSelector("input:above(#password)")
Wrong: ':above' is not a valid CSS pseudo-class.
with(By.id("password")).below(By.tagName("input"))
Wrong: this reverses the relationship and anchors on the wrong element.
Selenium 4 relative locators use With.tagName(...).above(elementOrLocator). So with(By.tagName("input")).above(By.id("password")) finds the input above the password label.
A table row shows: <tr><td>ACME Ltd</td><td><button class="del">Delete</button></td></tr>. You must click the Delete button in the row whose first cell text is 'ACME Ltd'. Which XPath is correct?
//td[text()='ACME Ltd']/ancestor::tr//button[text()='Delete']
Correct: anchors on the row's identifying cell, then finds the Delete button within that same row.
//button[text()='Delete']
Wrong: matches every Delete button in the table, not the specific row.
//td[text()='ACME Ltd']//button
Wrong: the button is not a descendant of the first cell; it is in a sibling cell.
//tr[text()='ACME Ltd']//button
Wrong: the text 'ACME Ltd' belongs to the <td>, not directly to the <tr>.
Anchor on the unique cell text, then walk up to the row and down to the button: //td[text()='ACME Ltd']/ancestor::tr//button[text()='Delete'].
Which TWO practices make locators more robust against UI changes? (Select TWO)
Prefer stable, dedicated attributes such as id or data-test.
Correct: purpose-built test hooks rarely change with styling or layout.
Keep locators short and relative to a stable ancestor.
Correct: shallow, relative locators tolerate DOM restructuring better.
Use full absolute XPath from /html/body downward.
Wrong: absolute paths break as soon as any intermediate element changes.
Rely on positional indexes like (//div)[7].
Wrong: index-based locators break whenever elements are added or reordered.
Stable, purpose-built hooks (id, data-test attributes) and short, shallow locators resist change. Long absolute XPath and index-based positions are brittle.
What is the core idea of the Page Object Model (POM)?
Encapsulate each page's locators and actions in a dedicated class.
Correct: this centralises locators and exposes behaviour as methods, improving maintainability.
Store all test data in a single object.
Wrong: that describes a data/fixture pattern, not POM.
Write every test in one long method.
Wrong: this is the opposite of the modular structure POM promotes.
Replace WebDriver with a mock in every test.
Wrong: POM is a design pattern, not a mocking strategy.
POM encapsulates a page's locators and interactions in a dedicated class, so tests call meaningful methods instead of duplicating locator/interaction code.
According to good POM practice, where should test assertions normally live?
In the test methods, not inside the page objects.
Correct: keeping assertions in tests keeps page objects reusable and focused on interaction.
Inside every page object method.
Wrong: embedding assertions couples page objects to specific test expectations, hurting reuse.
In the WebDriver constructor.
Wrong: the driver setup has nothing to do with test assertions.
In the HTML of the page under test.
Wrong: assertions are test code, not part of the application markup.
Assertions belong in the test methods, not in page objects. Page objects model page structure and actions and return data/state that tests assert on.
In a well-designed POM, a LoginPage has a method login(user, pass) that submits valid credentials and lands on the dashboard. What should login() return so the test can continue fluently?
A DashboardPage object representing the resulting page.
Correct: returning the next page object enables fluent, type-safe chaining of steps.
A boolean 'true' if any element is present.
Wrong: a bare boolean discards navigation context and forces the test to re-locate everything.
The raw WebDriver instance.
Wrong: leaking the driver breaks encapsulation that POM is meant to provide.
void (nothing).
Wrong: returning nothing after a page transition forces manual re-instantiation of the next page.
A navigation action that moves to another page should return the next page object (e.g. DashboardPage), so tests can chain interactions and stay type-safe.
In the PageFactory variant of POM, what does the @FindBy annotation do?
It declares the locator used to resolve a WebElement field.
Correct: @FindBy attaches a locator to a field, resolved lazily via PageFactory.
It runs an assertion on the element.
Wrong: it only declares how to find the element, not what to assert.
It launches the browser.
Wrong: it has nothing to do with starting a driver session.
It takes a screenshot of the element.
Wrong: screenshots are unrelated to @FindBy.
@FindBy declares the locator for a WebElement field; PageFactory.initElements(...) wires up lazy proxies that resolve the locator when the field is used.
A locator for the 'Checkout' button is used in 15 different tests. The button's id changes. With a well-applied Page Object Model, how many places must you update?
One — the locator in the page object.
Correct: centralising the locator means a single edit fixes all 15 tests.
Fifteen — one per test.
Wrong: that is the duplication problem POM is designed to eliminate.
Thirty — the locator plus its assertion in each test.
Wrong: assertions are separate and the locator is still centralised in POM.
None — Selenium auto-heals locators.
Wrong: Selenium has no built-in locator self-healing.
POM centralises each locator in one page class, so a locator change is fixed in exactly one place regardless of how many tests use it.
Which TWO items belong inside a page object class? (Select TWO)
Element locators for that page.
Correct: locators are the primary content of a page object.
Action methods such as search() or login().
Correct: behaviour methods expose the page's interactions to tests.
The pass/fail assertions of individual tests.
Wrong: assertions belong in the tests, keeping page objects reusable.
The test runner's scheduling configuration.
Wrong: suite/runner configuration is infrastructure, not page modelling.
A page object holds the page's element locators and action/service methods (e.g. login, search). Test assertions and test-suite scheduling do not belong there.
What is the key difference between an implicit wait and an explicit wait?
Implicit wait is global for all lookups; explicit wait targets a specific condition.
Correct: implicit applies everywhere; explicit waits for a defined condition on an element.
Implicit wait pauses a fixed number of seconds every time regardless of state.
Wrong: that describes Thread.sleep; implicit wait polls and returns as soon as found.
Explicit wait is global; implicit wait targets one element.
Wrong: the roles are reversed.
They are the same and can be freely mixed with no side effects.
Wrong: they differ, and mixing implicit and explicit waits can cause unpredictable timeouts.
An implicit wait is a global timeout applied to every element lookup; an explicit wait targets a specific condition on a specific element.
After clicking 'Load more', results are injected via AJAX and a container with id 'results' becomes visible after a variable delay. You must wait until it is visible before reading it. Which is the correct Selenium 4 explicit wait?
new WebDriverWait(driver, Duration.ofSeconds(10)).until(ExpectedConditions.visibilityOfElementLocated(By.id("results")))
Correct: waits up to 10s for the element to be present and visible before returning it.
Thread.sleep(10000)
Wrong: a fixed sleep is slow when fast and flaky when slow; it does not check the condition.
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)) then getText()
Wrong: implicit wait covers presence but not visibility; reading a hidden container can still fail.
driver.findElement(By.id("results")).getText() immediately
Wrong: with no wait this throws NoSuchElementException while AJAX is still loading.
Use WebDriverWait with Duration and ExpectedConditions.visibilityOfElementLocated(By.id("results")) to wait for the element to be present and displayed.
Why is Thread.sleep() discouraged as a synchronisation mechanism in Selenium tests?
It always waits the full fixed time, making tests slow or flaky depending on the value.
Correct: it ignores the actual state, so it wastes time or fails intermittently.
It is not supported by the Java language.
Wrong: Thread.sleep is standard Java; the problem is behavioural, not availability.
It closes the browser session.
Wrong: sleeping does not affect the WebDriver session.
It polls the DOM every 500 ms like an explicit wait.
Wrong: it does not poll at all; it simply blocks for the fixed duration.
Thread.sleep pauses for a fixed duration regardless of readiness, making tests slow when the wait is too long and flaky when it is too short.
A 'Submit' button is present in the DOM but stays disabled until a form is valid. Clicking it too early does nothing. Which ExpectedCondition should you wait for before calling click()?
ExpectedConditions.elementToBeClickable(...)
Correct: it requires visible AND enabled, matching the disabled-until-valid button.
ExpectedConditions.presenceOfElementLocated(...)
Wrong: presence only checks it is in the DOM; the button is present but disabled.
ExpectedConditions.titleContains(...)
Wrong: this checks the page title, unrelated to the button state.
ExpectedConditions.alertIsPresent()
Wrong: there is no alert involved in this scenario.
elementToBeClickable waits until the element is both visible and enabled, which is exactly the condition needed for a button that becomes enabled only when the form is valid.
What does a FluentWait let you configure that a plain WebDriverWait constructor call does not emphasise?
The polling interval and which exceptions to ignore while polling.
Correct: FluentWait exposes pollingEvery(...) and ignoring(...) alongside the timeout.
The browser's user-agent string.
Wrong: user-agent is a browser/capability setting, not part of a wait.
The screen resolution of the test machine.
Wrong: unrelated to waiting logic.
The number of parallel threads for the suite.
Wrong: parallelism is configured in the test runner, not in a wait.
FluentWait lets you set the polling interval and specify exception types to ignore during polling, in addition to the overall timeout.
Which TWO are valid ExpectedConditions provided by Selenium's support library? (Select TWO)
visibilityOfElementLocated(By)
Correct: a standard condition waiting for an element to be present and displayed.
textToBePresentInElement(element, text)
Correct: a standard condition waiting for specific text to appear in an element.
elementHasNiceColor(By)
Wrong: no such condition exists in Selenium.
pageIsBeautiful()
Wrong: invented; not part of the ExpectedConditions API.
visibilityOfElementLocated and textToBePresentInElement are standard ExpectedConditions. 'elementHasNiceColor' and 'pageIsBeautiful' are invented.
Which pair of calls both load a URL in the current browser window?
driver.get(url) and driver.navigate().to(url)
Correct: both navigate to the given URL in the current window.
driver.open(url) and driver.load(url)
Wrong: neither open() nor load() exists on WebDriver.
driver.goTo(url) and driver.visit(url)
Wrong: these method names are not part of the WebDriver API.
driver.getUrl(url) and driver.setUrl(url)
Wrong: getCurrentUrl() reads the URL and takes no argument; setUrl() does not exist.
Both driver.get(url) and driver.navigate().to(url) load a page; get() is essentially shorthand and waits for the page load, navigate().to() adds history support like back()/forward().
Which call returns to the previous page in the browser's history?
driver.navigate().back()
Correct: this navigates one entry back in browser history.
driver.back()
Wrong: back() is on the Navigation object, not directly on driver.
driver.navigate().refresh()
Wrong: refresh() reloads the current page, it does not go back.
driver.navigate().forward()
Wrong: forward() goes forward, not back.
driver.navigate().back() moves one step back in history, equivalent to the browser Back button.
A payment form is inside an <iframe id="pay">. After filling and submitting fields inside it, you must click a 'Continue' button that lives in the MAIN document, outside the iframe. What must you do before locating 'Continue'?
Call driver.switchTo().defaultContent() to return to the main document.
Correct: this restores focus to the top-level document so main-page elements are locatable.
Call driver.switchTo().frame("pay") again.
Wrong: this keeps you inside the iframe, where 'Continue' does not exist.
Refresh the page with navigate().refresh().
Wrong: a refresh discards the form state and does not change frame context correctly.
Nothing — elements in the main document are always reachable from inside an iframe.
Wrong: while focused in an iframe, top-document elements are not in scope.
While focused in an iframe, the main document is out of context. You must switch back with driver.switchTo().defaultContent() before locating elements in the top document.
A JavaScript confirm() dialog appears. How do you accept it (click OK) in Selenium?
driver.switchTo().alert().accept()
Correct: switches to the alert and clicks OK.
driver.findElement(By.id("ok")).click()
Wrong: native browser dialogs are not part of the DOM and cannot be located by By.
driver.switchTo().alert().dismiss()
Wrong: dismiss() cancels (clicks Cancel), it does not accept.
driver.navigate().refresh()
Wrong: refreshing does not interact with the dialog.
Switch to the alert and accept it: driver.switchTo().alert().accept(). dismiss() would cancel it.
Clicking a 'View invoice' link opens the invoice in a NEW browser tab. You must read text on the invoice, then close it and return to the original tab. Which sequence is correct?
Save the current handle, switchTo().window(newHandle), read, close(), then switchTo().window(originalHandle).
Correct: you must explicitly switch to the new tab and switch back after closing it.
Just call getText() — WebDriver follows the new tab automatically.
Wrong: focus stays on the original tab until you switchTo().window(...).
Call driver.navigate().forward() to reach the new tab.
Wrong: forward() moves within one tab's history, not between tabs.
Call driver.quit() then reopen the original page.
Wrong: quit() ends the whole session, losing all state.
Capture the original handle, find the new handle among getWindowHandles(), switchTo().window(newHandle), read/close, then switchTo().window(originalHandle).
A submenu only appears when the mouse hovers over a top menu item. Which Selenium API models this hover-then-click interaction?
The Actions class, e.g. new Actions(driver).moveToElement(menu).click(submenu).perform()
Correct: Actions models advanced pointer sequences like hover-then-click.
driver.get() on the submenu URL.
Wrong: the submenu is not a separate URL; it appears via hover state.
driver.switchTo().frame(menu)
Wrong: switching frames is unrelated to hovering over a menu.
driver.manage().window().fullscreen()
Wrong: fullscreen changes window size, not hover behaviour.
The Actions class builds composite input sequences; moveToElement(menu).click(submenu).perform() performs the hover then click.
What is a 'flaky' automated test?
A test that sometimes passes and sometimes fails without any code or environment change.
Correct: non-deterministic results with no real change is the definition of flakiness.
A test that always fails.
Wrong: a consistently failing test is deterministic, indicating a real defect, not flakiness.
A test with more than 100 steps.
Wrong: length alone does not make a test flaky.
A test written in a scripting language.
Wrong: the implementation language has nothing to do with flakiness.
A flaky test produces different results (pass/fail) on the same code and environment without any real change, undermining trust in the suite.
Which is the most common root cause of flaky Selenium UI tests?
Timing/synchronisation issues — acting before elements are ready.
Correct: race conditions between test and app rendering are the top cause; explicit waits address them.
Using too few comments in the code.
Wrong: comments do not affect runtime behaviour or flakiness.
Naming test methods in English.
Wrong: method naming language is irrelevant to stability.
Compiling the tests instead of interpreting them.
Wrong: compilation vs interpretation does not cause flakiness.
Timing/synchronisation issues — interacting with elements before they are ready — are the leading cause of flakiness, best fixed with explicit waits.
A test stores a WebElement in a variable, then the page re-renders a list via AJAX, and the next action on that variable throws StaleElementReferenceException. What is the correct fix?
Re-locate the element after the DOM update instead of reusing the stale reference.
Correct: the old node was replaced; a fresh findElement (after a wait) resolves the current node.
Wrap the action in a try/catch and ignore the exception.
Wrong: swallowing the exception hides the failure and the action still does not happen.
Increase the implicit wait to 60 seconds.
Wrong: a longer implicit wait does not refresh a reference that is already stale.
Restart the browser before every action.
Wrong: restarting is drastic, slow, and unnecessary; re-locating the element suffices.
A stale reference points to a DOM node that was replaced. The fix is to re-locate the element after the DOM changes (ideally after an explicit wait), not to reuse the old reference.
Why should each automated test be independent of the others?
So tests can run in any order or in parallel and one failure does not cascade.
Correct: independence enables parallelism and isolates failures for clear diagnosis.
So the suite runs slower and is easier to watch.
Wrong: independence supports speed via parallelism, not slowness.
So tests must always share one browser session.
Wrong: independence usually means the opposite — isolated sessions/state.
So you can remove all assertions.
Wrong: independence has nothing to do with removing assertions.
Independent tests can run in any order and in parallel, and a failure in one does not cascade into others, which improves reliability and diagnosis.
Which TWO practices reduce flakiness in a Selenium suite running on a CI server? (Select TWO)
Use explicit waits for the exact condition instead of fixed sleeps.
Correct: condition-based waits adapt to variable CI timing, cutting timing flakiness.
Have each test create and clean up its own isolated data.
Correct: self-contained data prevents cross-test interference, especially under parallel CI runs.
Insert Thread.sleep(5000) before each interaction.
Wrong: fixed sleeps are slow and still flaky when the server is slower than expected.
Make tests depend on the data left behind by the previous test.
Wrong: order dependence is a classic flakiness source, especially with parallel execution.
Using explicit waits for conditions and ensuring each test sets up its own isolated data both reduce flakiness. Hard-coded sleeps and depending on execution order increase it.
Capturing a screenshot automatically when a test fails primarily helps with what?
Diagnosing why the test failed by showing the UI state at that moment.
Correct: the screenshot is a diagnostic artifact of the failure state, invaluable in CI.
Making the test run faster.
Wrong: capturing a screenshot adds a small cost; it does not speed up the run.
Preventing the failure from happening.
Wrong: a screenshot records the failure; it cannot prevent it.
Automatically fixing the broken locator.
Wrong: screenshots do not modify or repair test code.
A failure screenshot captures the UI state at the moment of failure, which speeds up debugging and diagnosis, especially in headless CI runs.