A4Q Selenium Tester Mock Exam #1 — 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.
How does Selenium WebDriver communicate with a real browser such as Chrome or Firefox?
Through a browser-specific driver using the W3C WebDriver protocol
Correct — the client library talks to a driver (chromedriver/geckodriver) over HTTP, and the driver drives the browser.
By injecting JavaScript that is the only way it controls the page
Wrong — WebDriver can execute JavaScript, but native commands go through the driver, not solely via injected JS.
By directly modifying the browser's source code at runtime
Wrong — WebDriver never edits browser source code; it automates the browser through its driver.
Through screen-scraping pixels and simulating mouse clicks at OS level
Wrong — that describes image-based tools; WebDriver uses the browser's automation API via the driver.
WebDriver sends commands over the W3C WebDriver protocol (HTTP/JSON) to a browser-specific driver executable (e.g. chromedriver, geckodriver), which controls the browser.
What happens when driver.findElement(By.id("login")) is called and no element with that id exists on the page?
It throws a NoSuchElementException
Correct — findElement raises NoSuchElementException when no element matches.
It returns null
Wrong — findElement never returns null; it throws. findElements returns an empty list instead.
It returns an empty WebElement
Wrong — there is no 'empty WebElement'; the call fails with an exception.
It waits forever until the element appears
Wrong — findElement does not block indefinitely; without a wait it fails fast.
findElement throws a NoSuchElementException immediately when no matching element is found.
How does driver.findElements(By.className("row")) behave when no matching elements are present?
It returns an empty list
Correct — findElements returns a list of size 0 when nothing matches.
It throws a NoSuchElementException
Wrong — that is findElement's behaviour; findElements does not throw on zero matches.
It returns null
Wrong — it returns an empty collection, never null.
findElements returns an empty list (size 0) rather than throwing; this is useful for presence checks.
What is the difference between driver.close() and driver.quit()?
close() closes the current window; quit() closes all windows and ends the session
Correct — quit() also disposes the driver process, releasing resources.
They are identical aliases for the same operation
Wrong — they differ: close() affects one window, quit() the whole session.
quit() closes only the active tab; close() ends the session
Wrong — this reverses the two methods.
close() deletes cookies; quit() keeps the browser open
Wrong — neither method is about cookies, and quit() does not keep the browser open.
close() closes the current browser window/tab; quit() closes all windows opened by that driver session and ends the WebDriver session.
Which of the following are valid built-in locator strategies exposed by the By class in Selenium WebDriver? (Choose two.)
By.cssSelector
Correct — cssSelector is a core By strategy.
By.xpath
Correct — xpath is a core By strategy.
By.value
Wrong — there is no By.value; match an attribute value via CSS or XPath instead.
By.placeholder
Wrong — placeholder is not a By strategy; target it with a CSS attribute selector.
Valid By strategies include id, name, className, tagName, linkText, partialLinkText, cssSelector and xpath. 'value' and 'placeholder' are not standalone strategies.
You need to read the visible label of a button into a string. Which WebElement method should you use?
getText()
Correct — getText() returns the rendered visible text of the element.
getAttribute("text")
Wrong — there is no standard 'text' attribute; use getText() for visible content.
getTagName()
Wrong — getTagName() returns the element's HTML tag, not its label.
getCssValue("label")
Wrong — getCssValue reads CSS properties, not the element's text.
getText() returns the visible, rendered inner text of an element; getAttribute() reads a named HTML attribute value.
An <input> field already contains the text "abc". You call element.sendKeys("123"). What is the field's value afterwards (assuming no other action)?
abc123
Correct — sendKeys appends, so the existing "abc" is kept and "123" is added.
123
Wrong — that would require calling clear() first; sendKeys alone does not erase.
123abc
Wrong — keys are appended at the cursor (end), not prepended.
An empty string
Wrong — sendKeys adds text, it never empties the field.
sendKeys appends to existing content; it does not clear the field. To replace, call clear() first.
Which statement best describes the relationship between the WebDriver interface and a class such as ChromeDriver?
WebDriver is an interface that ChromeDriver implements
Correct — programming to the WebDriver interface keeps tests browser-independent.
ChromeDriver is an interface that WebDriver implements
Wrong — this reverses the relationship; WebDriver is the interface.
They are unrelated classes with no inheritance link
Wrong — ChromeDriver implements WebDriver, so they are clearly related.
WebDriver is a subclass of ChromeDriver
Wrong — it is the other way round; ChromeDriver implements the WebDriver interface.
WebDriver is an interface; browser-specific classes like ChromeDriver, FirefoxDriver and EdgeDriver implement it, which lets tests be written against the interface.
A page contains the following element:
<input type="text" id="user-email" name="email" class="form-control required">
Which CSS selector uniquely and most robustly targets this single input by its id?
#user-email
Correct — # selects by id, which is unique, giving a short stable locator.
.form-control.required
Wrong — class selectors may match many elements and classes change often; less robust than the id.
input
Wrong — the tag selector matches every input on the page, so it is not unique.
Wrong — the id is user-email, not email; #email matches nothing here.
An id is unique on a valid page, so the id selector #user-email is the most robust CSS locator here.
In XPath, what is the difference between a path that starts with // and one that starts with /?
// searches descendants anywhere; / selects from the document root
Correct — // is a relative/descendant search; a single leading / is an absolute path from the root.
// is for CSS and / is for XPath
Wrong — both are XPath syntax; neither is CSS.
// selects only the first match; / selects all matches
Wrong — neither operator limits to the first match; that depends on indexing like [1].
There is no difference; they are interchangeable
Wrong — they behave very differently (descendant search vs absolute root path).
A leading / selects from the document root (absolute), while // selects nodes anywhere in the document that match (relative/descendant search).
The page has two buttons:
<button class="btn">Cancel</button> <button class="btn">Submit</button>
Which XPath selects only the Submit button by its visible text?
//button[text()='Submit']
Correct — it matches the button whose text node equals 'Submit'.
//button[@class='btn']
Wrong — both buttons have class btn, so this matches two elements.
//button
Wrong — this matches every button on the page, not just Submit.
//button[@text='Submit']
Wrong — there is no text attribute; visible text needs the text() function, not @text.
Both buttons share class btn, so a class locator is ambiguous. Matching the exact text with text()='Submit' selects only the Submit button.
In a CSS selector, which prefix selects an element by its class attribute?
A dot, e.g. .btn
Correct — the dot prefix selects by class name in CSS.
A hash, e.g. #btn
Wrong — the hash selects by id, not by class.
An at-sign, e.g. @btn
Wrong — @ is XPath attribute syntax, not CSS.
A colon, e.g. :btn
Wrong — a colon introduces a pseudo-class (like :hover), not a class match.
In CSS, . (dot) selects by class and # (hash) selects by id.
Which of the following locator practices generally lead to MORE stable, maintainable tests? (Choose two.)
Using a unique id or a dedicated data-testid attribute
Correct — these are stable and rarely change with styling or layout.
Short, scoped CSS selectors based on meaningful attributes
Correct — concise attribute-based CSS is readable and resilient to layout change.
Long absolute XPaths like /html/body/div[3]/div[2]/form/input[1]
Wrong — absolute paths break with almost any DOM change; they are brittle.
Selecting elements by their numeric position index
Wrong — position indexes change whenever sibling order changes, making tests flaky.
Stable locators favour unique ids and purpose-built test attributes; long absolute XPaths and position indexes break easily when the DOM changes.
You must select this field by its name attribute:
<input name="email" type="email">
Which CSS attribute selector is correct?
input[name='email']
Correct — square-bracket attribute syntax matches the name attribute exactly.
input(name='email')
Wrong — CSS does not use parentheses for attribute selection.
input@name='email'
Wrong — @ is XPath attribute syntax, not CSS.
input.name.email
Wrong — dots select classes named 'name' and 'email', not the name attribute.
A CSS attribute selector uses square brackets: input[name='email'] matches an input whose name attribute equals email.
Given this markup, you need the <input> that immediately follows the label:
<label for="q">Search</label><input id="q" type="text">
Which XPath uses an axis to select the input that is a following sibling of the label?
//label/following-sibling::input
Correct — the following-sibling axis selects the input that follows the label at the same level.
//label/child::input
Wrong — the input is a sibling of the label, not its child, so child:: matches nothing.
//label/parent::input
Wrong — the parent axis goes upward; an input is not the parent of a label.
//label/preceding-sibling::input
Wrong — preceding-sibling looks backward, but the input comes after the label.
The following-sibling axis selects siblings that come after the context node. //label/following-sibling::input picks the input after the label.
An element has a dynamic class that always contains the word 'alert' but with extra suffixes, e.g. class="alert alert-danger fade-in". Which XPath reliably matches any element whose class contains 'alert'?
//*[contains(@class,'alert')]
Correct — contains() does a substring match on the class attribute, tolerating extra tokens.
//*[@class='alert']
Wrong — exact match fails because the full class string is 'alert alert-danger fade-in'.
//*[class='alert']
Wrong — attributes need the @ prefix in XPath; class without @ refers to a child node named class.
//*[starts-with(@id,'alert')]
Wrong — this checks the id, not the class, and uses prefix not substring matching.
The contains() function does a substring match, so contains(@class,'alert') matches regardless of the other class tokens.
What is the primary purpose of the Page Object Model (POM) design pattern in Selenium test automation?
To encapsulate a page's locators and actions in one class, improving readability and maintainability
Correct — this central goal reduces duplication and isolates UI changes to a single class.
To make tests run faster in parallel
Wrong — POM aids maintainability; parallel speed comes from the runner/grid, not the pattern.
To replace the need for any locators
Wrong — POM still uses locators; it just centralises them inside page classes.
To generate test data automatically
Wrong — test data generation is unrelated to POM, which models pages.
POM encapsulates the locators and interactions of a page inside a dedicated class, so test scripts call readable methods and locator changes are made in one place.
According to common Page Object Model guidance, where should test assertions normally be placed?
In the test methods, not inside the page objects
Correct — keeping assertions in tests makes page objects reusable across different checks.
Inside every page object method
Wrong — embedding assertions everywhere couples pages to specific checks and hurts reuse.
In the WebDriver configuration
Wrong — driver configuration is about setup, not verifying expected outcomes.
In the HTML of the page under test
Wrong — assertions are test code; they are never placed in the application's HTML.
Page objects should expose state/behaviour and return data or other page objects; assertions belong in the test methods, keeping page objects reusable.
A LoginPage method submits the form and lands the user on the dashboard:
public DashboardPage login(String u, String p) { ... }
Why is returning a DashboardPage object (rather than void) considered good Page Object practice?
It models the page transition and lets tests chain to the next page in a type-safe way
Correct — returning the resulting page object expresses navigation and enables fluent, readable chains.
It makes the login run without a browser
Wrong — the return type does not change whether a browser is used; WebDriver still drives one.
It automatically asserts that login succeeded
Wrong — returning a page object does not assert anything; assertions stay in the test.
It avoids the need to instantiate WebDriver
Wrong — the driver is still required; the return type is unrelated to driver creation.
Returning the next page object models navigation and lets tests chain calls fluently while keeping the page transition explicit and type-safe.
A locator for the login button changes in the application's UI. In a well-structured Page Object Model project, how many places typically need updating?
One — the locator defined in the relevant page object
Correct — centralising locators means a single edit fixes all dependent tests.
Every test that clicks the button
Wrong — that is the problem POM solves; without POM you would edit many tests.
None — locators update themselves
Wrong — locators are static strings/definitions; they do not self-update.
The WebDriver binary must be reinstalled
Wrong — a locator change has nothing to do with the driver binary.
Because each locator is defined once inside its page object, a UI change is fixed in a single location, regardless of how many tests use it.
Which of the following typically belong INSIDE a page object class? (Choose two.)
The locators of the elements on that page
Correct — locators are encapsulated in the page object.
Methods that perform user interactions on that page
Correct — action methods (e.g. login, search) belong in the page object.
The expected test data and assertions
Wrong — these belong in the test, not the page object, to keep it reusable.
The test runner configuration (e.g. TestNG suite XML)
Wrong — runner configuration is project setup, separate from page objects.
A page object holds the page's locators and methods that perform user interactions or return information; test data and assertions live in the tests.
In the Selenium PageFactory approach (Java), a field is declared like this:
@FindBy(id = "submit") private WebElement submitButton;
What does the @FindBy annotation, combined with PageFactory.initElements, achieve?
It initialises the WebElement field so the element is located lazily on first use
Correct — PageFactory wires up annotated fields and resolves the locator when the element is accessed.
It permanently caches the element so it never goes stale
Wrong — cached PageFactory elements can still throw StaleElementReferenceException after DOM changes.
It adds an implicit assertion that the button exists
Wrong — @FindBy locates; it does not assert presence.
It downloads the matching browser driver automatically
Wrong — driver management is unrelated to @FindBy.
PageFactory uses @FindBy to lazily locate the element when it is first used, initialising the annotated WebElement fields so you don't call findElement explicitly.
How does an implicit wait configured with driver.manage().timeouts().implicitlyWait(...) affect element lookups?
It applies globally, making every findElement poll up to the timeout before failing
Correct — the implicit wait is set once and affects all subsequent element searches.
It waits only for one specific element you name each time
Wrong — that describes an explicit wait; the implicit wait is global, not per-named-element.
It pauses the whole test for the full duration every time
Wrong — it only waits as long as needed; if the element appears sooner the call returns immediately.
It only affects driver.get() navigation, not findElement
Wrong — the implicit wait affects element location, not page navigation timeouts.
An implicit wait sets a global polling timeout: every findElement call will keep polling the DOM up to that duration before throwing NoSuchElementException.
A test fails intermittently because a button is in the DOM but briefly disabled after the page loads. Which explicit wait condition best fixes this?
new WebDriverWait(driver, Duration.ofSeconds(10)).until(ExpectedConditions.________)
elementToBeClickable(locator)
Correct — it waits for the element to be visible AND enabled before proceeding.
presenceOfElementLocated(locator)
Wrong — presence only checks the element is in the DOM, not that it is enabled/clickable.
titleContains("...")
Wrong — this checks the page title, unrelated to the button's enabled state.
Thread.sleep(10000)
Wrong — that is not an ExpectedCondition and a fixed sleep is exactly the brittle approach to avoid.
elementToBeClickable waits until the element is both visible and enabled, which is exactly the condition for a button that is present but temporarily disabled.
Why is using Thread.sleep() for synchronisation generally discouraged in Selenium tests?
It always waits the full fixed time, making tests slow and still flaky
Correct — a static sleep cannot adapt to actual load times, so it wastes time or fails.
It is not supported by Java
Wrong — Thread.sleep is valid Java; the issue is suitability, not support.
It closes the browser session
Wrong — sleeping pauses the thread; it does not close the browser.
It only works in headless mode
Wrong — Thread.sleep behaves the same in headed and headless modes.
Thread.sleep always pauses for the fixed time regardless of readiness, making tests slower than necessary and still flaky if the wait is too short.
What is the key behavioural difference between an explicit wait (WebDriverWait + ExpectedConditions) and an implicit wait?
Explicit waits target a specific condition; implicit waits are a global timeout for all lookups
Correct — explicit waits are condition-based and local; implicit waits are blanket and global.
Explicit waits are global; implicit waits target one condition
Wrong — this reverses the two wait types.
There is no difference; the terms are synonyms
Wrong — they are distinct mechanisms with different scope and behaviour.
Explicit waits only work in Python; implicit waits only in Java
Wrong — both wait types exist across the Selenium language bindings.
An explicit wait targets a specific condition for a specific element, while an implicit wait applies a single global timeout to all element lookups.
Which of the following are recommended synchronisation practices for stable Selenium tests? (Choose two.)
Use explicit waits with conditions that reflect what the test needs (visible, clickable)
Correct — condition-based waits return as soon as the app is ready, improving speed and stability.
Use a FluentWait to poll with a timeout and ignore expected transient exceptions
Correct — FluentWait lets you set polling interval and ignore exceptions like NoSuchElement while waiting.
Mix implicit and explicit waits freely throughout the suite
Wrong — mixing them can produce unpredictable, additive wait times and is discouraged.
Add long Thread.sleep calls before every interaction
Wrong — fixed sleeps make suites slow and do not guarantee readiness.
Good practice favours explicit/fluent waits on meaningful conditions and avoids mixing implicit and explicit waits or scattering fixed sleeps.
Why is mixing an implicit wait and an explicit WebDriverWait in the same test session considered risky?
Their timeouts can combine unpredictably, leading to longer or inconsistent waits
Correct — the official guidance warns the two can interact and inflate wait times.
It causes a compilation error
Wrong — the code compiles; the problem is runtime timing behaviour, not compilation.
Explicit waits are disabled whenever an implicit wait exists
Wrong — both remain active; that is precisely why they can interfere.
It permanently corrupts the browser profile
Wrong — there is no profile corruption; the only effect is on wait timing.
When both are set, their timeouts can combine unpredictably (the documented behaviour is that wait times may add up), producing longer or inconsistent waits that are hard to reason about.
Which method navigates the browser back to the previous page in its history?
driver.navigate().back()
Correct — navigate().back() steps back one page in history.
driver.get("back")
Wrong — get() loads a URL; 'back' is not a URL.
driver.previous()
Wrong — there is no previous() method on WebDriver.
driver.close()
Wrong — close() closes the window; it does not navigate back.
driver.navigate().back() moves one entry back in the browser history, like the browser's Back button.
Clicking a link opens a second browser tab. What must you do before WebDriver can interact with elements in that new tab?
Switch to the new window handle using switchTo().window(handle)
Correct — WebDriver must be told which window to act on; switching focus is required.
Nothing — WebDriver auto-focuses the newest tab
Wrong — WebDriver does not switch automatically; focus stays on the original window.
Call driver.refresh() on the new tab
Wrong — refreshing does not move focus to another window.
Restart the WebDriver session
Wrong — restarting is unnecessary; you simply switch window handles.
WebDriver stays focused on the original window until you switch. Use getWindowHandles() to find the new handle and switchTo().window(handle) to focus it.
A form is rendered inside an iframe:
<iframe id="payment"><input id="card"></iframe>
driver.findElement(By.id("card")) throws NoSuchElementException even though the field is visible. What is the correct fix?
Call driver.switchTo().frame("payment") before locating the field
Correct — you must switch into the iframe context before its elements are findable.
Increase the implicit wait to 60 seconds
Wrong — waiting longer will not help; the element is in a different frame context, not just slow.
Use driver.navigate().refresh()
Wrong — refreshing reloads the page but does not enter the iframe context.
Change By.id to By.name
Wrong — the locator type is not the issue; the element is simply in another frame.
Elements inside an iframe are not in the main document context. You must switchTo().frame(...) first, interact, then switchTo().defaultContent() to return.
A native JavaScript alert pops up. How do you accept (click OK on) it with WebDriver?
driver.switchTo().alert().accept()
Correct — switching to the alert and calling accept() confirms it.
driver.findElement(By.id("ok")).click()
Wrong — native alerts are not DOM elements, so findElement cannot locate the OK button.
driver.navigate().refresh()
Wrong — refreshing does not interact with the alert dialog.
driver.quit()
Wrong — quitting ends the session instead of accepting the alert.
JavaScript alerts are handled through the Alert interface: driver.switchTo().alert().accept() clicks OK; dismiss() clicks Cancel.
For which of the following does WebDriver require a switchTo() call before you can interact? (Choose two.)
Interacting with an element inside an iframe
Correct — you must switchTo().frame(...) to enter the iframe context.
Accepting or dismissing a JavaScript alert
Correct — alerts are handled via switchTo().alert().
Clicking a button in the current page
Wrong — elements in the current document are interacted with directly, no switch needed.
Reading the text of a heading on the current page
Wrong — getText() on a current-document element needs no switchTo().
switchTo() is needed to enter iframes and to handle JavaScript alerts (and to change window focus). A normal button click or reading text in the current document does not.
Which Selenium API is designed for complex user gestures such as hovering over a menu or drag-and-drop?
The Actions class
Correct — Actions provides advanced mouse/keyboard gestures executed via perform().
The Select class
Wrong — Select is only for <select> dropdown elements, not general gestures.
The Alert interface
Wrong — Alert handles JavaScript dialogs, not mouse gestures.
The TakesScreenshot interface
Wrong — TakesScreenshot captures images; it does not perform gestures.
The Actions class builds sequences of low-level interactions (moveToElement, dragAndDrop, clickAndHold) that are then performed with perform().
A test stores a WebElement reference, then the page updates part of the DOM via AJAX. Using the old reference now throws StaleElementReferenceException. What is the correct way to handle this?
Re-locate the element after the DOM change instead of reusing the old reference
Correct — a fresh findElement (often within a wait) gives a valid reference to the new node.
Catch the exception and ignore it so the test continues
Wrong — ignoring it leaves the action unperformed and hides a real synchronisation issue.
Increase the browser window size
Wrong — window size has nothing to do with a stale DOM reference.
Switch from Chrome to Firefox
Wrong — the exception is browser-independent; changing browser does not fix a stale reference.
The reference points to a DOM node that has been removed/replaced. The fix is to re-locate the element (find it again) after the DOM changes, ideally inside an explicit wait.
In test automation, what best describes a 'flaky' test?
A test that passes and fails intermittently without changes to the code under test
Correct — inconsistent results across identical runs is the defining trait of flakiness.
A test that always fails
Wrong — a consistently failing test is reliably broken, not flaky.
A test that runs slowly
Wrong — slowness is a performance concern, not the same as inconsistent results.
A test with no assertions
Wrong — a test without assertions is weak, but that is not what 'flaky' means.
A flaky test produces different results (pass/fail) across runs without any change to the code or system under test, usually due to timing, ordering or environment issues.
Why should automated UI tests generally be independent of one another (no shared order or state)?
So they can run in any order or in parallel, and one failure does not cascade into others
Correct — independence enables parallelism and isolates failures to their real cause.
So that tests can share login state to run faster
Wrong — sharing state creates the very dependencies that make suites fragile and order-sensitive.
Because Selenium cannot run more than one test
Wrong — Selenium runs many tests; independence is a design choice, not a tool limit.
To avoid having to write any assertions
Wrong — independence does not remove the need for assertions; tests still verify outcomes.
Independent tests can run in any order or in parallel, and a failure in one does not cascade into others, which makes results reliable and debugging easier.
Where should a test that creates data (e.g. a new user) clean that data up to keep the suite repeatable?
In a teardown step that runs after the test, whether it passed or failed
Correct — teardown guarantees cleanup so later runs start from a known, repeatable state.
Nowhere — leftover data never affects other tests
Wrong — leftover data commonly causes failures like duplicate-user errors in later runs.
Only manually, by a person, after the whole suite finishes
Wrong — manual cleanup is unreliable and defeats automation; it should be automated in teardown.
Inside the locator definitions in the page object
Wrong — locators describe elements; they are not where data cleanup belongs.
Cleanup belongs in a teardown step (e.g. @AfterMethod / fixture teardown) so each test leaves the system in a known state regardless of pass or fail.
Which of the following practices help reduce flakiness in a Selenium suite? (Choose two.)
Synchronising with explicit waits on meaningful conditions
Correct — waiting for the right condition removes most timing-related flakiness.
Using stable, unique locators (ids / test attributes)
Correct — robust locators avoid breakage from layout or class changes.
Letting tests depend on the data left behind by previous tests
Wrong — shared leftover data creates order dependence and intermittent failures.
Adding fixed Thread.sleep delays to 'be safe'
Wrong — fixed sleeps slow the suite and still fail when the app is slower than the guess.
Explicit waits on real conditions and stable, unique locators directly cut flakiness; running tests in a random shared order or relying on fixed sleeps does the opposite.
A click fails with ElementClickInterceptedException because a sticky cookie banner overlaps the target button. Which is the most robust fix?
Dismiss or scroll past the overlapping banner, then wait until the button is clickable
Correct — handling the intercepting element addresses the real cause and keeps the click realistic.
Wrap the click in a loop that retries thousands of times
Wrong — blind retries waste time and do not remove the overlay that keeps intercepting the click.
Delete the assertion that checks the result
Wrong — removing the assertion hides the failure instead of letting the click succeed.
Lower the implicit wait to zero
Wrong — the issue is an overlapping element, not waiting time; reducing the wait does not help.
The element is covered by another element. The robust fix is to remove/handle the overlay (e.g. dismiss the banner) or scroll/wait until the target is actually clickable, rather than forcing the click blindly.