Interview Insights · Software Tester
Why Every Software Tester Should Practice Explaining Their Code Aloud
Quick summary — Tester code aloud
In automation interviews, I score your explanation of the code more than the code itself. Code can be copied from a tutorial or generated by a tool. An explanation cannot be faked for long. When you walk me through your script, I learn whether you understand locators, synchronisation, assertions and test design. Practising aloud exposes the lines you cannot justify, so you can fix them before the interview instead of during it.
In this guide you will learn:
- Why explaining aloud reveals gaps that silent practice hides
- A real Selenium test in Python with a line-by-line walkthrough
- The four questions interviewers ask about any test script
- How to explain waits and why time.sleep is a warning sign
- A rehearsal routine for walking through your own repository
SECTION 01Why reading your test script silently is not enough
When you read your own code silently, your brain fills in the gaps. You see WebDriverWait and think 'yes, that waits', and you move on. When you have to explain it out loud to another person, you suddenly need to say what it waits for, how long, and what happens if the condition never becomes true. That is where many testers discover they do not fully know.
In an interview, I usually ask you to share your screen and walk me through one test. I am not checking whether it runs. I am checking whether you made the decisions in it. Explaining aloud at home is the only way to find out in advance.
| Line in the script | What weak testers say | What I want to hear | Follow-up question |
|---|---|---|---|
| driver.find_element(By.ID, 'email') | It finds the email box | ID is unique and stable here, so it is the safest locator | What if there is no ID? |
| WebDriverWait(driver, 10).until(...) | It waits 10 seconds | It polls until the condition is true, up to 10 seconds | What happens on timeout? |
| assert 'Dashboard' in driver.title | It checks the test passed | It checks we landed on the right page after login | Is the title enough proof? |
| @pytest.fixture driver | It opens the browser | It sets up and closes the browser for each test | Why yield instead of return? |
import os
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# Full address of the practice site the-internet.herokuapp.com
BASE_URL = os.environ["APP_URL"]
@pytest.fixture
def driver():
drv = webdriver.Chrome()
drv.implicitly_wait(0)
yield drv
drv.quit()
def test_valid_login_shows_secure_area(driver):
driver.get(BASE_URL + "/login")
driver.find_element(By.ID, "username").send_keys("tomsmith")
driver.find_element(By.ID, "password").send_keys("SuperSecretPassword!")
driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click()
flash = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.ID, "flash"))
)
assert "You logged into a secure area!" in flash.text
assert driver.current_url.endswith("/secure")"The fixture creates a Chrome driver, yields it to the test,
and quits it after the test, even if the test fails.
I set implicit wait to zero so I only use explicit waits
and do not mix the two.
The test opens the login page and uses IDs for the fields,
because they are unique on this page. For the button there
is no ID, so I used a short CSS selector on the submit type.
After clicking, I wait until the flash message is visible,
up to ten seconds. If it never appears, a TimeoutException
fails the test with a clear reason.
I then assert two things: the success text, and that the
URL ends with /secure, so I am checking both the message
and that navigation really happened."
This test uses a public practice site so you can run it yourself: pip install selenium pytest, set the APP_URL environment variable to the full address of the-internet.herokuapp.com, then run pytest test_login.py. Reading the base URL from the environment also lets the same test run against staging or a local copy. Recent Selenium versions download a matching ChromeDriver automatically through Selenium Manager, so you only need Chrome installed.
SECTION 02Explaining waits, the part most testers get wrong
Synchronisation is the most common reason automated UI tests are flaky, so it is the area I probe most in interviews. Many candidates have time.sleep(5) scattered through their scripts. That is not automatically wrong in a quick experiment, but in a suite it makes tests slow when the app is fast and still flaky when the app is slow.
When you explain your waits aloud, cover three things: what condition you wait for, why that condition means the app is ready, and what happens if it times out. If you can also explain why mixing implicit and explicit waits causes unpredictable timing, you are ahead of most candidates.
| Wait type | How it works | When to use it | What to say in an interview |
|---|---|---|---|
| time.sleep(n) | Pauses for a fixed time, always | Almost never in a real suite | It wastes time and still fails on slow builds |
| Implicit wait | Retries find_element up to a limit for all lookups | Simple scripts, if used alone | It applies globally and can hide timing issues |
| Explicit wait | Polls one specific condition up to a timeout | Default choice for dynamic pages | It waits only as long as needed for a known state |
| Custom condition | Your own function passed to until() | When built-in conditions do not fit | For example, waiting until a table has rows |
# Flaky and slow
driver.find_element(By.ID, "search").send_keys("laptop")
driver.find_element(By.ID, "go").click()
time.sleep(5)
results = driver.find_elements(By.CSS_SELECTOR, ".result")
assert len(results) > 0
# Stable: wait for the state that proves results loaded
driver.find_element(By.ID, "search").send_keys("laptop")
driver.find_element(By.ID, "go").click()
results = WebDriverWait(driver, 10).until(
EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".result"))
)
assert len(results) > 0from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
def table_has_rows(min_rows):
def condition(driver):
rows = driver.find_elements(By.CSS_SELECTOR, "table tbody tr")
return rows if len(rows) >= min_rows else False
return condition
# usage inside a test
rows = WebDriverWait(driver, 15).until(table_has_rows(5))
assert len(rows) >= 5
# Spoken: until() calls my function repeatedly. It returns
# False while the table is still loading, and returns the
# rows once there are at least five, which ends the wait.
The custom condition is a strong thing to show in an interview because it proves you understand how until() works: it keeps calling a function until that function returns something truthy, or the timeout is reached.
SECTION 03Locators and assertions: the two places your reasoning shows
After waits, the questions I ask most are about locators and assertions. Locators show whether you think about maintenance: a long absolute XPath copied from browser tools will break the moment a developer adds a div. Assertions show whether you think about what 'pass' really means: a test that clicks through a flow and asserts nothing is not a test.
Practise saying, for each locator, why you chose it over the alternatives. For each assertion, say what user-visible outcome it proves, and whether a weaker check could pass while the feature is actually broken.
| Locator choice | Example | Strength | Risk to mention |
|---|---|---|---|
| Dedicated test attribute | [data-testid='checkout-btn'] | Stable, made for tests | Needs developer agreement to add |
| ID | By.ID, 'username' | Fast and usually unique | Some frameworks generate dynamic IDs |
| Short CSS selector | form#login button[type='submit'] | Readable and flexible | Breaks if structure changes heavily |
| Absolute XPath | /html/body/div[2]/div/form/button | Works today | Breaks with any layout change |
# Weak: passes even if the cart is wrong
driver.find_element(By.CSS_SELECTOR, "[data-testid='add-to-cart']").click()
assert driver.find_element(By.ID, "cart").is_displayed()
# Strong: checks the outcome the user cares about
driver.find_element(By.CSS_SELECTOR, "[data-testid='add-to-cart']").click()
count = WebDriverWait(driver, 10).until(
EC.text_to_be_present_in_element((By.ID, "cart-count"), "1")
)
assert count
item = driver.find_element(By.CSS_SELECTOR, "[data-testid='cart-item-name']")
assert item.text == "Wireless Mouse", f"Unexpected item: {item.text}"FOR EVERY TEST YOU SHOW, BE READY FOR:
1. Why this locator and not XPath?
2. What are you waiting for, and why that condition?
3. What exactly does this assertion prove?
4. Could this test pass while the feature is broken?
5. Where does the test data come from?
6. How would this run in CI without a screen?
-> add the --headless=new argument to ChromeOptions
7. Why is this test automated at all, and not manual?
Say each answer aloud in under 30 seconds.
Question four is the one that separates strong automation testers. If you can point at your own assertion and explain how it could give a false pass, and how you would tighten it, you show that you test your tests.
SECTION 04A weekly routine for walking through your own test code
Use your own repository, not a tutorial, for this routine. The goal is to be able to open any test you wrote and explain it calmly in two to three minutes, the way you would in a screen-share interview.
TWO-MINUTE TEST WALKTHROUGH
1. Purpose (15s) -> "This test checks that ..."
2. Setup (20s) -> fixture, browser, test data source
3. Actions (30s) -> each step and why that locator
4. Sync (20s) -> what I wait for and the timeout
5. Asserts (20s) -> what each one proves
6. Limits (15s) -> what this test does NOT cover
Record on your phone. Re-record any part where
you said 'basically' or 'it just works'.LINE JUSTIFICATION SHEET (one test file)
Line | Code (short) | Why it is there
-----|---------------------------|------------------------
1 | fixture driver | ______________________
2 | driver.get(...) | ______________________
3 | find_element(By.ID ...) | ______________________
4 | WebDriverWait(...).until | ______________________
5 | assert ... | ______________________
Any blank in the right column = study or delete.BEFORE YOU SHARE YOUR AUTOMATION REPO
[ ] README says how to install and run the tests
[ ] requirements.txt lists selenium and pytest
[ ] No time.sleep left in the main tests
[ ] No absolute XPath locators
[ ] Every test has at least one meaningful assertion
[ ] Test names describe behaviour, e.g. test_invalid_password_shows_error
[ ] No real passwords or personal data committed
[ ] You can explain every file in the repo
SECTION 05Habits for explaining test code clearly under pressure
These habits make screen-share rounds calmer and more convincing.
- Start with the purpose — Say what behaviour the test protects before reading any code, so the interviewer knows what to look for.
- Narrate decisions, not syntax — Do not read the code word by word. Explain why you chose each locator, wait and assertion.
- Admit copied parts honestly — If a helper came from documentation, say so and explain what it does. Pretending you wrote it invites deeper questions.
- Point out a weakness yourself — Mention one thing you would improve, such as moving locators into a page object. It shows maturity.
- Keep tests small enough to explain — A test that checks one behaviour is easier to explain and debug than one that walks through the whole app.
SECTION 06Interview Q&A — Tester code aloud
Q1Walk me through one automated test from your project.
I start with the behaviour it checks, then explain setup in the fixture, the actions with my locator choices, the explicit wait condition and what each assertion proves. I finish by mentioning what the test does not cover, so the interviewer sees I understand its scope.
Q2What is the difference between implicit and explicit waits in Selenium?
An implicit wait applies to every element lookup and retries until an element is found or the timeout ends. An explicit wait polls one specific condition, such as visibility or clickability, for one element. Mixing them can cause unpredictable wait times, so I prefer explicit waits only.
Q3How do you choose a locator for an element?
I prefer a dedicated test attribute or a unique ID, then a short CSS selector. I use relative XPath only when I need text matching or to move up the DOM, and I avoid absolute XPath because any layout change breaks it.
Q4Why should a test fixture use yield in pytest?
With yield, code before it runs as setup and code after it runs as teardown, even if the test fails. That makes sure the browser is always closed, so failed tests do not leave stray browser processes running.
Q5How would you find out why a test passes locally but fails in CI?
I check the CI logs and screenshots first, then compare the environment: browser version, headless mode, screen size and test data. Timing differences are common, so I review the waits. I also run the test headless locally to reproduce the CI conditions.
SECTION 07Test yourself — Tester code aloud quiz
Five questions. No sign-up.
0 / 5Pick an answer to see why it is right or wrong.
SECTION 08Frequently asked questions
How do I explain my Selenium project in an interview?
Describe the application, what you automated and why, the framework structure such as pytest with page objects, and then walk through one test: setup, locators, waits and assertions. Mention how you ran it and one improvement you would make.
Which automation code questions are asked in software tester interviews?
Common ones cover locator strategies, implicit versus explicit waits, handling dynamic elements, assertions, fixtures or setup methods, page object model, and why tests are flaky. You may also be asked to write or explain a small test live.
Is it okay to use tutorial code in my testing portfolio?
It is fine to learn from tutorials, but your portfolio should contain tests you adapted and understand. Change the application, add your own cases, and be ready to explain every line. Copied code you cannot explain hurts more than it helps.
How can I practise explaining code for a QA automation interview?
Pick one test, set a two-minute timer, and explain it aloud while recording. Cover purpose, setup, actions, waits, assertions and limits. Listen back and re-study any line you could not justify clearly.
What is a flaky test and how do you fix it?
A flaky test passes and fails without code changes. Common causes are poor waits, shared or changing test data, test order dependence and unstable environments. Fixes include explicit waits on the right state, isolated test data and independent tests.
Where can I practise Software Tester interview answers with expert feedback?
Yes. Uncodemy's Software Testing Training Course in Noida (classroom and online) includes live projects, one-to-one mock interviews and resume reviews, so you practise Software Tester interview answers with trainer feedback before the real interview. You can book a free demo class from this page to see how the sessions work.
SECTION 09Related reads
Classroom & online · Noida
Write test code you can explain line by line
Our Software Testing Training Course covers manual testing foundations and Selenium automation with real practice suites, plus screen-share mock rounds where you explain your own code.
Talk to a counsellor for current fees- Selenium with Python and Java
- Waits, locators and asserts
- Code walkthrough mocks
- Weekday & weekend batches