Skip to the questions

QA / Test Engineer · Fresher to 3 years

QA and testing interview questions

The 40 manual and automation testing questions that come up most in QA interviews. Each one has a short answer you can say out loud in about 30 seconds, and the full explanation, with worked examples and code, for when you need it.

Read the quick answers

3 Fundamentals · 5 SDLC & STLC · 5 Types & levels · 5 Test design · 6 Defects · 6 Selenium · 6 Frameworks · 2 API testing · 2 Performance & CIUpdated 27 Oct 2026

When is your interview?

01Testing fundamentals

0/3 got it

Q01Not marked yetFresherAsked oftenConcept

What is software testing, and why does a project need it?

Say this first~30 sec to say

Software testing is checking that software does what it should and finding defects before users do: running the product, and reviewing its requirements and code, against what's expected. Projects need it because a defect costs more to fix the later it's found, failures in production lose money and trust, and testing gives the team evidence that a release is good enough to ship. Testing can show that defects exist; it can't prove there are none.

Could you say it?
Full answer2 min read

What testing gives a project

BenefitExample
Finds defects earlyA wrong GST rate caught in a requirement review costs a short meeting; caught in production, it costs refunds and a hotfix
Builds confidence to releaseA passing regression suite lets the team ship on Friday without guessing
Reduces business riskFailed payments, lost data and security holes are found before customers see them
Proves requirements are metEvery requirement has tests that show it works (question 17)
Meets contracts and regulationsBanking and healthcare apps must keep evidence of testing

Why "the earlier, the cheaper": a mistake in a requirement gets copied into the design, the code and the test cases, and must then be fixed in all of them. Found in production, it also brings support calls, an emergency release and damage to the brand. The multipliers people quote, such as "10 times more per phase", are rough rules of thumb, but the direction holds.

The seven testing principles come up as follow-ups often enough to know by name. In the current ISTQB syllabus they are:

  1. Testing shows the presence, not the absence, of defects.
  2. Exhaustive testing is impossible, so we prioritise.
  3. Early testing saves time and money.
  4. Defects cluster together: a few modules hold most of them.
  5. Tests wear out: repeating the same tests stops finding new bugs (once called the pesticide paradox).
  6. Testing is context dependent: a banking app and a game need different testing.
  7. The absence-of-defects fallacy: a bug-free product that doesn't meet users' needs is still a failure.

Follow-ups

  • QA vs QC vs testing? Quality assurance improves the process to prevent defects (standards, reviews, audits); quality control checks the product to find them; testing is the main quality-control activity.
  • Can testing prove software is bug-free? No. That's principle 1: it reduces the risk of undiscovered defects, it doesn't remove it.
Q02Not marked yetFresherAsked very oftenConcept

How is verification different from validation?

Say this first~25 sec to say

Verification asks, "Are we building the product right?" It checks work products, such as requirements, designs and code, against their specifications, usually without running the software: reviews, walkthroughs and inspections. Validation asks, "Are we building the right product?" It runs the software to confirm it meets users' real needs, through functional, system and acceptance testing. Verification comes first and catches mistakes early; validation proves the result is useful.

Could you say it?
Full answer2 min read
VerificationValidation
QuestionAre we building the product right?Are we building the right product?
Checks againstSpecifications and standardsUser needs and business goals
Runs the code?Usually not: static testingYes: dynamic testing
ActivitiesReviews, walkthroughs, inspections, static analysisFunctional, system and acceptance testing
WhenFrom the first requirement onwardsOnce there is something to run
Typical findingA requirement contradicts the designThe feature works as specified, but users can't find it

On a food delivery app

  • Verification: reviewing the requirement "orders under ₹199 pay a ₹30 delivery fee" against the design and the code, and spotting that the code uses <= instead of <.
  • Validation: placing a real ₹150 order on the test build and checking the fee charged is ₹30, then letting users try it in acceptance testing.

A nuance worth one sentence: strictly, some verification also runs code, such as unit tests checked against a design. But the static vs dynamic split is the answer interviewers expect, so lead with it.

Follow-ups

  • Can a product pass verification but fail validation? Yes. It can match its specification perfectly while the specification describes the wrong thing, like a beautifully built report nobody needs.
  • Where do they sit in the V-Model? Verification activities run down the left side, validation (test execution) up the right side (question 4).

02SDLC, STLC and Agile

0/5 got it

Q04Not marked yetFresherAsked very oftenConcept

Walk through the SDLC phases. How does the V-Model differ from Waterfall?

Say this first~30 sec to say

The SDLC usually runs requirements, design, development, testing, deployment and maintenance. In Waterfall, each phase finishes before the next starts, so testing begins only after coding, when defects are expensive to fix. The V-Model pairs every development phase with a test level: requirements with acceptance testing, system design with system testing, architecture with integration testing and module design with unit testing. Test planning starts alongside requirements, so problems surface earlier.

Could you say it?
Full answer2 min read

The SDLC phases and what each produces

PhaseOutput
Requirement gathering and analysisBusiness or software requirements (BRD, SRS), user stories
DesignHigh-level design (architecture), low-level design (modules, database)
DevelopmentCode, unit tests
TestingTest results, defect reports
DeploymentThe release in production
MaintenanceBug fixes, patches and small enhancements

Some sources add a separate planning phase at the start; the order is what matters.

Waterfall: one straight line, each phase signed off before the next.

Requirements → Design → Development → Testing → Deployment → Maintenance

The V-Model: development goes down the left side; each phase has a matching test level on the right, planned at the same time.

Requirements ──────────────────────────────── Acceptance testing
    System design ──────────────────── System testing
        Architecture design ──── Integration testing
            Module design ── Unit testing
                      Coding
WaterfallV-Model
When testing startsAfter developmentTest planning starts with requirements
Test levelsOne testing phaseFour levels, each tied to a development phase
Cost of late defectsHighLower: many are found in reviews and early planning
FlexibilityLowLow: both assume stable requirements
SuitsSmall projects with fixed, clear requirementsProjects that need strong verification, such as medical or banking systems

Follow-ups

  • When is Waterfall still a fair choice? For short projects whose requirements genuinely won't change, or where regulations demand sign-off at each phase.
  • How does Agile differ? It repeats a small cycle of all these phases every sprint, so testing happens continuously (question 7).
Q05Not marked yetFresherAsked very oftenConcept

What happens in each phase of the STLC, and what does each phase produce?

Say this first~25 sec to say

The STLC has six phases. Requirement analysis finds what's testable. Test planning sets scope, effort and schedule in a test plan. Test case development writes the cases and test data. Environment setup prepares servers and data and smoke-tests the build. Test execution runs the cases and logs defects. Test closure reports results and lessons learned. Each phase has entry criteria to start and exit criteria to finish.

Could you say it?
Full answer2 min read
PhaseEntry criteriaMain activitiesDeliverables
1. Requirement analysisRequirements or user stories availableReview requirements, list questions, decide test types, check automation feasibilityQuestions for the BA, first draft of the RTM, automation feasibility notes
2. Test planningRequirements understoodDefine scope, approach, estimates, roles, schedule, risksTest plan, effort estimate
3. Test case developmentTest plan approvedWrite and review test cases and scripts, prepare test dataTest cases, test data, updated RTM
4. Test environment setupEnvironment needs known; build availableSet up servers, devices and data; smoke-test the buildA ready environment, smoke test results
5. Test executionCases ready, environment ready, smoke test passedRun tests, log defects, retest fixes, run regressionExecution results, defect reports, updated RTM
6. Test cycle closureExecution finished or exit criteria metCheck exit criteria, collect metrics, hold a lessons-learned reviewTest closure report, metrics

Environment setup often runs in parallel with test case development, since different people usually handle them.

Entry and exit criteria are the conditions to start and finish a phase. Typical exit criteria for execution:

  • All planned test cases executed, and every critical case passed.
  • No open blocker or critical defects; any open major ones accepted by the product owner.
  • Regression suite passed on the final build.

Phase names vary between sources: some call phase 3 "test design", or merge closure into reporting. Interviewers care that you know the flow and what each step produces.

Follow-ups

  • SDLC vs STLC? The STLC is the testing part of the SDLC. It starts as soon as requirements exist, not when coding ends.
  • What if the exit criteria aren't met by the release date? Report the gap and the risk; the product owner decides whether to ship, delay or cut scope (question 8).
Q06Not marked yet1–3 yrsAsked oftenConcept

How is a test plan different from a test strategy, and what goes into a test plan?

Say this first~30 sec to say

A test plan says what will be tested, how, by whom and when for one project or release: scope, approach, environments, schedule, roles, risks, entry and exit criteria, and deliverables. A test strategy is higher level: the organisation's or programme's general approach to testing, such as which test levels, types, tools and standards to use, which every plan then follows. The strategy rarely changes; each release gets its own plan.

Could you say it?
Full answer2 min read

What a test plan contains, for a release adding UPI refunds

SectionExample
ScopeIn: UPI payments and refunds on Android and Chrome. Out: card payments, iOS
ApproachManual functional testing, automated regression with Selenium, API checks in Postman
EnvironmentsStaging with the bank's sandbox; Pixel 7 and Galaxy A54 test devices
ScheduleTest design 3–7 Nov, execution 10–21 Nov, user acceptance testing 24–26 Nov
RolesAsha (test lead), Ravi and Priya (manual), Arjun (automation)
Entry criteriaBuild deployed and smoke test passed; test accounts ready
Exit criteriaAll critical cases passed; no open blocker or critical defects
Suspension criteriaStop if the smoke test fails or the sandbox is down
Risks and mitigationsBank sandbox outages: use the mock payment server
DeliverablesTest cases, defect reports, daily status, closure report

This outline comes from the IEEE 829 standard, since replaced by ISO/IEC/IEEE 29119-3, but it's still the one most teams and interviewers use. In Agile teams, the plan is often a single wiki page per release.

Test strategyTest plan
LevelOrganisation or programmeOne project or release
AnswersHow do we test, in general?What, when and who, for this release?
Written byQA manager or architectTest lead
ChangesRarelyEvery release
Example content"Every service has automated API tests; UI regression runs nightly""Arjun automates refund cases by 14 Nov"

Follow-ups

  • Who reviews a test plan? The project manager, product owner and development lead, so the scope and schedule are agreed before testing starts.
  • Is a test plan needed in Agile? Usually a lighter one: sprint-level testing goes into the stories, and a short release plan covers environments, risks and regression.
Q07Not marked yet1–3 yrsAsked oftenConcept

What does a tester do across a Scrum sprint, from sprint planning to the review?

Say this first~30 sec to say

A tester works from the start, not just at the end. In refinement and planning, they question stories, help write acceptance criteria and include testing in estimates. During the sprint, they design tests early, test each story as soon as it's ready, automate checks and keep regression current. At the review, they help demo, and every story must meet the Definition of Done. Starting testing this early is called shift-left.

Could you say it?
Full answer2 min read
Scrum eventWhat the tester does
Backlog refinementAsks "what if?" questions, spots edge cases, helps write acceptance criteria, flags stories that can't be tested
Sprint planningEstimates testing effort, lists test data and environment needs, agrees what's achievable
Daily scrumShares progress and blockers, such as "staging has been down since 10 a.m."
During the sprintDesigns tests while code is written, tests stories as they're ready, explores, logs defects, automates and updates regression
Sprint reviewDemos tested features and notes feedback
RetrospectiveRaises process problems, such as stories reaching testing on the last day

Acceptance criteria a tester helps write

Story: As a shopper, I want to apply a coupon so that I pay less.

Given a cart worth ₹1,200
When Asha applies coupon SAVE10
Then the total becomes ₹1,080
And the message "Coupon applied" appears

Given a cart worth ₹400
When Asha applies coupon SAVE10
Then the total stays ₹400
And the message "Add ₹100 more to use this coupon" appears

This Given/When/Then style comes from behaviour-driven development, and each criterion becomes at least one test.

A typical Definition of Done: code reviewed, unit tests passing, acceptance criteria tested, no open critical defects, regression updated, deployed to staging.

Shift-left means moving testing earlier: reviewing requirements, testing APIs before the UI exists, and running automated tests on every commit. Each defect found earlier is cheaper to fix (question 1).

Follow-ups

  • Who owns quality in Scrum? The whole team. The tester brings testing skills, but developers write unit tests and the team agrees the Definition of Done.
  • What if stories always reach testing on the last day? Raise it in the retrospective: split stories smaller, and test each piece as soon as it's done.
Q08Not marked yet1–3 yrsAsked oftenScenario

The release is tomorrow and there isn't time to run every test. How do you decide what to test?

Say this first~30 sec to say

I'd use risk-based testing. First, smoke-test the build to confirm it's stable. Then test the critical business flows, such as login, search, checkout and payment, and the areas changed in this release, plus anything that has broken before. The automated regression runs in parallel. Low-risk areas get a quick check or none. Finally, I'd tell stakeholders exactly what wasn't tested and the risk, so the release decision is made with full information.

Could you say it?
Full answer2 min read

Step by step

  1. Smoke test the build. If it fails, nothing else matters: report it immediately.
  2. List what changed. Release notes, merged tickets and the code diff show where new defects are most likely.
  3. Rank areas by risk: how likely they are to break, multiplied by how much damage a failure would do.
  4. Test from the top of the list and run the automated regression alongside.
  5. Report clearly before the go/no-go meeting.
AreaChanged in this release?Business impactPlan
Payment and refundsYesVery highFull manual testing plus automated regression
Checkout and couponsYesHighMain paths and the riskiest edge cases
LoginNoHighSmoke test and automated regression only
Order historyNoMediumAutomated regression only
Profile photo uploadNoLowNot tested; listed as a known gap

The status note matters as much as the testing

Release 2.5 test status (27 Oct, 6 p.m.)
Tested: payments, refunds, checkout, coupons; automated regression 312/315 passed.
Open: 1 major defect, a coupon message cut off on small screens (SHOP-244).
Not tested: profile photo upload, notification settings (unchanged since 2.4).
Recommendation: OK to release if SHOP-244 is accepted; test the skipped areas on Monday.

Follow-ups

  • Would you ever recommend not releasing? Yes, if a blocker or critical defect is open in a core flow. The decision belongs to the product owner, but the recommendation should be clear.
  • What happens after the release? Test the skipped areas first, and watch production errors and support tickets closely for a few days.

03Types and levels of testing

0/5 got it

Q09Not marked yetFresherAsked very oftenConcept

Smoke vs sanity testing: how do they differ, and when is each run?

Say this first~30 sec to say

Smoke testing is a broad, shallow check on a new build: do the main features work well enough to start detailed testing? If login or checkout is broken, the build goes back. Sanity testing is a narrow check after a small change or fix: does that area now behave sensibly? Smoke tests are usually scripted and often automated; sanity checks are quick and often unscripted. Teams use the terms inconsistently, and some glossaries treat them as synonyms.

Could you say it?
Full answer2 min read
Smoke testingSanity testing
QuestionIs this build stable enough to test?Does this change or fix work, and is the area sane?
ScopeWide and shallow: every critical feature, lightlyNarrow: the changed area and what's next to it
WhenOn every new build, before anything elseAfter a bug fix or small change, often late in a cycle
Scripted?Usually, and often automated in CIOften unscripted
If it failsThe build is rejectedThe fix is rejected, or the area needs more testing
Also calledBuild verification testingA quick, focused subset of regression

On a food delivery app, build 2.4.0

  • Smoke: the app opens, a user can log in, search for a restaurant, add an item, and pay with a test card. Ten minutes, all critical paths, nothing in depth.
  • Sanity, after a fix for "coupon not applied": apply SAVE10, check the total, remove the coupon, apply an expired one. Just the coupon area.

Why the terms get muddled: the ISTQB glossary lists sanity test as a synonym for smoke test, while many teams use the distinction above. In an interview, give the common usage and mention that some teams use the words interchangeably.

Follow-ups

  • Is smoke testing part of regression? It's a small, fast subset of the most critical regression checks, run first so a broken build doesn't waste anyone's time.
  • Who runs them? Smoke tests often run automatically in the CI pipeline on every build (question 40); a tester usually does the sanity check on a fix.
Q10Not marked yetFresherAsked very oftenConcept

Retesting vs regression testing: what is the difference, and when do you do each?

Say this first~25 sec to say

Retesting, also called confirmation testing, runs the same test that failed, after the fix, to confirm the defect is gone. Regression testing checks that a change hasn't broken anything that used to work, often in areas nobody touched directly. Retesting targets specific known defects; regression is a repeated suite, which makes it the best candidate for automation. Usually you retest the fix first, then run regression around it.

Could you say it?
Full answer1 min read

One fix, both activities

Bug SHOP-231, "Coupon SAVE10 isn't applied to carts above ₹1,000", has been fixed in build 2.4.1.

  • Retesting: repeat the exact steps and data from the bug report on build 2.4.1. The total now drops by 10%, so the bug is verified.
  • Regression: check what the fix could have disturbed: other coupons, carts at exactly ₹1,000, the payment amount, GST on the invoice, and order history.
RetestingRegression testing
PurposeConfirm a specific defect is fixedConfirm nothing else broke
Tests runThe failed test casesA suite of previously passing tests
Planned in advance?No: it depends on which defects get fixedYes: a maintained suite
AutomationPossible, if the failed test is already automatedThe main target of automation
WhenAs soon as the fix is deployedAfter retesting, and before every release

Follow-ups

  • Which comes first? Retesting. There's little point running a long regression on a build where the fix itself doesn't work.
  • How do you choose regression scope when time is short? By risk: the changed module, the features that depend on it, and the critical business flows (question 8).
Q11Not marked yetFresherAsked very oftenConcept

What are unit, integration, system and acceptance testing, and who usually does each?

Say this first~30 sec to say

They're test levels with widening scope. Unit testing checks one function or class in isolation, written by developers. Integration testing checks that modules work together, such as the cart calling the payment service, by developers or testers. System testing checks the complete application end to end against the requirements, by the QA team. Acceptance testing, or UAT, checks it meets business needs, by users, clients or product owners, before go-live.

Could you say it?
Full answer2 min read
LevelScopeUsually done byExample on a shopping appTypical tools
UnitOne function or classDeveloperscalculateGst(1000) returns 180JUnit, TestNG, pytest, Jest
IntegrationTwo or more modules, or a module and an external serviceDevelopers and testersThe order service saves an order and the inventory service reduces stockPostman, RestAssured, test containers
SystemThe whole application, end to endIndependent testers (QA team)Search, add to cart, pay, receive an invoice emailSelenium, manual test cases
Acceptance (UAT)Business fit, in realistic conditionsUsers, clients, product ownersThe finance team confirms invoices match their accounting rulesManual, checklists

Integration approaches, a common follow-up:

  • Big bang: combine everything at once and test. Simple, but failures are hard to trace.
  • Top-down: start from the top modules and replace missing lower ones with stubs, which return canned answers.
  • Bottom-up: start from the lowest modules and call them through drivers, small test programs standing in for the callers.
  • Sandwich (hybrid): both directions at once.

Kinds of acceptance testing: alpha testing is done by internal users at the developer's site; beta testing by real customers in their own environment before general release.

Follow-ups

  • Stub vs driver? A stub stands in for a module being called; a driver stands in for the module doing the calling.
  • Where do API tests fit? Mostly at the integration and system levels: they check services working together without the UI.
Q12Not marked yetFresherAsked very oftenConcept

Black-box vs white-box testing: how do they differ, and where does grey-box fit?

Say this first~30 sec to say

Black-box testing designs tests from the requirements and behaviour, without looking at the code: inputs go in, outputs are checked. Its techniques include equivalence partitioning, boundary values and decision tables. White-box testing designs tests from the code's internal structure, aiming to cover its statements, branches and paths; developers usually do it. Grey-box testing uses partial knowledge of the internals, such as the database schema or the API, to design sharper black-box tests.

Could you say it?
Full answer2 min read
Black-boxWhite-boxGrey-box
Based onRequirements, specificationsCode structureRequirements plus some internal knowledge
Needs code accessNoYesPartly: schema, APIs, architecture
Usually done byTesters, usersDevelopersTesters
TechniquesEquivalence partitioning, boundary values, decision tables, state transitionsStatement, branch and path coverageDatabase checks, API-level tests, testing known integration points
FindsMissing or wrong behaviourUntested code, dead code, logic errorsData and integration defects

White-box in practice: statement vs branch coverage

Java
double finalPrice(double price, boolean hasCoupon) {
    if (hasCoupon) {
        price = price - 50;
    }
    return price;
}

The single test finalPrice(500, true) runs every statement, so it reaches 100% statement coverage, but it only takes the true branch of the if: 50% branch coverage. Adding finalPrice(500, false) covers both branches. Branch coverage is the stronger measure.

Grey-box in practice: after placing an order through the UI, you query the orders table to check the status is PLACED and the amount matches, because you know how the data is stored.

Follow-ups

  • Which kind do testers do most? Black-box. White-box testing mostly happens through developers' unit tests and code coverage reports.
  • Is grey-box just a mix of the other two? In practice, yes: black-box tests designed with a little knowledge of the internals.
Q13Not marked yetFresherAsked very oftenConcept

Functional vs non-functional testing: how do they differ? Give an example of each

Say this first~25 sec to say

Functional testing checks what the system does, feature by feature, against its requirements: for example, "applying coupon SAVE10 takes 10% off the cart". Non-functional testing checks how well it does it: performance ("the checkout page loads in under 2 seconds with 5,000 users online"), security, usability, compatibility across browsers and devices, reliability and accessibility. A feature can pass every functional test and still fail non-functionally.

Could you say it?
Full answer2 min read
TypeChecksExample on a banking app
FunctionalFeatures against requirementsTransferring ₹5,000 reduces the balance by ₹5,000 and shows it in the statement
PerformanceSpeed and capacity under loadThe balance page responds within 2 seconds with 10,000 users logged in
SecurityProtection of data and accessAnother customer's account can't be opened by changing the ID in the URL
UsabilityEase of useA first-time user can make a transfer without help
CompatibilityBrowsers, devices, operating systemsThe app works on Chrome, Safari and Android 12 to 15
AccessibilityUse by people with disabilitiesA screen reader announces every button; the app works with a keyboard alone
Reliability and recoveryBehaviour over time and after failuresAfter a server restart, an interrupted transfer isn't applied twice

Functional testing types you'll hear: unit, integration, system, smoke, sanity, regression and acceptance testing. Non-functional: performance (load, stress, spike, endurance; question 39), security, usability, compatibility, accessibility and localisation.

Why non-functional requirements need questions: they're often missing from the specification. A tester should ask how fast is fast enough, how many users to expect, and which browsers and devices matter, then turn the answers into measurable targets.

Follow-ups

  • Is accessibility functional or non-functional? Usually classed as non-functional, a quality attribute, though laws and contracts can make it a hard requirement.
  • Can the same test be both? One session can cover both, but the checks differ: "the transfer works" is functional; "it completes in under 2 seconds" is non-functional.

04Test design

0/5 got it

Q14Not marked yetFresherAsked very oftenPractical

Write test cases for a login page with email and password fields, "Remember me" and "Forgot password"

Say this first~30 sec to say

I'd group cases into positive and negative. Positive: valid email and password log in; "Remember me" keeps the user logged in after reopening the browser; "Forgot password" sends a working reset link. Negative: wrong password, unregistered email, blank fields, badly formatted email, and lockout after repeated failures. Then UI and security: the password is masked, errors don't reveal which field was wrong, and logout, the back button and session expiry behave correctly.

Could you say it?
Full answer4 min read

First, ask a few questions: how many failed attempts trigger a lockout, and for how long? What are the password rules? How long does "Remember me" last? Which browsers and devices matter? Good testers clarify before writing cases.

IDScenarioTest data and stepsExpected resultType
TC01Valid loginRegistered email and correct password, click "Log in"Dashboard opens with "Welcome, Asha"Positive
TC02Email is case-insensitive[email protected] with the correct passwordLogs in (if the requirement says emails ignore case)Positive
TC03Enter key submitsFill both fields, press EnterSame as clicking "Log in"Positive
TC04Wrong passwordRegistered email, wrong password"Invalid email or password"; stays on the login pageNegative
TC05Unregistered email[email protected], any passwordThe same generic message as TC04Negative
TC06Both fields blankClick "Log in""Email is required" and "Password is required"Negative
TC07Invalid email formatasha@, asha.example.com"Enter a valid email address"Negative
TC08Password is case-sensitiveCorrect password typed in a different caseLogin failsNegative
TC09Account lockout5 wrong passwords in a rowAccount locked for the agreed time; a 6th attempt with the right password also failsNegative
TC10Password maskedType in the password fieldDots shown; a "show" toggle (if present) reveals itUI
TC11"Remember me" tickedLog in, close and reopen the browserStill logged inPositive
TC12"Remember me" not tickedLog in, close and reopen the browserLogin page shownPositive
TC13Forgot passwordClick the link, enter a registered emailReset email arrives; the link works once and expires as specifiedPositive
TC14Logout and back buttonLog out, press the browser's back buttonLogin page, not the cached dashboardSecurity
TC15Session expiryStay idle past the timeout, then click somethingRedirected to log in againSecurity
TC16SQL injection attemptEmail ' OR '1'='1Rejected as an invalid login; no error page or data shownSecurity

One case written in full: this is what a test management tool, or an interviewer asking for "one detailed case", expects.

ID:            TC04
Title:         Login fails with a wrong password
Priority:      High
Preconditions: User [email protected] exists and isn't locked
Steps:         1. Open https://staging.example.com/login
               2. Enter [email protected] in Email
               3. Enter Wrong@123 in Password
               4. Click "Log in"
Expected:      "Invalid email or password" appears; user stays on the login page;
               the failed-attempt count goes up by one

Positive vs negative testing: positive tests use valid inputs and check the system works; negative tests use invalid or unexpected inputs and check it fails gracefully, with a clear message and no crash.

Follow-ups

  • Why the same message for a wrong password and an unknown email? A different message tells an attacker which emails are registered.
  • What would you test that isn't functional? Load time, behaviour on slow networks, keyboard-only use and screen-reader labels, HTTPS, and rate limiting against password guessing.
Q15Not marked yetFresherAsked very oftenPractical

An age field accepts whole numbers from 18 to 60. Derive test inputs using equivalence partitioning and boundary value analysis

Say this first~30 sec to say

Equivalence partitioning splits inputs into groups the system should treat the same way and tests one value from each: below the range (say 10), valid (35) and above the range (75), plus invalid types such as blank, letters, decimals and negatives. Boundary value analysis tests each edge and its neighbours, where off-by-one bugs hide. With two-value BVA, that's 17, 18, 60 and 61; three-value BVA adds 19 and 59.

Could you say it?
Full answer3 min read

Step 1: the partitions

PartitionValuesRepresentativeExpected
Too young17 and below10Error: "Age must be between 18 and 60"
Valid18 to 6035Accepted
Too old61 and above75Error
Not a whole numberDecimals25.5Error
Not a numberLetters, symbolsabc, #Error, or can't be typed
EmptyBlank(nothing)"Age is required"
NegativeBelow zero-5Error

Step 2: the boundaries

  too young           │            valid            │        too old
 …  16   17           │   18   19   …   59   60     │   61   62  …
                lower boundary                upper boundary
ConventionLower boundaryUpper boundaryValues to test
Two-value BVA (each boundary and its outside neighbour)17, 1860, 6117, 18, 60, 61
Three-value BVA (each boundary and both neighbours)17, 18, 1959, 60, 6117, 18, 19, 59, 60, 61

This answer uses two-value BVA; the ISTQB syllabus describes both, so say which one you're using.

Why boundaries matter: one value catches the bug

Java
static boolean isValidAge(int age) {
    return age > 18 && age <= 60;     // bug: should be age >= 18
}

// isValidAge(35)  -> true   the partition value passes, so EP alone misses the bug
// isValidAge(18)  -> false  only the boundary value exposes it
// isValidAge(17)  -> false
// isValidAge(60)  -> true
// isValidAge(61)  -> false

The final set, two-value BVA plus the invalid-type partitions: 17, 18, 60, 61, 25.5, abc, blank and -5. The boundary values already cover the three numeric partitions (17 is too young, 18 and 60 valid, 61 too old), so 10, 35 and 75 add little; many testers still include 35 as a "typical" value.

Follow-ups

  • What if the age is picked from a dropdown? The UI can't send invalid values, but the API behind it still can, so test the boundaries there (question 37).
  • What's a decision table? A black-box technique for combinations of conditions, such as "member and cart above ₹1,000", where each column of the table becomes a test.
Q16Not marked yetFresherAsked very oftenConcept

Test scenario vs test case: what is the difference?

Say this first~30 sec to say

A test scenario is a one-line statement of what to test, taken from a requirement or user story: "Check that a shopper can apply a coupon at checkout." A test case is the detailed how: an ID, preconditions, steps, test data and the expected result, precise enough that anyone running it reaches the same verdict. One scenario usually becomes several test cases: a valid coupon, an expired one, a cart below the minimum value, and so on.

Could you say it?
Full answer2 min read

One scenario, several cases

Scenario TS-05: Check that a shopper can apply a coupon at checkout.

CaseTitleTest dataExpected result
TC-05-1Valid couponSAVE10 on a ₹1,200 cartTotal ₹1,080, "Coupon applied"
TC-05-2Expired couponDIWALI24"This coupon has expired"; total unchanged
TC-05-3Cart below the minimumSAVE10 on a ₹400 cart"Add ₹100 more to use this coupon"
TC-05-4Invalid codeSAVE99"Invalid coupon code"
TC-05-5Code with lowercase letterssave10Applied, if codes ignore case per the requirement
TC-05-6Removing a couponApply SAVE10, then remove itTotal back to ₹1,200
Test scenarioTest case
AnswersWhat to testHow to test it, and what should happen
DetailOne linePreconditions, steps, data, expected result
Derived fromRequirements, user storiesScenarios
NumberFewMany per scenario
Effort to maintainLowHigher
Best forCoverage planning, exploratory and Agile teamsRegression, audits, new team members, automation

Related terms: a test script is a test case written as code; a test suite is a group of test cases run together, such as "checkout regression".

Follow-ups

  • Do Agile teams still write detailed test cases? Often only for regression and critical flows; elsewhere they work from scenarios, checklists and the acceptance criteria.
  • What makes a good test case? One clear objective, exact data, and an expected result that leaves no room for opinion.
Q17Not marked yetFresherAsked oftenConcept

What is a requirement traceability matrix (RTM), and why keep one?

Say this first~25 sec to say

An RTM is a table that maps each requirement to the test cases covering it, and usually to their latest result and any defects. It proves coverage: every requirement has at least one test, and every test traces back to a requirement. It also supports impact analysis: when a requirement changes, you see exactly which tests to update and rerun. Traceability can be forward, backward or both.

Could you say it?
Full answer2 min read
Req IDRequirementTest casesLatest resultDefects
REQ-101A valid coupon reduces the totalTC-05-1, TC-05-5Pass
REQ-102An expired coupon shows an errorTC-05-2FailSHOP-231
REQ-103Coupons need a cart of at least ₹500TC-05-3Pass
REQ-104Only one coupon per order(none)Not covered

The last row is the point of the exercise: REQ-104 has no test, and the RTM makes that gap impossible to miss.

TypeDirectionShows
ForwardRequirements → testsEvery requirement is tested
BackwardTests → requirementsEvery test has a reason to exist; finds tests for removed features
BidirectionalBothFull coverage and impact analysis

Where it lives: a spreadsheet in small teams; in larger ones, links between Jira stories and test management tools such as Xray, Zephyr or TestRail build it automatically. It's started in the requirement analysis phase of the STLC and updated through execution (question 5).

Follow-ups

  • How does an RTM help when a requirement changes? Find the requirement's row, and you have the list of test cases to update and rerun.
  • Is 100% requirement coverage enough? No. It proves each requirement has a test, not that the tests are good; a single happy-path case "covers" a requirement too.
Q18Not marked yetFresherAsked oftenScenario

You're asked to test a feature that has no requirement document. How do you start?

Say this first~30 sec to say

I'd find the expected behaviour from other sources: talk to the product owner, BA and developers; read the user story, tickets, designs and any API documentation; and use the existing app and similar products. I'd write down my assumptions and open questions, then explore the feature in short, focused sessions to learn how it behaves, turn what I learn into scenarios, and get them confirmed by the product owner before treating them as expected results.

Could you say it?
Full answer2 min read

Where expected behaviour hides

SourceWhat it tells you
Product owner, BAThe purpose of the feature, who uses it, what "done" means
DevelopersHow it works, known limits, what changed
Tickets, user stories, emailsFragments of the rules and acceptance criteria
Designs (Figma), API documentationFields, messages, flows, limits
The existing app and older versionsCurrent behaviour users rely on
Competitors and similar productsConventions users expect

Questions worth asking

  • Who will use it, and what problem does it solve for them?
  • What inputs are allowed, and what are the limits?
  • What should happen when something goes wrong?
  • Which platforms, browsers and roles are in scope? What's explicitly out of scope?

Exploratory testing with charters: time-boxed sessions, each with a mission, such as "Explore coupon entry with unusual codes, for 45 minutes, to discover how validation works." Note what you find, then turn it into scenarios.

The deliverable: a short list of scenarios and assumptions, such as "Assumption: coupon codes aren't case-sensitive", sent to the product owner to confirm. Once confirmed, it becomes the requirement you test against.

Follow-ups

  • How would you test a pen? The same skill: ask first (what kind of pen, for whom, for what), then cover function (it writes, the ink flows), limits (paper types, temperatures), durability (drops, clicks) and negative cases (writing upside down).
  • What is exploratory testing? Learning, test design and execution done at the same time, guided by a charter rather than a script.

05Defect management

0/6 got it

Q19Not marked yetFresherAsked very oftenConcept

Severity vs priority: how do they differ? Give a high-severity, low-priority bug and the reverse

Say this first~30 sec to say

Severity is how badly a defect affects the system: a crash or data loss is critical, a typo is minor. Priority is how urgently it should be fixed, based on business needs and deadlines. Testers usually set severity; the product owner or lead sets priority. High severity, low priority: the app crashes when an admin exports a ten-year report, a feature used once a year. Low severity, high priority: the company's name is misspelt on the home page.

Could you say it?
Full answer2 min read
SeverityPriority
MeasuresTechnical impact on the systemUrgency of the fix for the business
Set byUsually the testerProduct owner, project manager or test lead
Typical scaleBlocker or critical, major, minor, trivialP1 (fix now), P2 (this release), P3 (later)
Changes whenThe impact turns out differentDeadlines, customers or plans change

The four combinations

High priorityLow priority
High severityUPI payments fail for every userThe app crashes when exporting a ten-year report; one admin uses it once a year, and a workaround exists
Low severityThe brand name is misspelt on the home page the day before a launchA typo on an old FAQ page

Why they diverge: severity is about the software, priority about the business. A crash in an obscure corner hurts less than a typo every visitor sees on launch day.

Follow-ups

  • Can priority change while severity stays the same? Yes. A minor layout bug becomes P1 when a big client's demo is tomorrow.
  • What makes a defect a blocker? It stops testing or a core business flow entirely, with no workaround, such as a build where login always fails.
Q20Not marked yetFresherAsked very oftenConcept

Walk through the bug life cycle, from a newly logged bug to closure

Say this first~30 sec to say

A newly logged bug is New. A lead reviews it and assigns it to a developer, who works on it (Open, or In progress) and marks it Fixed. The tester retests it: if the fix works, it's Verified and then Closed; if not, it's Reopened and goes back to the developer. Along the way, a bug can be Rejected as not a bug, marked Duplicate, or Deferred to a later release. Exact status names depend on the tool and team.

Could you say it?
Full answer2 min read
New ──▶ Assigned ──▶ Open ──▶ Fixed ──▶ Retest ──┬──▶ Verified ──▶ Closed
 │         │                                     │
 │         │                                     └──▶ Reopened ──▶ Assigned (again)
 │         ├──▶ Rejected       (not a bug, or works as designed)
 │         ├──▶ Duplicate      (already reported)
 │         └──▶ Deferred       (fix in a later release)
 └──▶ Needs more info / Cannot reproduce
StatusMeaningMoved there by
NewLogged, not yet reviewedTester
AssignedAccepted and given to a developerLead or manager
Open (In progress)The developer is working on itDeveloper
FixedCode changed; waiting for a buildDeveloper
Retest (Ready for test)The fix is on the test environmentDeveloper or build process
VerifiedThe tester confirmed the fixTester
ClosedDone; no further actionTester or lead
ReopenedThe fix didn't work, or the bug came backTester
RejectedNot a defectLead or developer, ideally agreed with the tester
DuplicateSame as an existing bugLead or tester
DeferredReal, but postponedProduct owner

Tools differ: Jira's simplest workflow is just To Do, In Progress and Done, and every team customises it. In an interview, explain the flow and the decision points rather than reciting one fixed list.

Follow-ups

  • Rejected vs deferred? Rejected means it isn't a defect; deferred means it is, but it won't be fixed in this release.
  • A closed bug appears again in a later release. Reopen it or log a new one? Teams differ; many log a new bug linked to the old one, so release history stays accurate.
Q21Not marked yetFresherAsked very oftenScenario

A developer says the bug you raised isn't a bug. What do you do?

Say this first~30 sec to say

First, I'd recheck it myself against the requirement, acceptance criteria or design, and reproduce it again. If I still think it's a bug, I'd share evidence: exact steps, data, a recording, and the line of the requirement it breaks. Then I'd discuss it calmly, focusing on the impact on users, and listen, since the developer may know something I don't. If we still disagree, the product owner or BA decides, and I record the outcome in the ticket.

Could you say it?
Full answer2 min read

Step by step

  1. Recheck. Is it really against the requirement, or against my assumption? Is my build, data or environment unusual?
  2. Gather evidence. Steps, test data, build number, screenshots or a video, logs, and the exact requirement or design it contradicts.
  3. Understand their view. "Not a bug" often means one of the reasons below.
  4. Discuss, don't argue. Keep it about the product and its users, not about who's right.
  5. Escalate to the owner of the requirement if you still disagree: the product owner or BA decides what the product should do.
  6. Record the decision in the ticket: fixed, rejected as working as designed, or converted into an enhancement.
What "not a bug" can meanWhat to do
It works as designed; the requirement differs from your readingAsk the BA; if the design is wrong for users, raise it as an enhancement
An environment or configuration problemCheck whether it happens on other environments
Bad test dataRetry with clean data
It's a duplicate or a known limitationLink the existing ticket
It can't be reproducedSee question 23

A comment that keeps things calm and specific

Hi Ravi, on build 2.4.1 (staging, Chrome on Windows 11), applying SAVE10 to a ₹1,200
cart leaves the total at ₹1,200. Story SHOP-88, acceptance criterion 2, says carts
above ₹1,000 get 10% off. Recording and console log attached. Could you take a look,
or let me know if the rule has changed?

Follow-ups

  • What if the developer is right? Thank them, close or reject the ticket, and fix your test case or understanding. Being right isn't the goal; the product is.
  • What if it keeps happening with one developer? Agree on acceptance criteria before development starts, so disagreements are settled in refinement instead of in tickets.
Q22Not marked yetFresherAsked oftenPractical

Write a bug report for this defect: on the checkout page, clicking "Apply coupon" does nothing

Say this first~25 sec to say

A good report lets a developer reproduce the bug without asking me anything. It has a clear title naming the feature and the symptom, the environment and build, preconditions, numbered steps to reproduce with exact test data, expected vs actual result, severity and priority, how often it happens, and evidence: a screenshot or recording, plus any console errors or failed network calls. One defect per report.

Could you say it?
Full answer2 min read
Title:          Checkout: "Apply coupon" does nothing for a valid code (SAVE10)
ID:             SHOP-231
Environment:    Staging, build 2.4.1; Chrome on Windows 11; also on Android 14 app
Preconditions:  Logged in as [email protected]; cart total ₹1,200 (2 items)

Steps to reproduce:
  1. Open the cart and click "Checkout".
  2. In "Coupon code", type SAVE10.
  3. Click "Apply coupon".

Expected:       The total changes to ₹1,080 and "Coupon applied" appears.
Actual:         Nothing happens: no message, the total stays ₹1,200,
                and no network request is sent (DevTools, Network tab).
Console error:  Uncaught TypeError: Cannot read properties of null (reading 'value')
                    at applyCoupon (coupon.js:42)
Frequency:      5 out of 5 attempts
Severity:       Major (customers can't use any coupon; checkout itself works)
Priority:       High (the festive sale starts on Friday)
Attachments:    apply-coupon.mp4, console.png
Notes:          Works on build 2.4.0. Fails with every code tried (SAVE10, WELCOME50).

Why each part is there

FieldPurpose
TitleFindable and clear on its own: where, what, when
Environment and buildThe first thing a developer checks when they can't reproduce it
Preconditions and test dataBugs often depend on the user, cart or data
StepsNumbered, minimal, one action each
Expected vs actualMakes the defect undeniable, and ties it to a requirement
Severity and priorityHelps the team decide when to fix it (question 19)
EvidenceA video and the console error can save a developer an hour

Isolate before you report: try another coupon, another browser and the previous build, and open the browser's DevTools. "No request sent" points to the front end; a request that returns a 500 error points to the server. Those two lines in the report send it to the right developer immediately.

Follow-ups

  • What makes a bug title bad? Vague words like "Coupon not working" or "Checkout issue": they don't say where, what or under which conditions.
  • Should one report hold several bugs? No. Each defect gets its own report, so each can be assigned, fixed and verified separately.
Q23Not marked yetFresherAsked oftenScenario

A developer can't reproduce a bug you reported. What do you do?

Say this first~30 sec to say

First, I'd reproduce it again myself in a fresh session and capture exact steps, test data, build, environment and time, plus a recording and logs. Then I'd look for what differs between my setup and the developer's: build, browser version, user role, data, feature flags, cache, network or device. If it's still unclear, I'd show it on my machine or pair with the developer. If it's intermittent, I'd record how often it happens and under what conditions.

Could you say it?
Full answer2 min read

Differences that commonly hide a bug

DifferenceExample
Build or branchThe developer tests their local branch, which already has another fix
Test dataOnly users created before 2024 have the old address format
User role and permissionsFails only for "seller" accounts
Browser, version, deviceFails on Safari or on a small Android screen
Feature flags or configurationThe new checkout is switched on only in staging
Cache, cookies, sessionFails only after logging out and back in
Network and timingFails on slow connections, or when two clicks arrive quickly
Time and localeFails after midnight UTC, or with the Hindi locale

Evidence to attach

  • A screen recording from a fresh session, showing the steps from the start.
  • The browser console log and a HAR file of network traffic (DevTools, Network tab, export). HAR files contain cookies and tokens, so remove them or share the file privately.
  • The exact time of the failure and any request IDs, so the developer can find the matching server logs.
  • For mobile apps, device logs, such as adb logcat on Android.

If neither of you can reproduce it: record every attempt and condition in the ticket, mark it Cannot reproduce (or Needs more info), and keep watching. Intermittent bugs often reappear under load or in production, and the earlier notes make them much faster to fix then.

Follow-ups

  • What does "intermittent" tell you? That the cause depends on something variable: timing, data, concurrency or the environment. Note the frequency, such as "3 out of 10 attempts".
  • Should you close the ticket? Not without agreement. A bug that can't be reproduced today isn't proof that it's fixed.
Q24Not marked yet1–3 yrsAsked oftenScenario

A bug you missed in testing is reported from production. What do you do?

Say this first~30 sec to say

First, help contain it: reproduce it, assess how many users it affects, and support the hotfix by testing the fix and the areas around it. Don't start with blame. Then do a blameless root-cause analysis: was the scenario missing from our tests, skipped for lack of time, impossible in our environment, or caused by production data? Finally, prevent a repeat: add the case to the regression suite, automate it if possible, and fix the process gap.

Could you say it?
Full answer2 min read

1. Contain

  • Reproduce it on a production-like environment; note the affected users, platforms and data.
  • Help judge severity, so the team can decide on a hotfix, rollback or feature flag.
  • Test the hotfix quickly but properly: retest the bug and run a focused regression around it.

2. Find the root cause, without blame

Why it was missedExample fix
No test covered the scenarioAdd it, and review requirements for similar gaps
A test existed but wasn't runRevisit risk-based selection; automate it so it always runs
The test environment couldn't show itMake staging closer to production: data volumes, configuration, integrations
Production data differedAdd realistic and edge-case test data
The requirement was ambiguousInvolve testers earlier, in refinement

The five whys, on a real-looking case

Customers were charged twice for one order.
1. Why?  The app retried the payment after a timeout and created a second charge.
2. Why wasn't it caught?  No test covered payment-gateway timeouts.
3. Why not?  The bank's sandbox in staging never times out.
4. Why?  We had no way to simulate a slow gateway.
5. Action: a mock gateway with configurable delays, and a regression test for timeouts.

3. Prevent a repeat: add the scenario to the regression suite, update the RTM, share the lessons with the team, and track defect leakage: the share of defects found after release, such as 3 of 60, or 5%.

In the interview, own it. "I'd acknowledge we missed it and focus on fixing the gap" sounds far stronger than explaining why it wasn't your fault.

Follow-ups

  • Is a production bug always the tester's fault? No. Quality is the team's responsibility; the useful question is which part of the process let it through.
  • What is defect leakage? Defects found after release divided by all defects found, as a percentage; lower is better.

06Selenium WebDriver

0/6 got it

Q25Not marked yetFresherAsked very oftenConcept

What is Selenium WebDriver, and how does a command in your test reach the browser?

Say this first~30 sec to say

Selenium WebDriver is an open-source library for automating real browsers from code. My Java test calls the client library, which turns each command, such as findElement or click, into an HTTP request using the W3C WebDriver protocol. A browser driver, such as ChromeDriver or GeckoDriver, receives it, controls the browser natively and returns the result. The Selenium project also includes IDE, for record and playback, and Grid, for running tests in parallel on many machines.

Could you say it?
Full answer3 min read
Your test (Java + TestNG)
   │   driver.findElement(By.id("email"))
   ▼
Selenium client library (Java bindings)
   │   HTTP + JSON, W3C WebDriver protocol
   ▼
Browser driver (chromedriver, geckodriver, msedgedriver, safaridriver)
   │   native automation
   ▼
Browser (Chrome, Firefox, Edge, Safari)

A first test

Java
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class FirstTest {
    public static void main(String[] args) {
        WebDriver driver = new ChromeDriver();        // Selenium Manager finds or downloads chromedriver
        try {
            driver.get("https://example.com/");
            System.out.println(driver.getTitle());                                 // Example Domain
            System.out.println(driver.findElement(By.tagName("h1")).getText());    // Example Domain
        } finally {
            driver.quit();                            // ends the session and closes the browser
        }
    }
}

What travels over the wire for findElement(By.id("email"))

POST /session/{session id}/element
{"using": "css selector", "value": "#email"}

Response:
{"value": {"element-6066-11e4-a52e-4f735466cecf": "f.8C2A…d.3"}}

The W3C protocol defines five locator strategies: CSS selector, XPath, link text, partial link text and tag name. Selenium's Java client sends By.id and By.name as CSS selectors.

Selenium componentWhat it is
WebDriverThe API and drivers for controlling browsers from code
IDEA browser extension that records and plays back clicks; good for quick checks and learning
GridRuns tests on many machines and browsers in parallel

What changed in Selenium 4: the client speaks the W3C WebDriver standard instead of the older JSON Wire Protocol, and Selenium Manager (from 4.6) downloads the right driver automatically. Old tutorials that start with System.setProperty("webdriver.chrome.driver", "C:\\drivers\\chromedriver.exe") are no longer needed.

Follow-ups

  • What can't Selenium test? Desktop apps, CAPTCHAs (by design), image content and native mobile apps on its own; Appium covers mobile using the same WebDriver protocol.
  • Does Selenium produce reports? No. Reports come from the test framework, such as TestNG, or a tool like Allure.
Q26Not marked yetFresherAsked very oftenConcept

Which locator would you choose for an element, and why do testers avoid absolute XPath?

Say this first~30 sec to say

I'd pick the most stable, unique attribute available: an id, then a name or a dedicated test attribute such as data-testid, then a short CSS selector, and relative XPath when I need to match text or move up the page structure. I avoid absolute XPath, like /html/body/div/form/input[2], because it spells out the whole path from the root: one added wrapper or reordered field breaks it. Auto-generated IDs and classes break just as easily.

Could you say it?
Full answer2 min read

The page used in the examples

HTML
<div class="page">
  <form id="login-form">
    <input id="email" name="email" type="email" data-testid="login-email">
    <input id="password" name="password" type="password">
    <button type="submit" class="btn btn-primary">Log in</button>
    <a href="/forgot">Forgot password?</a>
  </form>
</div>
LocatorExampleNotes
By.idBy.id("email")First choice, if IDs are unique and not generated
By.nameBy.name("password")Good for form fields
By.cssSelectorBy.cssSelector("[data-testid='login-email']")Fast and readable; test attributes survive redesigns
By.xpathBy.xpath("//button[text()='Log in']")Can match visible text and move to parents
By.classNameBy.className("btn-primary")One class only: "btn btn-primary" throws an error
By.linkTextBy.linkText("Forgot password?")A link's exact text
By.partialLinkTextBy.partialLinkText("Forgot")Part of a link's text
By.tagNameBy.tagName("button")Usually too broad on its own

Absolute vs relative XPath

AbsoluteRelative
Example/html/body/div/form/input[2]//input[@name='password']
Starts fromThe root of the document (/)Anywhere in the document (//)
Breaks whenAny element on the path is added, removed or movedThe element's own attribute changes

findElement vs findElements

Java
WebElement email = driver.findElement(By.id("email"));      // the first match, or NoSuchElementException
List<WebElement> errors = driver.findElements(By.cssSelector(".error"));   // all matches; empty if none
boolean hasErrors = !errors.isEmpty();                      // a safe way to check something is absent

In Python, the old find_element_by_id("email") style was removed in Selenium 4.3. Use driver.find_element(By.ID, "email"), even though many tutorials still show the old form.

Follow-ups

  • How do you check a locator before using it? In Chrome DevTools, press Ctrl+F in the Elements panel and type the CSS selector or XPath; it highlights the matches and shows how many there are.
  • What if the only unique thing is generated, like id="input-4821"? Ask developers to add a data-testid attribute, or anchor on a stable neighbour, such as the field's label text.
Q27Not marked yetFresherAsked very oftenPractical

Given the HTML of a users table, write a relative XPath for the Delete button in the row that contains a given email. Could a CSS selector do the same?

Say this first~20 sec to say

Anchor on the email cell, then move to the button in the same row: //td[text()='[email protected]']/following-sibling::td/button[text()='Delete']. Or select the row first: //tr[td[text()='[email protected]']]//button[text()='Delete']. A CSS selector can't do this, because CSS can't match an element's visible text. CSS works only if the email also appears in an attribute, such as data-email on the row.

Could you say it?
Full answer3 min read
HTML
<table id="users">
  <thead>
    <tr><th>Name</th><th>Email</th><th>Actions</th></tr>
  </thead>
  <tbody>
    <tr data-email="[email protected]">
      <td>Asha Rao</td>
      <td>[email protected]</td>
      <td><button class="edit">Edit</button> <button class="delete">Delete</button></td>
    </tr>
    <tr data-email="[email protected]">
      <td>Ravi Kumar</td>
      <td>[email protected]</td>
      <td><button class="edit">Edit</button> <button class="delete">Delete</button></td>
    </tr>
  </tbody>
</table>

Four XPaths that find Ravi's Delete button, and only that one

XPathHow it works
//td[text()='[email protected]']/following-sibling::td/button[text()='Delete']Finds the email cell, steps to later cells in the same row, then the button
//tr[td[text()='[email protected]']]//button[text()='Delete']Finds the row that has that email cell, then the button inside it
//td[text()='[email protected]']/ancestor::tr//button[@class='delete']Climbs from the cell to its row with the ancestor axis
//td[text()='[email protected]']/..//button[contains(text(),'Del')].. is the parent row; contains() allows a partial match

In a test

Java
static WebElement deleteButtonFor(WebDriver driver, String email) {
    return driver.findElement(By.xpath(
            "//tr[td[normalize-space()='" + email + "']]//button[normalize-space()='Delete']"));
}

// deleteButtonFor(driver, "[email protected]").click();

normalize-space() trims and collapses whitespace, so <td> [email protected] </td> still matches. It also matches text inside child elements, such as <button><span>Delete</span></button>, which text() doesn't.

The XPath axes worth knowing

AxisSelects
parent:: (or ..)The direct parent
ancestor::Parent, grandparent and so on
following-sibling::Later siblings
preceding-sibling::Earlier siblings
child::, descendant::Children; all levels below

When CSS works: if the row carries the email as an attribute, CSS is simpler: tr[data-email='[email protected]'] button.delete. If the attribute sits on a cell instead, modern browsers' :has() selects the row through it: tr:has(> td[data-email='[email protected]']) button.delete. Either way, CSS matches attributes, never text; jQuery's :contains() isn't real CSS, and browsers reject it as an invalid selector.

Follow-ups

  • What if the email contains an apostrophe, like o'[email protected]? A single-quoted XPath string breaks; wrap it in double quotes instead: //td[text()="o'[email protected]"].
  • Is XPath slower than CSS? Slightly, in some browsers, but the difference is rarely noticeable; choose the locator that's clearer and more stable.
Q28Not marked yetFresherAsked very oftenConcept

Implicit vs explicit vs fluent waits: how do they differ, and why not just use Thread.sleep()?

Say this first~30 sec to say

An implicit wait is a global setting: every findElement keeps retrying for up to that long before failing. An explicit wait waits for one condition, such as an element being clickable, using WebDriverWait and ExpectedConditions. A fluent wait is an explicit wait with a custom polling interval and ignored exceptions. Thread.sleep() always waits the full time: wasted when the page is fast, too short when it's slow, so tests become both slow and flaky.

Could you say it?
Full answer3 min read
Java
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;      // Selenium's, not java.util's
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
import org.openqa.selenium.support.ui.WebDriverWait;

public class Waits {
    static void implicitWait(WebDriver driver) {
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));   // applies to every findElement
    }

    static void explicitWait(WebDriver driver) {
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
        WebElement pay = wait.until(ExpectedConditions.elementToBeClickable(By.id("pay-now")));
        pay.click();
        wait.until(ExpectedConditions.textToBePresentInElementLocated(By.id("status"), "Payment successful"));
    }

    static WebElement fluentWait(WebDriver driver) {
        Wait<WebDriver> wait = new FluentWait<>(driver)
                .withTimeout(Duration.ofSeconds(30))
                .pollingEvery(Duration.ofMillis(500))
                .ignoring(NoSuchElementException.class);
        return wait.until(d -> d.findElement(By.id("receipt")));             // retries until found or 30 s pass
    }
}
ImplicitExplicit (WebDriverWait)Fluent (FluentWait)Thread.sleep()
ScopeEvery findElement in the sessionOne conditionOne conditionA fixed pause
Waits forThe element to exist in the pageAny condition: visible, clickable, text present, alert present…Any condition you writeNothing: just time
PollingDriver-controlledEvery 500 ms by defaultYou chooseNone
Ignores exceptionsNoNoSuchElementException by defaultYou chooseNo
RecommendedRarely, and never mixed with explicit waitsYes: the default choiceWhen you need custom pollingNo

Don't mix implicit and explicit waits. Selenium's documentation warns that combining them causes unpredictable wait times; for example, an implicit wait of 10 seconds with an explicit wait of 15 seconds could time out after 20 seconds. Most teams set the implicit wait to zero (the default) and use explicit waits everywhere.

Selenium 4 takes a Duration. The older forms, implicitlyWait(10, TimeUnit.SECONDS) and new WebDriverWait(driver, 10), are deprecated; use the Duration versions.

Follow-ups

  • What's the difference between presenceOfElementLocated and visibilityOfElementLocated? Presence means the element is in the page's HTML; visibility means it's also displayed with a size greater than zero. You usually want visibility, or clickability, before interacting.
  • Why import Selenium's NoSuchElementException? java.util has one with the same name; ignoring the wrong one means the fluent wait never catches Selenium's exception.
Q29Not marked yetFresherAsked very oftenPractical

Write Selenium code to choose a dropdown option by its visible text, then check which option is selected

Say this first~20 sec to say

For a native <select> element, wrap it in Selenium's Select class: new Select(driver.findElement(By.id("city"))), call selectByVisibleText("Pune"), and check the result with getFirstSelectedOption().getText(). Select also offers selectByValue and selectByIndex. It works only on <select> elements; for custom dropdowns built from divs or lis, click the control to open it, then click the option, usually found by its text.

Could you say it?
Full answer2 min read
HTML
<select id="city" name="city">
  <option value="">Select a city</option>
  <option value="PNQ">Pune</option>
  <option value="BLR">Bengaluru</option>
  <option value="DEL">Delhi</option>
</select>
Java
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.Select;
import org.testng.Assert;

public class CityDropdown {
    static void chooseCity(WebDriver driver) {
        Select city = new Select(driver.findElement(By.id("city")));

        city.selectByVisibleText("Pune");                                   // the text the user sees
        Assert.assertEquals(city.getFirstSelectedOption().getText(), "Pune");

        city.selectByValue("BLR");                                          // the value attribute
        Assert.assertEquals(city.getFirstSelectedOption().getText(), "Bengaluru");

        city.selectByIndex(3);                                              // position, from 0: Delhi (fragile)
        Assert.assertEquals(city.getOptions().size(), 4);                   // includes the placeholder
    }
}
Select methodUse
selectByVisibleText, selectByValue, selectByIndexChoose an option
getFirstSelectedOption()The selected option (the first, for multi-selects)
getAllSelectedOptions()Every selected option in a multi-select
getOptions()All options, such as for checking the list is sorted
isMultiple(), deselectAll()Multi-select lists only; deselectAll() throws on a single select

Custom dropdowns (common in React and Angular apps) aren't <select> elements, so new Select(...) throws UnexpectedTagNameException. Click your way through instead:

Java
driver.findElement(By.cssSelector("[data-testid='city-picker']")).click();      // open the list
new WebDriverWait(driver, Duration.ofSeconds(5))
        .until(ExpectedConditions.elementToBeClickable(
                By.xpath("//li[@role='option' and normalize-space()='Pune']")))
        .click();

Follow-ups

  • Why is selectByIndex fragile? Adding or reordering one option silently selects a different city. Visible text or value states your intent.
  • How would you check the options are in alphabetical order? Read getOptions(), collect their texts, skip the placeholder, and compare with a sorted copy.
Q30Not marked yetFresherAsked oftenConcept

How do you handle a JavaScript alert, an iframe and a new browser tab in Selenium?

Say this first~25 sec to say

WebDriver works in one context at a time, and driver.switchTo() changes it. For a JavaScript alert, switchTo().alert(), then accept(), dismiss(), getText() or sendKeys(). For an iframe, switchTo().frame() by name, index or element, and defaultContent() to come back. For a new tab, read getWindowHandles(), switch to the new handle with switchTo().window(), and switch back afterwards. close() closes the current window; quit() ends the whole session.

Could you say it?
Full answer3 min read
Java
import java.time.Duration;
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class SwitchingContexts {
    static void handleAlert(WebDriver driver) {
        driver.findElement(By.id("delete-account")).click();
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
        Alert alert = wait.until(ExpectedConditions.alertIsPresent());
        System.out.println(alert.getText());           // Are you sure?
        alert.accept();                                // OK; alert.dismiss() would press Cancel
    }

    static void handleIframe(WebDriver driver) {
        driver.switchTo().frame("payment-frame");      // by name or id; also by index or WebElement
        driver.findElement(By.id("card-number")).sendKeys("4111111111111111");
        driver.switchTo().defaultContent();            // back to the main page
    }

    static void handleNewTab(WebDriver driver) {
        String original = driver.getWindowHandle();
        driver.findElement(By.linkText("Terms and conditions")).click();      // opens a new tab
        new WebDriverWait(driver, Duration.ofSeconds(5))
                .until(ExpectedConditions.numberOfWindowsToBe(2));
        for (String handle : driver.getWindowHandles()) {
            if (!handle.equals(original)) {
                driver.switchTo().window(handle);
                break;
            }
        }
        System.out.println(driver.getTitle());          // the new tab's title
        driver.close();                                 // closes this tab only
        driver.switchTo().window(original);             // switch back explicitly
    }
}
ContextSwitch inSwitch outTypical error if you forget
Alert, confirm, promptswitchTo().alert()accept() or dismiss() closes itUnhandledAlertException on the next command
IframeswitchTo().frame(...)defaultContent(), or parentFrame() one level upNoSuchElementException for elements inside the frame
Window or tabswitchTo().window(handle)Switch back to the saved handleCommands go to the wrong tab, or fail after it closes

close() vs quit()

close()quit()
ClosesThe current window or tabEvery window
SessionStays open while other windows remainEnds; the driver process stops
UseClosing a popup tabIn teardown, after every test

Selenium 4 can open tabs itself: driver.switchTo().newWindow(WindowType.TAB) opens a blank tab and switches to it.

Follow-ups

  • How do you type into a prompt() dialog? alert.sendKeys("Asha"), then alert.accept().
  • Can Selenium handle the browser's own file-download or print dialogs? No: they aren't part of the page. Set browser preferences, such as a download folder, through ChromeOptions instead.

07Automation frameworks

0/6 got it

Q31Not marked yetFresherAsked very oftenConcept

What are the main TestNG annotations, and in what order do they run?

Say this first~25 sec to say

TestNG wraps tests in setup and teardown methods at four levels: @BeforeSuite, @BeforeTest (once per <test> tag in testng.xml), @BeforeClass, and @BeforeMethod before every @Test. The matching After methods run in reverse: method, class, test, suite. Attributes on @Test control what runs and when: priority (lower runs first), dependsOnMethods, groups, and enabled = false to switch a test off.

Could you say it?
Full answer4 min read
Java
import org.testng.annotations.*;

public class OrderDemo {
    @BeforeSuite  public void beforeSuite()  { System.out.println("BeforeSuite"); }
    @BeforeTest   public void beforeTest()   { System.out.println("BeforeTest"); }
    @BeforeClass  public void beforeClass()  { System.out.println("BeforeClass"); }
    @BeforeMethod public void beforeMethod() { System.out.println("  BeforeMethod"); }

    @Test(priority = 1) public void login()  { System.out.println("    Test: login"); }
    @Test(priority = 2) public void search() { System.out.println("    Test: search"); }

    @AfterMethod  public void afterMethod()  { System.out.println("  AfterMethod"); }
    @AfterClass   public void afterClass()   { System.out.println("AfterClass"); }
    @AfterTest    public void afterTest()    { System.out.println("AfterTest"); }
    @AfterSuite   public void afterSuite()   { System.out.println("AfterSuite"); }
}
BeforeSuite
BeforeTest
BeforeClass
  BeforeMethod
    Test: login
  AfterMethod
  BeforeMethod
    Test: search
  AfterMethod
AfterClass
AfterTest
AfterSuite
AnnotationRunsTypical use
@BeforeSuite / @AfterSuiteOnce for the whole suiteStart a report, connect to a test database
@BeforeTest / @AfterTestOnce per <test> tag in testng.xmlSettings shared by a set of classes, such as the browser
@BeforeClass / @AfterClassOnce per test classLog in once for all of a class's tests
@BeforeMethod / @AfterMethodAround every @Test methodOpen and quit the browser, so each test starts clean
@BeforeGroups / @AfterGroupsBefore the first and after the last test of a groupPrepare data for the "payments" group

The classic confusion: @BeforeTest doesn't run before each test method; that's @BeforeMethod. A "test" in TestNG is the <test> tag in testng.xml, which can hold many classes.

@Test attributeEffect
priority = 1Lower numbers run first; the default is 0. Without priorities, TestNG runs methods in alphabetical order
dependsOnMethods = "login"Runs only if login passed; otherwise it's reported as skipped
groups = {"smoke"}Lets testng.xml run just the smoke group
enabled = falseSwitches the test off
invocationCount = 3, timeOut = 5000Run it three times; fail it after 5 seconds
expectedExceptions = ArithmeticException.classPasses only if that exception is thrown

If you're asked about pytest: it has no annotation hierarchy. Setup and teardown live in fixtures with a scope, such as function, class, module or session, so don't map TestNG's annotations onto it one to one.

Follow-ups

  • What is testng.xml for? It defines the suite: which classes, groups and parameters to run, and whether to run them in parallel (question 40 shows one).
  • Does a failing @BeforeMethod fail the test? The configuration method fails, and the tests it guards are skipped, which shows up in the report as skips, not failures.
Q32Not marked yet1–3 yrsAsked very oftenPractical

Using the Page Object Model, write a page class for a login page and a TestNG test that uses it

Say this first~25 sec to say

The Page Object Model gives each page its own class holding its locators and actions, such as loginAs(email, password). Tests call those methods instead of using Selenium directly. When the UI changes, you fix one page class instead of fifty tests, and tests read like the user's steps. Page methods return the next page object, and assertions stay in the tests, not in the page classes.

Could you say it?
Full answer8 min read
src/test/java/
├── pages/
│   ├── LoginPage.java
│   └── DashboardPage.java
└── tests/
    └── LoginTest.java
Java
// src/test/java/pages/LoginPage.java
package pages;

import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class LoginPage {
    private final WebDriver driver;
    private final WebDriverWait wait;

    private final By email = By.id("email");                              // locators live here, once
    private final By password = By.id("password");
    private final By loginButton = By.cssSelector("button[type='submit']");
    private final By error = By.cssSelector("[role='alert']");

    public LoginPage(WebDriver driver) {
        this.driver = driver;
        this.wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    }

    public LoginPage open(String baseUrl) {
        driver.get(baseUrl + "/login");
        wait.until(ExpectedConditions.visibilityOfElementLocated(email));   // the page has loaded
        return this;
    }

    public DashboardPage loginAs(String user, String pass) {
        submit(user, pass);
        return new DashboardPage(driver);                                  // success leads to the next page
    }

    public LoginPage loginExpectingError(String user, String pass) {
        submit(user, pass);
        return this;                                                       // failure stays on this page
    }

    public String errorText() {
        return wait.until(ExpectedConditions.visibilityOfElementLocated(error)).getText();
    }

    private void submit(String user, String pass) {
        type(email, user);
        type(password, pass);
        driver.findElement(loginButton).click();
    }

    private void type(By locator, String text) {
        WebElement field = wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
        field.clear();
        field.sendKeys(text);
    }
}
Java
// src/test/java/pages/DashboardPage.java
package pages;

import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class DashboardPage {
    private final WebDriverWait wait;
    private final By welcome = By.cssSelector("[data-testid='welcome']");

    public DashboardPage(WebDriver driver) {
        this.wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    }

    public String welcomeText() {
        return wait.until(ExpectedConditions.visibilityOfElementLocated(welcome)).getText();
    }
}
Java
// src/test/java/tests/LoginTest.java
package tests;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import pages.DashboardPage;
import pages.LoginPage;

public class LoginTest {
    private static final String BASE_URL = System.getProperty("baseUrl", "https://staging.example.com");
    private WebDriver driver;

    @BeforeMethod
    public void startBrowser() {
        ChromeOptions options = new ChromeOptions();
        if (Boolean.getBoolean("headless")) {                    // mvn test -Dheadless=true
            options.addArguments("--headless=new", "--window-size=1920,1080");
        }
        driver = new ChromeDriver(options);
    }

    @Test
    public void validUserSeesDashboard() {
        DashboardPage dashboard = new LoginPage(driver)
                .open(BASE_URL)
                .loginAs("[email protected]", "Secret@123");
        Assert.assertEquals(dashboard.welcomeText(), "Welcome, Asha");
    }

    @Test
    public void wrongPasswordShowsError() {
        LoginPage page = new LoginPage(driver)
                .open(BASE_URL)
                .loginExpectingError("[email protected]", "wrong-pass");
        Assert.assertEquals(page.errorText(), "Invalid email or password");
    }

    @AfterMethod(alwaysRun = true)
    public void closeBrowser() {
        if (driver != null) {
            driver.quit();
        }
    }
}

Why teams use it

Without page objectsWith page objects
Locators repeated in every testEach locator defined once
A changed button ID breaks fifty testsFix one line in LoginPage
Tests full of findElement callsTests read like steps: open, log in, check the greeting
Hard to reuse flowsloginAs is reused by every test that needs a logged-in user

Assertions belong in tests. Selenium's own guidance is that page objects shouldn't make assertions; the one check they may make is that their page has loaded, as open() does here.

PageFactory is an older style you'll see in many frameworks: @FindBy(id = "email") private WebElement email; plus PageFactory.initElements(driver, this) in the constructor. It follows the same pattern with different syntax.

Follow-ups

  • What is POM, and why use it? This is the spoken version freshers usually get: one class per page holding its locators and actions, so tests are readable and UI changes are fixed in one place.
  • Should a page object return void from actions? Returning the next page object makes navigation explicit and lets tests chain calls, as above.
Q33Not marked yetFresherAsked oftenConcept

Hard assert vs soft assert in TestNG: how do they differ, and when would you use each?

Say this first~30 sec to say

A hard assert, such as TestNG's Assert.assertEquals, stops the test immediately when it fails, so later checks never run. A soft assert uses a SoftAssert object that records each failure and carries on; calling assertAll() at the end fails the test with every recorded failure. Use hard asserts when later steps depend on the check, such as login succeeding; soft asserts for several independent checks on one page. Forget assertAll(), and failures pass silently.

Could you say it?
Full answer3 min read
Java
import org.testng.Assert;
import org.testng.annotations.Test;
import org.testng.asserts.SoftAssert;

public class ProfileTest {
    // Stand-ins for values read from the profile page
    private final String name = "Asha Rao";
    private final String city = "Mumbai";            // wrong: should be Pune
    private final boolean avatarShown = false;       // wrong: should be shown

    @Test
    public void hardAsserts() {
        Assert.assertEquals(name, "Asha Rao");
        Assert.assertEquals(city, "Pune");           // fails here and stops the test
        Assert.assertTrue(avatarShown, "avatar missing");   // never runs
    }

    @Test
    public void softAsserts() {
        SoftAssert soft = new SoftAssert();          // a new one in every test
        soft.assertEquals(name, "Asha Rao");
        soft.assertEquals(city, "Pune");             // recorded; carries on
        soft.assertTrue(avatarShown, "avatar missing");     // recorded; carries on
        soft.assertAll();                            // fails now, listing both problems
    }
}

hardAsserts reports one failure, the city; you only discover the missing avatar after fixing it and running again. softAsserts reports both in one run.

Hard assert (Assert)Soft assert (SoftAssert)
On failureThrows immediately; the test stopsRecords it; the test continues
ReportedThe first failure onlyEvery failure, at assertAll()
Use whenLater steps depend on this one: login, navigationIndependent checks on one page: labels, fields, totals
RiskHides later problemsForgetting assertAll() means the test passes anyway

Two easy mistakes

  • Argument order: TestNG's assertEquals takes (actual, expected), the reverse of JUnit's (expected, actual). Swap them, and the failure message reads backwards.
  • Sharing one SoftAssert across tests as a field: failures from one test leak into the next. Create one per test.

In older Selenium terms, this was "assert vs verify": an assert stops the test, a verify notes the failure and continues. pytest has no built-in soft assert: a failing assert ends the test, so soft checks need a plugin such as pytest-check.

Follow-ups

  • Can you mix them in one test? Yes, and it's common: hard-assert that login worked, then soft-assert the page's details.
  • What does the failure message contain? The expected and actual values for each failure, plus any message you passed, such as "avatar missing".
Q34Not marked yet1–3 yrsAsked oftenPractical

Use a TestNG @DataProvider to run one login test with several username and password pairs

Say this first~30 sec to say

A @DataProvider method returns an Object[][], where each inner array is one row of arguments. A test annotated @Test(dataProvider = "logins") takes those arguments as parameters and runs once per row, and each run is reported separately. One login test then covers valid, wrong-password and blank-field cases without copied code. Rows can be written in code or read from CSV, Excel (with Apache POI) or JSON, which keeps test data out of the test.

Could you say it?
Full answer4 min read
Java
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import pages.LoginPage;

public class LoginDataTest {
    private WebDriver driver;

    @BeforeMethod
    public void startBrowser() {
        driver = new ChromeDriver();
    }

    @DataProvider(name = "logins")
    public Object[][] logins() {
        return new Object[][] {
            {"[email protected]", "Secret@123", true},        // valid
            {"[email protected]", "wrong-pass", false},       // wrong password
            {"[email protected]", "Secret@123", false},     // unregistered email
            {"", "Secret@123", false},                       // blank email
        };
    }

    @Test(dataProvider = "logins")
    public void login(String email, String password, boolean shouldSucceed) {
        LoginPage page = new LoginPage(driver).open("https://staging.example.com");
        if (shouldSucceed) {
            Assert.assertEquals(page.loginAs(email, password).welcomeText(), "Welcome, Asha");
        } else {
            Assert.assertFalse(page.loginExpectingError(email, password).errorText().isEmpty());
        }
    }

    @AfterMethod(alwaysRun = true)
    public void closeBrowser() {
        driver.quit();
    }
}

The report shows four results for login, each with its parameters, so a failure points straight at the row that broke. LoginPage is the page object from question 32.

Reading the rows from a CSV file instead

email,password,shouldSucceed
[email protected],Secret@123,true
[email protected],wrong-pass,false
,Secret@123,false
Java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import org.testng.annotations.DataProvider;

public class LoginCsvData {
    @DataProvider(name = "loginsFromCsv")
    public static Object[][] loginsFromCsv() throws IOException {
        List<String> lines = Files.readAllLines(Path.of("src/test/resources/logins.csv"));
        return lines.stream()
                .skip(1)                                        // the header row
                .map(line -> line.split(",", -1))              // -1 keeps empty trailing fields
                .map(cols -> new Object[] {cols[0], cols[1], Boolean.parseBoolean(cols[2])})
                .toArray(Object[][]::new);
    }
}

A test in another class uses it with @Test(dataProvider = "loginsFromCsv", dataProviderClass = LoginCsvData.class); a provider in another class must be static, or its class must have a no-argument constructor.

OptionHow
Run the rows in parallel@DataProvider(name = "logins", parallel = true)
Huge data setsReturn Iterator<Object[]> to supply rows one at a time
Excel filesRead the sheet with Apache POI (XSSFWorkbook) and build the same Object[][]
Same data for many testsA shared provider class with dataProviderClass

Follow-ups

  • DataProvider vs @Parameters? @Parameters passes single values from testng.xml, such as the browser name, once per run; a DataProvider supplies many rows, running the test once per row.
  • Where should passwords for real test accounts live? Not in the code or the CSV in Git: read them from environment variables or the CI system's secret store.
Q35Not marked yet1–3 yrsAsked oftenConcept

How do you decide which test cases to automate and which to keep manual?

Say this first~30 sec to say

I'd automate tests that are repeated often, stable and valuable: smoke and regression suites, critical flows like login and checkout, data-driven checks with many inputs, and cross-browser runs. I'd keep manual what needs human judgement or changes too fast to maintain: exploratory and usability testing, one-off checks, features still being designed, and things like CAPTCHAs. The test is simple: will the time saved over many runs outweigh the cost to build and maintain the automation?

Could you say it?
Full answer2 min read
AutomateKeep manual
Smoke and regression tests, run every buildExploratory testing
Critical business flows: login, search, checkoutUsability and look-and-feel judgements
Data-driven tests with many input combinationsOne-off or rarely run tests
The same checks across browsers and devicesFeatures whose UI changes every sprint
Long, repetitive, error-prone manual stepsCAPTCHA, real OTPs and physical devices, unless the app offers test hooks
API checks (fast and stable)Ad hoc checks while investigating a bug

A quick payback estimate

Manual regression:      16 hours every sprint
Automated regression:   1 hour to run and review + 3 hours of maintenance = 4 hours
Saving per sprint:      12 hours
Cost to build:          120 hours
Break-even:             120 / 12 = 10 sprints (about 5 months of two-week sprints)

After that, every run is time saved, and the suite can run every night, which manual testing never could.

The test pyramid guides where to automate: many fast unit tests at the base, fewer API tests in the middle, and only a thin layer of slow, brittle UI tests at the top. Automating everything through the UI makes suites slow and flaky.

          /\
         /UI\          few: slow, brittle, end to end
        /----\
       / API  \        more: fast, stable
      /--------\
     /  Unit    \      most: fastest, written by developers
    /------------\

Follow-ups

  • Can everything be automated? No. Exploratory testing, usability judgements and checks needing human perception stay manual, and some automation costs more to maintain than it saves.
  • When would you automate a new feature? Once its behaviour and UI have settled, usually a sprint or two after it ships; automating a moving target wastes effort.
Q36Not marked yet1–3 yrsAsked oftenScenario

An automated test passes on some runs and fails on others in the nightly build. How would you find the cause?

Say this first~30 sec to say

I'd treat it as a real defect in the test or the app, not bad luck. First, gather evidence from failed runs: the failing step, screenshots and logs. Then check the usual causes: timing (fixed sleeps, missing explicit waits), unstable locators, shared or leftover test data, order dependence when tests run together or in parallel, and environment differences such as a small headless window. I'd reproduce it by running it many times, then fix the cause; retries only hide it.

Could you say it?
Full answer3 min read
SymptomLikely causeFix
NoSuchElementException or "element not interactable" at random stepsTiming: Thread.sleep, no wait, animations, slow API callsExplicit waits for the right condition (question 28)
Fails only in CI or headless runsHeadless Chrome opens a small window, so the page shows its mobile layout; slower CI machines--window-size=1920,1080; waits instead of fixed times
Passes alone, fails in the full suiteOrder dependence: relies on data or state from another testEach test creates its own data and cleans up
Fails only in parallel runsShared accounts or data; one static WebDriver shared by threadsUnique data per test; one driver per thread (ThreadLocal)
StaleElementReferenceExceptionThe page re-rendered after the element was foundFind the element again after the update
Fails at certain times of dayTime zones, dates, scheduled jobs or deployments on the test serverFixed test dates; check the environment's schedule
"Email already registered"Hard-coded data reused across runsGenerate unique data, such as "asha+" + System.currentTimeMillis() + "@example.com"

The most common fix: replace a fixed sleep with a wait for the real condition

Java
// Before: flaky. Two seconds is sometimes too short, and always wasted when the page is fast
driver.findElement(By.id("apply-coupon")).click();
Thread.sleep(2000);
Assert.assertEquals(driver.findElement(By.id("total")).getText(), "₹1,080");

// After: waits exactly as long as needed, up to 10 seconds
driver.findElement(By.id("apply-coupon")).click();
new WebDriverWait(driver, Duration.ofSeconds(10))
        .until(ExpectedConditions.textToBePresentInElementLocated(By.id("total"), "₹1,080"));

Reproducing it

  • Run the test many times in a row, for example by temporarily adding invocationCount = 50 to its @Test.
  • Compare: alone vs in the suite, headed vs headless, serial vs parallel, local vs CI.
  • Capture a screenshot and the page source on failure, with a TestNG listener, so every failed nightly run leaves evidence.

Retries are a stopgap. TestNG's IRetryAnalyzer can rerun failed tests, but a test that passes on the second attempt still hides a problem, and sometimes that problem is a real race condition in the app. If you add retries, track which tests needed them and fix those.

Follow-ups

  • What's a quarantine? Moving a known-flaky test out of the main suite into a separate run, with a ticket to fix it, so it stops blocking everyone while it's investigated.
  • Can a flaky test reveal a real bug? Yes. Timing-dependent failures sometimes come from the app itself, such as a double click creating two orders.

08API testing

0/2 got it

Q37Not marked yetFresherAsked oftenConcept

When testing an API, what do you check beyond the status code, for both valid and invalid requests?

Say this first~30 sec to say

Beyond the status code, I check the response body: correct values, data types and schema; key headers, such as Content-Type; response time against the target; and authorisation: no token gives 401, and another user's data is never returned. For invalid requests, I check for clear error messages without stack traces or internal details. And I confirm side effects: after creating something, a GET, or the database, shows it was really saved.

Could you say it?
Full answer3 min read

A valid request: POST /api/orders places an order

CheckWhat to look for
Status code201 Created
Body valuestotal is 1080 for the cart sent, status is "PLACED", the items match the request
Schema and typesid is a number, every required field is present, no unexpected nulls
HeadersContent-Type: application/json; a Location header pointing to the new order
Response timeWithin the agreed target, such as 500 ms
Persistence and side effectsGET /api/orders/{id} returns the same order; stock went down; one confirmation email was sent

Invalid requests: the negative tests

RequestExpected
items missing400 with a message naming the field, such as "items is required"
Quantity of 0 or -1400 (or 422), and no order created
No token, or an expired one401
Asha's token asking for Ravi's order403 or 404, never Ravi's data
Malformed JSON400, not a 500 crash
The same request sent twice by a retryOne order, not two (Backend kit, question 8)

Error responses deserve testing too. They shouldn't contain stack traces, SQL errors or server file paths: those help attackers and confuse users.

Checking the schema automatically, in Postman

JavaScript
const schema = {
    type: "object",
    required: ["id", "status", "total", "items"],
    properties: {
        id: { type: "integer" },
        status: { type: "string", enum: ["PLACED", "PAID", "SHIPPED"] },
        total: { type: "number", minimum: 0 },
        items: { type: "array", minItems: 1 }
    }
};

pm.test("matches the order schema", () => {
    pm.response.to.have.jsonSchema(schema);
});

What the status codes themselves mean is covered in the Backend kit, question 3; this question is about what a tester checks.

Follow-ups

  • Positive vs negative API tests? Positive tests send valid requests and check the right result; negative tests send invalid, unauthorised or malformed ones and check the API refuses them safely and clearly.
  • Why test APIs when the UI is tested? API tests are faster and more stable, they reach cases the UI blocks (such as a negative quantity), and they find defects before the UI exists.
Q38Not marked yet1–3 yrsAsked oftenPractical

In Postman, save the token from a login response, reuse it in the next request, and add tests that check the response

Say this first~25 sec to say

In the login request's post-response script (the old Tests tab), I check the status with pm.response.to.have.status(200), read the body with pm.response.json(), and save the token with pm.environment.set("token", body.token). The next request sends the header Authorization: Bearer {{token}}. Its script uses pm.test and pm.expect to check the status, body fields and response time. Requests live in a collection, run with the Collection Runner or Newman in CI.

Could you say it?
Full answer4 min read

Request 1: POST {{baseUrl}}/api/login, body {"email": "[email protected]", "password": "{{password}}"}. Its post-response script:

JavaScript
pm.test("login returns 200", function () {
    pm.response.to.have.status(200);
});

const body = pm.response.json();

pm.test("response contains a token", function () {
    pm.expect(body.token).to.be.a("string").and.not.empty;
});

pm.environment.set("token", body.token);         // saved for the requests that follow

Request 2: GET {{baseUrl}}/api/me, with the header Authorization: Bearer {{token}} (or the Authorization tab, type Bearer Token, value {{token}}). Its post-response script:

JavaScript
pm.test("status is 200", () => {
    pm.response.to.have.status(200);
});

pm.test("returns Asha's profile", () => {
    const user = pm.response.json();
    pm.expect(user.email).to.eql("[email protected]");
    pm.expect(user).to.have.property("id");
});

pm.test("responds in under 500 ms", () => {
    pm.expect(pm.response.responseTime).to.be.below(500);
});

pm.test("returns JSON", () => {
    pm.expect(pm.response.headers.get("Content-Type")).to.include("application/json");
});

Request 3, the negative case: GET {{baseUrl}}/api/me with no Authorization header

JavaScript
pm.test("rejects a request without a token", () => {
    pm.response.to.have.status(401);
});

Collections and environments: a collection is a saved, ordered set of requests with their scripts; an environment is a set of variables, such as baseUrl and password, so the same collection runs against dev, staging or production by switching environments.

Variable scopeLives inUse for
GlobalThe whole workspaceRarely; values shared everywhere
CollectionOne collectionValues fixed for that API, such as an API version
EnvironmentOne environmentbaseUrl, credentials, the saved token
DataA CSV or JSON file in a collection runData-driven runs, one iteration per row
LocalOne request's scriptTemporary values

When two scopes define the same name, the narrowest wins: local, then data, then environment, then collection, then global.

Running it from the command line, as CI does:

Terminal
newman run shop-api.postman_collection.json -e staging.postman_environment.json
→ Login
  POST http://localhost:3000/api/login [200 OK, …]
  ✓  login returns 200
  ✓  response contains a token

→ Profile
  GET http://localhost:3000/api/me [200 OK, …]
  ✓  status is 200
  ✓  returns Asha's profile
  ✓  responds in under 500 ms
  ✓  returns JSON

→ Profile without a token
  GET http://localhost:3000/api/me [401 Unauthorized, …]
  ✓  rejects a request without a token

That's Newman's output from running this collection against a local test API, trimmed. Newman exits with an error code if any test fails, which is what fails a CI build.

Old tutorials use tests["Status code is 200"] = responseCode.code === 200;. That syntax is deprecated; write pm.test with pm.expect or pm.response.to.

Follow-ups

  • Environment variable vs collection variable for the token? The environment, because the token belongs to the server and user you're testing against; switching to another environment shouldn't reuse it.
  • How would you run the login with many users? Put the users in a CSV file, refer to them as {{email}} and {{password}}, and pass the file to the Collection Runner or newman run … -d users.csv.

09Performance and CI basics

0/2 got it

Q39Not marked yetFresherAsked oftenConcept

Load testing vs stress testing: how do they differ, and where do spike and endurance testing fit?

Say this first~30 sec to say

Load testing checks performance at the expected and peak number of users: do response times and error rates stay within targets? Stress testing pushes beyond that until the system breaks, to find the limit, how it fails, and whether it recovers. Spike testing applies a sudden surge, such as a flash sale opening at midnight. Endurance (soak) testing holds a normal load for many hours to expose slow problems like memory leaks.

Could you say it?
Full answer2 min read

One shopping site, preparing for a Diwali sale that expects 5,000 users at once

TestLoad appliedQuestion it answers
LoadRamp up to 5,000 users, then a 7,500-user peakDo pages stay under 2 seconds with under 1% errors?
StressKeep adding users past 7,500 until it failsWhere's the breaking point, does it fail gracefully, and does it recover afterwards?
Spike500 users jump to 10,000 within a minute at midnightDoes it survive the sudden jump, and how fast does autoscaling react?
Endurance (soak)3,000 users steadily for 12 hoursDoes memory creep up, or do connections run out, over time?
VolumeNormal users, but 50 million orders in the databaseDo searches and reports stay fast with large data?

What to measure

MetricMeaning
Response time, average and percentilesp95 = 1.8 s means 95% of requests took 1.8 seconds or less
ThroughputRequests or transactions handled per second
Error rateShare of requests that failed or timed out
Server resourcesCPU, memory, database connections, disk and network on each server

Percentiles matter more than averages: an average of 800 ms can hide the 5% of users waiting 6 seconds.

Common tools: JMeter, k6, Gatling and Locust. Whatever the tool, the test environment should be as close to production as possible, or the numbers mean little.

Follow-ups

  • What's a performance bottleneck? The one resource that limits the whole system, such as a slow database query or too few connections in a pool. Tests find the symptom; profiling and monitoring find the bottleneck.
  • Who sets the targets? The business and the team together, from expected traffic; testers should ask for numbers ("how many users, how fast?") before testing, not after.
Q40Not marked yet1–3 yrsAsked oftenConcept

How do automated tests run in a CI pipeline such as Jenkins or GitHub Actions?

Say this first~30 sec to say

The pipeline runs automatically on every push or pull request, and often nightly for the full regression. It checks out the code, sets up Java, and runs the suite headless with mvn test, which picks up testng.xml through the Surefire plugin. Reports and screenshots are published with the build. If any test fails, Maven exits with an error, so the build fails and the team is told before the change is merged or released.

Could you say it?
Full answer5 min read

The suite file and the Maven setup

XML
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Regression" parallel="classes" thread-count="3">
  <test name="Web regression">
    <groups>
      <run>
        <include name="smoke"/>
        <include name="regression"/>
      </run>
    </groups>
    <classes>
      <class name="tests.LoginTest"/>
      <class name="tests.CheckoutTest"/>
    </classes>
  </test>
</suite>
XML
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>3.5.2</version>
  <configuration>
    <suiteXmlFiles>
      <suiteXmlFile>testng.xml</suiteXmlFile>
    </suiteXmlFiles>
  </configuration>
</plugin>

GitHub Actions: .github/workflows/ui-tests.yml

YAML
name: UI tests

on:
  push:
    branches: [main]
  pull_request:
  schedule:
    - cron: "30 20 * * *"   # 2:00 a.m. IST every night (GitHub's cron runs in UTC)

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: "17"
          cache: maven
      - name: Run the TestNG suite headless
        run: mvn -B test -Dheadless=true -DbaseUrl=https://staging.example.com
      - name: Upload test reports
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-reports
          path: target/surefire-reports/

-Dheadless=true reaches the test as a system property, which is what LoginTest in question 32 checks before adding --headless=new. GitHub's Ubuntu runners come with Chrome installed, and Selenium Manager fetches the matching driver.

The same in Jenkins: a declarative Jenkinsfile

pipeline {
    agent any
    triggers { cron('H 2 * * *') }               // nightly, some time in the 2 a.m. hour
    stages {
        stage('Test') {
            steps {
                sh 'mvn -B test -Dheadless=true'
            }
        }
    }
    post {
        always {
            junit 'target/surefire-reports/*.xml'                          // test results page and trend
            archiveArtifacts artifacts: 'target/surefire-reports/**', allowEmptyArchive: true
        }
    }
}
StepWhy
Trigger on push and pull requestCatch breakages before they're merged
Nightly scheduleRun the slow, full regression without blocking developers
Headless browserCI servers have no screen
Publish reports and screenshots, even on failureSo the failure can be investigated without rerunning it
Fail the build when tests failStops a broken change moving forward

How a failure stops the pipeline: when a test fails, Surefire reports BUILD FAILURE and Maven exits with a non-zero code; GitHub Actions and Jenkins treat that as a failed step. (Passing -Dmaven.test.failure.ignore=true lets Jenkins mark the build unstable instead, so later steps still run.)

CI/CD in general, building and deploying the application, is in the Backend kit, question 40; this question is about the test suite's part in it.

Follow-ups

  • How do you make a long suite faster in CI? Run it in parallel: parallel="classes" with a thread-count in testng.xml, Selenium Grid, or splitting it across CI jobs; and run only the smoke group on pull requests.
  • Where do test credentials go? In the CI system's secrets (GitHub Actions secrets, Jenkins credentials), passed as environment variables, never in the repository.

Last step

Write these from memory

Before a QA interview, make sure you can write each of these on a blank page without help:

  • Q5
  • Q14
  • Q15
  • Q19
  • Q20
  • Q22
  • Q27
  • Q28
  • Q29
  • Q30
  • Q31
  • Q32
  • Q33
  • Q34
  • Q38
  • Q40

0 of 16 done