By Himanshu Agarwal · himanshuai.com
The bar for senior test roles in 2026 is no longer "can you write a Selenium script?" — it's whether you can reason about concurrency, flaky tests, API security, and the new AI-testing stack (LLMs, RAG, MCP) out loud, with trade-offs and real examples.
Below are 10 real interview questions — spanning all 9 domains — answered the way a Senior SDET or Test Architect would answer them. This is a free preview of my full 112-page guide.
📘 First — grab the complete guide
This article is a free 10-question preview. The full 112-page ebook has 50 in-depth questions + 150 fully-answered follow-ups (200 Q&A total) across Java, Python, REST Assured, API Testing, Automation, AI Testing, LLM, RAG & MCP — each with a deep technical explanation, a real enterprise example, common mistakes, and the exact "best answer" to say in the room. Plus a 30-day interview roadmap.
👉 Get the full guide on Gumroad: >>https://himanshuai.gumroad.com/l/200InterviewSDETtoAITestArchitectQnA2026<<
1. ConcurrentHashMap Internals & Thread Safety
Category: Core Java
Difficulty: ⭐⭐⭐⭐⭐
Category: Java
Interview Experience: Interviewers ask this to separate people who use ConcurrentHashMap from people who understand why it is safe. In a test framework running hundreds of parallel threads, a naive shared map is the single most common source of flaky, non-reproducible failures. They want to see if you understand lock granularity, memory visibility, and the difference between "thread-safe" and "atomic across operations."
Question
How does ConcurrentHashMap achieve thread safety in modern Java, and why is a thread-safe map still not enough to make map.get() followed by map.put() correct?
Answer
ConcurrentHashMap provides thread safety through fine-grained, bucket-level synchronization rather than locking the whole map. Since Java 8 it abandoned the old segment-based locking and instead synchronizes on the first node of each bin, uses CAS (compare-and-swap) for empty-bin insertion, and treats reads as lock-free by relying on volatile semantics of the table and nodes. It is thread-safe for individual operations, but a check-then-act sequence like if (!map.containsKey(k)) map.put(k, v) is still a race condition because another thread can interleave between the two calls. You must use the atomic composite methods — putIfAbsent, computeIfAbsent, compute, merge — to make the whole operation atomic.
Deep Technical Explanation
-
Structure: an array of bins (
Node[] table). Each bin is either empty, a linked list, or (once it exceeds the treeify threshold of 8 nodes with table size ≥ 64) a red-black tree. -
Writes: to insert into an empty bin, it uses a CAS on the array slot — no lock needed. If the bin is occupied, it
synchronized-locks on the head node of that bin only, so contention is limited to keys that hash to the same bin. -
Reads:
get()acquires no lock. Correctness comes fromvolatilereads of the table reference and node values, which establish the necessary happens-before relationships so a reader sees a completed write. -
Resizing: multiple threads can cooperatively help transfer bins during a resize using a
ForwardingNodemarker, avoiding a stop-the-world rehash. -
Why composite ops matter: each method is individually atomic, but atomicity does not compose.
computeIfAbsent(key, k -> expensiveInit())guarantees the mapping function runs at most once per absent key under the bin lock, which is exactly what you want for lazy, once-only initialization.
Real Enterprise Example
In a Selenium Grid–style parallel execution engine, we cached WebDriver factories keyed by browser+version. The original code did if (!cache.containsKey(key)) cache.put(key, buildDriver()). Under 200 parallel threads this built the same driver twice for the same key, leaking sessions and exhausting the grid. Replacing it with cache.computeIfAbsent(key, k -> buildDriver()) guaranteed exactly-once construction and eliminated the leak.
Common Mistakes
- Claiming
ConcurrentHashMapstill uses segments (removed in Java 8). - Saying reads take a lock (they don't).
- Using
containsKey+putand assuming it's safe. - Putting
nullkeys or values (unlikeHashMap, it forbids both — precisely so anullreturn fromgetis unambiguous under concurrency).
Best Answer in Interview
"It's thread-safe per operation via bin-level synchronized plus CAS on empty bins, with lock-free reads through volatile semantics. But atomicity doesn't compose, so for check-then-act I use computeIfAbsent or merge instead of containsKey + put."
Follow-up Questions
(The detailed answers to these follow-ups are in the full 112-page guide.)
- Why does
computeIfAbsentwarn against modifying the same map inside the mapping function? - How does the treeification threshold interact with poor
hashCodedistribution? -
Contrast this with
Collections.synchronizedMap— why is it worse under contention?Key Takeaways
Bin-level locking + CAS + lock-free reads.
Atomicity does not compose — use the composite atomic methods.
No null keys or values, by design.
2. The Python GIL & True Concurrency
Category: Python
Difficulty: ⭐⭐⭐⭐⭐
Category: Python
Interview Experience: The GIL is the single most misunderstood topic in Python interviews. Interviewers ask it to see whether you can choose the right concurrency model for a workload rather than reflexively reaching for threads. For an SDET, this decides whether your test-data generation or load simulation actually uses the machine.
Question
Explain the GIL, and given a CPU-bound task, an I/O-bound task, and a huge number of concurrent HTTP calls, tell me which concurrency model you'd choose for each and why.
Answer
The Global Interpreter Lock is a mutex in CPython that allows only one thread to execute Python bytecode at a time, so threads cannot run Python code truly in parallel on multiple cores. For CPU-bound work I use multiprocessing (or a ProcessPoolExecutor) to sidestep the GIL with separate interpreters across processes. For I/O-bound work, threads are fine because the GIL is released during blocking I/O, so threads overlap their waits. For massive concurrent HTTP, asyncio is best — a single thread cooperatively multiplexing thousands of awaiting coroutines with almost no per-connection overhead.
Deep Technical Explanation
- Why the GIL exists: it simplifies CPython's memory management (reference counting isn't thread-safe without it) and makes C-extension integration easier. The cost is no parallel CPU execution of Python bytecode.
- GIL is released during blocking system calls (network, disk) and inside many C extensions (NumPy heavy math), which is why threading still helps I/O and why NumPy-based CPU work can parallelize despite the GIL.
- Processes each get their own interpreter and GIL, achieving true parallelism, but pay for inter-process communication (pickling) and higher memory.
-
asyncio uses a single-threaded event loop and cooperative scheduling: a coroutine runs until it
awaits, then yields control. No GIL contention, no thread stacks — ideal for tens of thousands of sockets. The catch: one blocking call (a non-async library,time.sleep) freezes the whole loop. - Python 3.13 free-threaded build (experimental, PEP 703) can disable the GIL, changing this landscape — worth naming to show you're current, while noting it isn't yet the default in production.
Real Enterprise Example
A load-generation tool needed 20,000 concurrent API connections. A thread-per-request design collapsed around ~2,000 threads from memory and context-switch overhead. Rewriting the client with asyncio + aiohttp sustained 20k connections in a single process on one core's worth of CPU, because the work was almost entirely waiting on the network.
Common Mistakes
- "Threads make Python parallel" — false for CPU-bound Python.
- Using
multiprocessingfor I/O-bound work (needless pickling/memory). - Mixing a blocking call into an
asyncioloop and freezing everything. - Ignoring that pickling overhead can erase multiprocessing gains for small tasks.
Best Answer in Interview
"The GIL serializes Python bytecode execution, so: CPU-bound → multiprocessing for real parallelism; I/O-bound → threads, since the GIL releases during blocking I/O; huge concurrent HTTP → asyncio, one event loop multiplexing thousands of awaits. I'd also mention the 3.13 free-threaded build as where this is heading."
Follow-up Questions
(The detailed answers to these follow-ups are in the full 112-page guide.)
- Why does NumPy-heavy code sometimes parallelize across threads despite the GIL?
- What breaks if you call a blocking DB driver inside an async coroutine?
-
How does
ProcessPoolExecutorcommunicate results back, and what's the cost?Key Takeaways
GIL blocks parallel Python bytecode, not parallel I/O waits.
CPU→processes, I/O→threads, mass-concurrency→asyncio.
One blocking call poisons an entire event loop.
3. Testing OAuth2 / JWT Authentication
Category: REST Assured
Difficulty: ⭐⭐⭐⭐⭐
Category: REST Assured
Interview Experience: Auth is the most common real-world blocker in API testing. Interviewers want to see you handle OAuth2 token flows and JWTs cleanly — acquiring, caching, and refreshing tokens — rather than pasting a static bearer token that expires mid-run.
Question
How do you handle OAuth2 and JWT authentication in a REST Assured framework so tokens are acquired, reused, and refreshed correctly across a long test run?
Answer
I never hard-code tokens. I implement a token provider that performs the OAuth2 flow (typically client-credentials or password grant for test users), caches the access token with its expiry, and transparently refreshes it before it lapses. The token is injected via a reusable RequestSpecification or a REST Assured Filter, so every request carries a valid bearer token without per-test logic. For JWTs I also validate structure and claims where relevant — decoding to assert issuer, audience, expiry, and scopes as part of security testing.
Deep Technical Explanation
-
Token acquisition: hit the token endpoint once, parse
access_tokenandexpires_in, store both. AFilteror spec addsAuthorization: Bearer <token>to outgoing requests. - Caching + refresh: guard the cached token behind expiry checking; refresh when within a safety margin (e.g., 60s before expiry) so a long run never fails mid-flight. Make this thread-safe for parallel suites (synchronize or use an atomic reference).
- Grant types: client-credentials for service-to-service tests; resource-owner-password for user-context tests against test accounts; authorization-code flows are usually stubbed or pre-provisioned in test environments.
-
JWT validation as testing: decode the JWT (header.payload.signature), assert claims (
iss,aud,exp,scope), and — for security tests — verify the server rejects tampered or expired tokens. - Secrets: client IDs/secrets come from environment/vault, never source control.
Real Enterprise Example
A 45-minute regression suite used a token whose lifetime was 15 minutes; tests started failing two-thirds of the way through with 401s. We introduced a thread-safe token manager that refreshed the token proactively before expiry and injected it via a filter. The intermittent 401 failures vanished, and adding a negative test (expired/altered JWT must return 401) caught a real authorization regression later.
Common Mistakes
- Pasting a static bearer token that expires mid-run.
- Re-fetching a token on every request (slow, rate-limit risk).
- Non-thread-safe token caching in parallel runs.
- Storing client secrets in the repo.
Best Answer in Interview
"A token provider does the OAuth2 flow once, caches the token with its expiry, refreshes proactively before it lapses in a thread-safe way, and injects it via a filter or spec. Secrets come from the environment. For JWTs I also assert claims and add negative tests that the server rejects tampered or expired tokens."
Follow-up Questions
(The detailed answers to these follow-ups are in the full 112-page guide.)
- How do you make token refresh thread-safe without serializing all requests?
- How would you test that an expired token is properly rejected?
-
What's the difference between validating a JWT signature and just decoding claims?
Key Takeaways
Acquire once, cache with expiry, refresh proactively, inject via filter.
Make it thread-safe; keep secrets external.
Negative auth tests are part of the job.
4. API Security — BOLA & Broken Authorization
Category: API Testing
Difficulty: ⭐⭐⭐⭐⭐
Category: API Testing
Interview Experience: Security is now table stakes for senior API testers. Interviewers reference the OWASP API Security Top 10 to see whether you test authorization at the object level, not just authentication — the most exploited class of API vulnerability.
Question
What API security tests do you prioritize, and why is broken object-level authorization (BOLA) the most important one?
Answer
I anchor API security testing on the OWASP API Security Top 10, and the highest-priority class is broken object-level authorization (BOLA/IDOR): verifying that user A cannot access user B's resources by changing an ID. It's the most exploited API flaw because authentication is usually correct but authorization per object is often missing — the endpoint checks you're logged in, not that the record belongs to you. Beyond BOLA I test broken authentication, broken function-level authorization (can a normal user hit admin endpoints?), excessive data exposure (does the response leak fields the client shouldn't see?), injection, mass assignment, and unrestricted resource consumption (missing rate limits).
Deep Technical Explanation
- BOLA/IDOR testing: authenticate as user A, capture a valid request, then replay it substituting user B's object ID. A correct API returns 403/404; a vulnerable one returns B's data. Automate this across every object-scoped endpoint.
- Function-level authorization: authenticate as a low-privilege user and attempt privileged operations; the server must reject based on role, not rely on the UI hiding the button.
- Excessive data exposure: assert responses contain only intended fields — servers that return full DB objects leak PII/internal flags.
-
Mass assignment: send extra fields (
"isAdmin": true) in a create/update and confirm the server ignores non-permitted fields rather than binding them blindly. - Injection & input validation: malformed, oversized, and hostile inputs must be rejected safely.
- Resource consumption: absent rate limits and pagination caps enable DoS; test that limits exist and are enforced.
Real Enterprise Example
An account-details endpoint at /users/{id}/orders checked authentication but not ownership. A tester authenticated as one user and incremented the ID, retrieving another customer's order history — a textbook BOLA. Because we automated ID-substitution tests across all object-scoped endpoints, we caught it pre-release and added an ownership check plus a regression test.
Common Mistakes
- Testing authentication but not per-object authorization.
- Trusting the UI to enforce roles (server must enforce).
- Ignoring mass assignment and excessive data exposure.
- No automated ID-substitution tests across endpoints.
Best Answer in Interview
"I prioritize the OWASP API Top 10, with BOLA first: replay a valid request as another user by swapping the object ID and assert 403/404. It's the most exploited flaw because auth is usually fine but object-level authorization is missing. I also test function-level authorization, excessive data exposure, mass assignment, injection, and missing rate limits."
Follow-up Questions
(The detailed answers to these follow-ups are in the full 112-page guide.)
- How would you automate BOLA checks across hundreds of endpoints?
- What's the difference between object-level and function-level authorization?
-
How do you test for mass assignment safely?
Key Takeaways
BOLA/IDOR is the top API risk — test object-level authz.
Enforce authorization server-side, per object and per function.
Automate ID-substitution across all scoped endpoints.
5. Killing Flaky Tests (Root Cause, Not Retries)
Category: Automation Framework
Difficulty: ⭐⭐⭐⭐⭐
Category: Automation Framework
Interview Experience: Flaky tests are the number-one complaint about automation suites. Interviewers ask this to see if you attack flakiness systematically — identifying root causes and fixing them — rather than papering over it with blanket retries. Reflexively retrying everything is a red flag.
Question
What are the root causes of flaky tests, and how do you systematically eliminate flakiness rather than masking it with retries?
Answer
Flakiness comes from non-determinism, and the main root causes are: improper waits (fixed sleeps or waiting on the wrong condition instead of the element being actionable), test interdependence and shared mutable state, order-dependence, timing/race conditions, unstable test data, and environmental instability. My approach is to quarantine and diagnose, not blindly retry: detect flaky tests via re-run analysis, isolate them, find the root cause (usually waits or shared state), and fix it. Retries are a safety net for genuinely non-deterministic externals, applied narrowly and tracked — never a substitute for fixing the underlying bug, because a retried flaky test still signals a real reliability problem.
Deep Technical Explanation
-
Waits: replace
Thread.sleepand naive presence waits with explicit waits on the actionable condition (clickable, visible, stable), backed by the framework's synchronization. Most UI flake is a wait problem. - Isolation: each test must set up and tear down its own data; shared fixtures create order-dependence where test A's leftover breaks test B. Tests should pass in any order and in parallel.
- Race conditions: async UI updates, animations, and network timing cause intermittent failures — wait on the observable end-state, not a timer.
- Quarantine workflow: a flaky test is moved out of the gating suite, tracked in a flake dashboard with failure rate, root-caused, fixed, then reinstated. This keeps the pipeline trustworthy while the fix happens.
- Narrow retries: retry only at the point of known non-determinism (e.g., a specific network call), report every retry, and alert if retry rate climbs — a rising retry rate is a regression signal, not a solved problem.
- Determinism: control clocks, seeds, and external dependencies (mocks/stubs) to remove timing randomness.
Real Enterprise Example
A UI suite had ~6% flake, and the team had added a global "retry twice" rule that hid it. We built a flake dashboard, quarantined the worst offenders, and found 70% were fixed sleeps and presence-only waits racing async rendering. Switching to explicit actionable waits and making each test own its data dropped flake below 0.5% — and we removed the blanket retry, restoring trust in red builds.
Common Mistakes
- Blanket retries that mask real bugs and erode trust in the suite.
-
Thread.sleepand presence waits instead of actionability waits. - Shared fixtures creating order-dependence.
- No flake tracking, so the same tests fail forever unaddressed.
Best Answer in Interview
"Flakiness is non-determinism — mostly bad waits and shared state. I quarantine flaky tests, root-cause them (usually replacing fixed sleeps with explicit actionable waits and making each test own its data), then reinstate them. Retries are a narrow, tracked safety net for genuine external non-determinism, never a fix — a retried flaky test is still a reliability signal."
Follow-up Questions
(The detailed answers to these follow-ups are in the full 112-page guide.)
- How do you decide a test is flaky vs. exposing a real intermittent bug?
- What's wrong with a global retry policy?
-
How do you make tests order-independent?
Key Takeaways
Root causes: bad waits, shared state, races, unstable data.
Quarantine + diagnose + fix; don't blanket-retry.
Rising retry rate is a regression signal.
🔥 Enjoying the preview? The other 40 questions go deeper
You're halfway through the free sample. The complete guide answers all 150 follow-up questions you see teased here, plus 40 more core questions — including full RAG evaluation, MCP production & security, LLM tool-calling, and agent testing deep-dives.
👉 Unlock the full 200 Q&A on Gumroad: >>https://himanshuai.gumroad.com/l/200InterviewSDETtoAITestArchitectQnA2026<<
6. Testing LLM Hallucination & Faithfulness
Category: AI Testing
Difficulty: ⭐⭐⭐⭐⭐
Category: AI Testing
Interview Experience: Hallucination is the defining reliability problem of LLM products. Interviewers want to know you can measure it, not just describe it — using groundedness/faithfulness metrics and automated evaluation rather than eyeballing outputs.
Question
How do you test for and measure hallucination in an LLM-powered feature, and what does "groundedness" mean operationally?
Answer
A hallucination is output that is fluent and confident but factually wrong or unsupported by the provided context. I test it by measuring groundedness/faithfulness — the degree to which every claim in the response is supported by the source material the model was given. Operationally, I decompose the response into atomic claims and check each against the source context; the faithfulness score is the fraction of claims that are supported. I build an evaluation set of inputs with known-correct grounded answers, run the feature, and score faithfulness automatically (often using an LLM-as-judge plus rule-based checks), tracking the metric over time and gating releases on a threshold. For RAG systems especially, I separate retrieval failures from generation failures, because a hallucination caused by bad retrieval needs a different fix than one caused by the model ignoring good context.
Deep Technical Explanation
- Faithfulness vs. correctness: faithfulness = supported by the given context; correctness = true in the real world. A RAG answer can be faithful to retrieved-but-wrong context, so both matter.
- Claim decomposition: break the response into atomic factual claims, then verify each against the source. The score is supported-claims / total-claims. This is far more diagnostic than a single thumbs-up/down.
- Evaluation datasets: curate representative inputs with reference answers and source contexts; include adversarial and edge cases (ambiguous queries, missing information the model should refuse to answer).
- LLM-as-judge + rules: an LLM grader scores faithfulness/relevance at scale, calibrated against human labels; deterministic rules catch format, citation, and refusal requirements. Never rely on the judge alone without human calibration.
- Refusal testing: a grounded system should say "I don't know" when the context lacks the answer; test that it abstains rather than fabricates.
- Regression gating: faithfulness becomes a tracked metric; a drop below threshold fails the release, just like a functional test.
Real Enterprise Example
A support-assistant RAG feature confidently cited a refund policy that didn't exist. We built an eval set of real queries with source docs, decomposed answers into claims, and scored faithfulness with an LLM-judge calibrated to human labels. The metric exposed that ~15% of answers contained unsupported claims, concentrated in queries where retrieval returned weak context. Fixing retrieval and adding an "abstain when unsupported" instruction raised faithfulness above 95% and gated future regressions.
Common Mistakes
- Eyeballing a few outputs instead of measuring on a dataset.
- Conflating faithfulness (grounded) with correctness (true).
- Trusting an LLM judge without calibrating it to human labels.
- Not testing that the system refuses when the answer is absent.
Best Answer in Interview
"I measure faithfulness — the fraction of response claims supported by the given context — on a curated eval set, decomposing answers into atomic claims and scoring with a human-calibrated LLM-judge plus rules. I separate retrieval failures from generation failures, test that the system abstains when context is missing, and gate releases on the faithfulness threshold as a tracked metric."
Follow-up Questions
(The detailed answers to these follow-ups are in the full 112-page guide.)
- How do you calibrate an LLM-as-judge against human labels?
- Why separate faithfulness from correctness in RAG?
-
How do you build an adversarial hallucination eval set?
Key Takeaways
Faithfulness = claims supported by context; measure it on a dataset.
Decompose into atomic claims; use calibrated LLM-judge + rules.
Test abstention; gate releases on the metric.
7. Temperature vs. Top-p Sampling
Category: LLM
Difficulty: ⭐⭐⭐⭐
Category: LLM
Interview Experience: Sampling parameters are frequently misunderstood. Interviewers ask this to confirm you understand how temperature and top-p shape output and how to configure them for a testable, reliable production feature versus a creative one.
Question
Explain temperature and top-p sampling. How do they interact, and how would you configure them for a factual extraction feature versus a creative one?
Answer
At each step the model produces a probability distribution over the next token. Temperature rescales that distribution before sampling: low temperature (→0) sharpens it toward the most likely tokens (more deterministic, focused), high temperature flattens it (more random, diverse). Top-p (nucleus sampling) restricts sampling to the smallest set of tokens whose cumulative probability reaches p, cutting off the long tail of unlikely tokens. They interact — both narrow or widen the candidate pool — so tuning both at once is confusing; the common advice is to adjust one, usually temperature. For a factual extraction/classification feature I use low temperature (near 0) for consistency and reliability; for a creative feature (brainstorming, copywriting) I raise temperature and/or top-p for diversity. Critically, low temperature reduces but does not guarantee determinism.
Deep Technical Explanation
- Temperature mechanics: dividing logits by temperature before softmax; T<1 concentrates probability on top tokens, T>1 spreads it. T=0 approximates greedy decoding (always the argmax) but true determinism also depends on model/infra version and can still vary.
- Top-p vs top-k: top-k keeps the k most likely tokens; top-p keeps the dynamic set summing to probability p, adapting to how peaked the distribution is — generally preferred because it adjusts to context confidence.
- Interaction guidance: because both control randomness, changing both simultaneously makes behavior hard to reason about. Pick one primary knob per use case.
- Testing implication: for regression tests you pin temperature low and, where supported, a seed to reduce variance — but you still design tests for distributions (see AI Testing) because low temperature isn't fully deterministic across versions.
- Failure modes: too-low temperature can cause repetitive, degenerate loops; too-high causes incoherence and hallucination. There's a task-specific sweet spot found empirically via evals.
Real Enterprise Example
A data-extraction feature (pulling structured fields from documents) was running at the default temperature and produced inconsistent field values across identical inputs, breaking downstream systems. Dropping temperature near 0 stabilized extraction. Meanwhile a marketing-copy feature at the same low temperature produced dull, repetitive text; raising temperature restored variety. Same model, opposite optimal settings — chosen by task.
Common Mistakes
- Believing temperature 0 guarantees identical outputs.
- Tuning temperature and top-p simultaneously and confusing the effect.
- Using high temperature for tasks that need consistency (extraction, classification).
- Not tuning these via evals for the specific task.
Best Answer in Interview
"Temperature rescales the next-token distribution — low sharpens toward the likely tokens, high flattens it — while top-p keeps the smallest token set summing to probability p, trimming the unlikely tail. They both control randomness, so I tune one, usually temperature: near 0 for factual extraction and classification, higher for creative tasks. And I never assume temperature 0 is fully deterministic, so my tests still target distributions."
Follow-up Questions
(The detailed answers to these follow-ups are in the full 112-page guide.)
- Why might top-p be preferable to top-k?
- What causes degenerate repetition at very low temperature?
-
Why isn't temperature 0 perfectly reproducible in practice?
Key Takeaways
Temperature and top-p both control randomness — tune one.
Low temp for consistency, high for creativity.
Low temp ≠ guaranteed determinism.
8. Production RAG Architecture, End to End
Category: RAG
Difficulty: ⭐⭐⭐⭐⭐
Category: RAG
Interview Experience: RAG architecture is a core system-design question for AI test/engineering roles. Interviewers want the full pipeline and — the senior differentiator — the production challenges that make RAG hard beyond the tutorial.
Question
Walk me through a production RAG architecture end to end, and name the challenges that make it hard beyond a demo.
Answer
RAG has two phases. Indexing (offline): ingest documents, chunk them, embed each chunk, and store the vectors (plus metadata) in a vector database. Retrieval + generation (online): embed the user query, retrieve the most relevant chunks (often hybrid dense + keyword search), optionally re-rank them, assemble a prompt with the retrieved context, and have the LLM generate a grounded, ideally cited answer. The challenges that separate a demo from production are: retrieval quality (garbage retrieved → garbage answer, regardless of the LLM), chunking strategy, keeping the index fresh as documents change, handling queries the corpus can't answer (abstain vs. hallucinate), latency budget across embed→retrieve→rerank→generate, cost, evaluating the pipeline stage-by-stage, and security (access control on retrieved documents, and injection via poisoned content).
Deep Technical Explanation
- Indexing pipeline: chunk (size/overlap tuned to content), embed with an appropriate model, store with metadata (source, timestamp, permissions) for filtering and citation; support incremental re-indexing as documents change to avoid staleness.
- Retrieval pipeline: query embedding → vector search (approximate nearest neighbor) → optional hybrid keyword search → re-ranking → context assembly within the token budget, placed to avoid lost-in-the-middle.
- Generation: prompt instructs the model to answer only from context, cite sources, and abstain when the answer isn't present.
- The 80% rule: most RAG failures are retrieval failures, not generation failures — if the right chunk isn't retrieved, no prompt saves you. So retrieval quality is where most effort goes.
- Production challenges: freshness (incremental indexing), access control (a user must not retrieve documents they can't see — a real security requirement), injection via poisoned documents, latency stacking across stages, cost of embeddings + LLM, and stage-wise evaluation so you know which stage failed.
- Security: enforce document-level permissions at retrieval time (filter by the requesting user's access), and treat retrieved content as untrusted (indirect injection risk).
Real Enterprise Example
An internal-docs assistant worked in the demo but failed in production: it retrieved outdated policy versions (no freshness pipeline), occasionally surfaced documents users weren't authorized to see (no permission filtering), and hallucinated when the answer wasn't indexed. We added incremental re-indexing, metadata-based permission filtering at retrieval, an abstain instruction, and stage-wise eval. Answer quality and — critically — the access-control gap were both fixed before wider rollout.
Common Mistakes
- Blaming the LLM when the real failure is retrieval.
- No freshness strategy, serving stale documents.
- No access control on retrieved documents (data-leak risk).
- Evaluating only the final answer, not each pipeline stage.
Best Answer in Interview
"Offline: chunk, embed, store vectors with metadata. Online: embed the query, retrieve (often hybrid), re-rank, assemble context, generate a grounded, cited answer that abstains when the answer isn't present. The hard part is production: most failures are retrieval failures, plus freshness, per-user access control on retrieved docs, injection via poisoned content, latency stacking, cost, and stage-wise evaluation so I know which stage broke."
Follow-up Questions
(The detailed answers to these follow-ups are in the full 112-page guide.)
- Why are most RAG failures retrieval failures rather than generation failures?
- How do you enforce document-level access control in retrieval?
-
How do you keep the index fresh without full re-indexing?
Key Takeaways
Index (chunk→embed→store) then retrieve→rerank→generate.
Retrieval quality dominates; evaluate stage by stage.
Freshness, access control, and injection are production-critical.
9. Model Context Protocol (MCP) — Architecture & Primitives
Category: MCP
Difficulty: ⭐⭐⭐⭐⭐
Category: MCP
Interview Experience: MCP is the 2026 differentiator on AI-focused test/engineering loops. Interviewers want to confirm you understand the protocol's purpose and its core primitives — not just that you've heard the acronym.
Question
What problem does the Model Context Protocol solve, and what are its core primitives and architecture?
Answer
MCP is an open protocol that standardizes how AI applications connect to external tools, data, and context — often described as "a universal connector for AI," replacing bespoke, one-off integrations with a single standard. Its architecture is client-server: a host application (the AI app) runs one or more MCP clients, each maintaining a connection to an MCP server that exposes capabilities. Communication uses JSON-RPC 2.0. The server exposes three core primitives: Tools (functions the model can call to take actions — the model-controlled primitive), Resources (data/content the app can read to provide context — application-controlled), and Prompts (reusable prompt templates the user can invoke — user-controlled). This standardization means any MCP-compatible client can talk to any MCP server, so an integration built once works across every compatible AI application.
Deep Technical Explanation
- Why it exists: before MCP, connecting each AI app to each tool/data source was an N×M integration problem. MCP turns it into N+M — build a server once, and every compatible client can use it.
- Roles: the host is the AI application; it instantiates clients, each holding a 1:1 stateful session with a server. Servers are typically focused (one exposes GitHub, another a database, another a filesystem).
- JSON-RPC 2.0: the wire format for requests, responses, and notifications between client and server.
- Three primitives and who controls them: Tools are model-controlled (the LLM decides to invoke them, with user approval in good clients); Resources are application-controlled (the app decides what context to pull in); Prompts are user-controlled (surfaced for the user to select, like slash commands).
- Capability negotiation: on connection, client and server exchange supported capabilities during initialization, so each side knows what the other offers (tools, resources, prompts, sampling, etc.).
- Currency note: MCP is evolving quickly with dated protocol revisions; I'd confirm details against the current spec rather than rely on memory.
Real Enterprise Example
An enterprise had five AI applications each needing access to the same internal systems (ticketing, docs, database). Originally each app implemented its own integrations — duplicated, inconsistent, and hard to secure. Standardizing on MCP servers (one per system) let all five apps consume the same servers through the standard protocol, cutting integration work dramatically and centralizing security and auditing at the server layer.
Common Mistakes
- Describing MCP as just "function calling" — it's a full client-server protocol with tools, resources, and prompts.
- Confusing the three primitives or who controls each.
- Forgetting capability negotiation during initialization.
- Assuming one server does everything, rather than focused servers.
Best Answer in Interview
"MCP standardizes how AI apps connect to external tools and data — turning an N×M integration mess into N+M. It's client-server over JSON-RPC 2.0: a host runs clients, each with a stateful session to a server. Servers expose three primitives — Tools (model-controlled actions), Resources (application-controlled context), and Prompts (user-controlled templates) — and both sides negotiate capabilities on connect. Build a server once and any compatible client can use it."
Follow-up Questions
(The detailed answers to these follow-ups are in the full 112-page guide.)
- Who controls Tools vs. Resources vs. Prompts, and why does that distinction matter?
- How does MCP reduce the N×M integration problem?
-
What role does capability negotiation play at connection time?
Key Takeaways
MCP = standard connector; N×M → N+M integrations.
Client-server over JSON-RPC 2.0; hosts run clients, clients bind to servers.
Three primitives: Tools (model), Resources (app), Prompts (user).
10. MCP Security — Confused Deputy & Injection
Category: MCP
Difficulty: ⭐⭐⭐⭐⭐
Category: MCP
Interview Experience: Security is the make-or-break MCP topic for senior roles. Because MCP servers expose tools and data to an LLM, interviewers want to know you understand authentication, authorization, and MCP-specific risks like prompt injection through tool results and the confused-deputy problem.
Question
What are the main security concerns with MCP, and how do you address authentication, authorization, and injection risks?
Answer
MCP security is critical because servers grant an LLM access to real tools and data, so a compromise or manipulation has real consequences. The key concerns: authentication (for remote HTTP servers, the spec builds on OAuth 2.1 — servers must verify who the client/user is), authorization (least privilege — a server should expose only the tools and data a given user is permitted to use, and enforce access server-side, never trusting the client or model), prompt injection via tool results (a tool's returned content can contain malicious instructions that hijack the model — indirect injection, treated as untrusted), the confused-deputy problem (a server acting on the model's behalf must not be tricked into using its own privileges for actions the user isn't authorized to perform), token/credential handling (servers hold powerful credentials and must protect them), and user consent (destructive tool calls should require explicit human approval). I test all of these adversarially.
Deep Technical Explanation
- Authentication (remote): the MCP authorization spec is based on OAuth 2.1 for HTTP transports — servers validate tokens, and clients obtain them through standard flows. Local stdio servers rely on process/OS boundaries instead.
- Authorization/least privilege: expose the minimum tool set; enforce per-user permissions at the server, filtering both which tools are callable and which resources are readable. Never rely on the model or client to self-restrict.
- Indirect prompt injection: tool/resource results flow back into the model's context, so malicious content there can drive unintended tool calls or data exfiltration. Treat all tool output as untrusted, and gate high-impact actions behind human approval.
- Confused deputy: because the server acts with its own credentials on behalf of the model/user, it must verify the user's authorization for each action rather than blindly exercising its own privileges — otherwise a low-privilege user could induce privileged actions.
- Credential protection: servers often hold API keys/tokens for downstream systems; store them securely (secret manager), scope them narrowly, and never leak them into model context or logs.
- Consent & auditing: good hosts prompt users before tool execution for sensitive actions; servers should audit-log tool invocations for accountability.
- Testing: adversarial suites for injection via tool results, authorization bypass (can user A invoke user B's tools/data?), confused-deputy scenarios, and credential-leak checks.
Real Enterprise Example
A database MCP server initially exposed a broad query tool with the service account's full privileges to every user. A test showed a lower-privilege user could induce queries against tables they shouldn't see — a confused-deputy/authorization failure. We scoped the server to enforce the requesting user's own permissions per query, added OAuth-based authentication, treated any tool output as untrusted, and required approval for write operations — then encoded these as adversarial regression tests.
Common Mistakes
- Exposing a server's full privileges to all users (confused deputy).
- Trusting tool-result content as safe (indirect injection).
- No authentication on remote servers, or auth without per-user authorization.
- Leaking downstream credentials into model context or logs.
Best Answer in Interview
"MCP hands an LLM real tools and data, so security is paramount. Remote servers authenticate via OAuth 2.1 and enforce per-user authorization server-side with least privilege — never trusting the model or client. Tool results are untrusted input, so indirect injection can hijack the model; high-impact actions need human approval. I guard against the confused-deputy problem by verifying the user's authorization per action, protect downstream credentials, audit tool calls, and test all of this adversarially."
Follow-up Questions
(The detailed answers to these follow-ups are in the full 112-page guide.)
- Explain the confused-deputy problem in an MCP server context.
- Why must tool results be treated as untrusted input?
-
How does least-privilege tool exposure limit blast radius?
Key Takeaways
Authenticate (OAuth 2.1 for remote); authorize per-user, server-side, least privilege.
Tool results are untrusted — indirect injection risk; gate destructive actions.
Guard against confused-deputy; protect credentials; audit and test adversarially.
🚀 Ready to walk into your 2026 interview prepared?
That was 10 of 50 questions — and none of the 150 answered follow-ups. The full 112-page guide gives you everything: Java, Python, REST Assured, API Testing, Automation, AI Testing, LLM, RAG & MCP, plus a 30-day prep roadmap and interview-day tips.
👉 Buy the complete guide on Gumroad: >>https://himanshuai.gumroad.com/l/200InterviewSDETtoAITestArchitectQnA2026<<
More from Himanshu Agarwal
- 📘 MCP Mastery Pack — https://himanshuai.gumroad.com/l/MCP-Mastery-Pack
- 📘 500 SDET + GenAI Interview Questions — https://himanshuai.gumroad.com/l/500-SDET-GenAI-Interview-Questions
- 📚 All books & bundles — https://himanshuai.gumroad.com
If this helped, follow me for more — and drop a comment with the role you're preparing for.
Written by Himanshu Agarwal · himanshuai.com