Ragas · DeepEval · LangSmith · Promptfoo · Garak · Evidently AI
Traditional software testing has deterministic pass/fail criteria: the function returns the right value or it doesn't. LLM systems are probabilistic — the same input can produce different outputs across runs, "correct" is often a matter of degree rather than binary, and failures are frequently silent (the system returns something, just not something accurate or useful). This demands a different testing philosophy and a different toolset.
| Tool | Primary layer | Core strength |
|---|---|---|
| Ragas | RAG evaluation | Automated retrieval + generation quality metrics without human labels |
| DeepEval | Unit + regression testing | pytest-style LLM test suite with 14+ built-in metrics |
| LangSmith | Observability + tracing | Full trace visibility across every LLM call and chain step |
| Promptfoo | Prompt testing + red-team | Side-by-side prompt comparison, automated adversarial probes |
| Garak | Security / safety red-teaming | Systematic LLM vulnerability scanning — jailbreaks, injections, leaks |
| Evidently AI | Production ML monitoring | Data + model drift detection, embedding drift, production dashboards |
| Postman / Newman | API & contract testing | Functional correctness of AI service endpoints — schema, auth, latency, CI/CD gating |
These tools are fast-moving. Treat specifics as directionally accurate and verify current API and metric names against each tool's official docs before an interview.
Ragas evaluates RAG pipelines by scoring both the retrieval and generation stages using LLM-as-a-judge techniques — without requiring a large set of human-labeled ground-truth answers. It computes metrics that together give a full picture of whether retrieval found the right content and whether generation used it faithfully.
| Metric | What it measures | What a low score means |
|---|---|---|
| Faithfulness | Is every claim in the answer grounded in the retrieved context? | Model is hallucinating beyond what the context supports |
| Answer Relevancy | Does the answer actually address the question asked? | Answer is off-topic or incomplete relative to the query |
| Context Precision | Of the retrieved chunks, how many were actually useful? | Retrieval is returning noise alongside signal |
| Context Recall | Did the retrieved context contain all information needed to answer? | Retrieval missed relevant content — index gap or chunking issue |
| Context Relevancy | How relevant are the retrieved chunks to the question? | Retrieval is finding topically adjacent but not useful chunks |
from ragas import evaluate
from ragas.metrics import faithfulness, answer_relevancy, context_recall
from datasets import Dataset
data = Dataset.from_dict({
"question": ["What is the 277CA transaction?"],
"answer": ["The 277CA is the Health Care Claim Acknowledgement..."],
"contexts": [["277CA is sent by payer to acknowledge receipt of claims..."]],
"ground_truth": ["The 277CA acknowledges receipt and validity of 837 claims"]
})
results = evaluate(data, metrics=[faithfulness, answer_relevancy, context_recall])
print(results)
# {'faithfulness': 0.94, 'answer_relevancy': 0.89, 'context_recall': 0.91}
DeepEval is a pytest-compatible LLM testing framework with 14+ built-in metrics. It brings traditional software testing discipline (test cases, assertion logic, CI integration) to LLM outputs — letting you write, run, and track test suites the same way you'd manage unit tests in a software project.
Did the response stay on topic with the input?
Is every claim supported by the retrieved context?
Does the output contradict known context or facts?
Does the output contain harmful or offensive content?
Does the output exhibit demographic or factual bias?
Define any arbitrary criteria in natural language — flexible for domain-specific quality checks
from deepeval import evaluate
from deepeval.metrics import AnswerRelevancyMetric, FaithfulnessMetric
from deepeval.test_case import LLMTestCase
test_case = LLMTestCase(
input="What does a 277CA acknowledge?",
actual_output="The 277CA is sent by the payer to acknowledge 837 claim receipt.",
retrieval_context=["277CA acknowledges receipt and syntactic validity of 837 submissions."]
)
relevancy = AnswerRelevancyMetric(threshold=0.7)
faithfulness = FaithfulnessMetric(threshold=0.8)
evaluate([test_case], [relevancy, faithfulness])
LangSmith is an observability and evaluation platform from LangChain. It traces every step of a LangChain or LangGraph execution — each LLM call, retrieval, tool invocation, and chain branch — giving you full visibility into what happened, how long it took, what it cost, and whether the output was correct. Think of it as the APM (Application Performance Monitoring) layer for LLM applications.
import os
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langsmith import traceable
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "your-api-key"
@traceable # auto-traces this function in LangSmith
def run_rag_pipeline(question: str, context: str) -> str:
prompt = ChatPromptTemplate.from_template(
"Answer from context only:\n{context}\n\nQ: {question}"
)
chain = prompt | ChatOpenAI(model="gpt-4o-mini")
return chain.invoke({"question": question, "context": context})
Promptfoo is a CLI and CI-integrated tool for systematically testing and comparing prompts. It runs your prompt variants across a test suite, scores outputs against assertions, and generates comparison reports — making prompt changes as reviewable and measurable as code changes. It also includes a built-in automated red-team module that probes prompts for safety and security vulnerabilities.
# promptfooconfig.yaml
prompts:
- "Answer using only this context:\n{{context}}\n\nQ: {{question}}"
- "You are a healthcare assistant. Context: {{context}}\nQuestion: {{question}}"
providers:
- openai:gpt-4o-mini
- openai:gpt-4o
tests:
- vars:
question: "What are the 277CA status codes?"
context: "277CA uses status codes CA, CD, and CE to indicate..."
assert:
- type: contains
value: "CA"
- type: llm-rubric
value: "Answer must reference HIPAA 5010 standards"
- type: not-contains
value: "I don't know"
Garak is an open-source LLM vulnerability scanner specifically focused on security and safety red-teaming. Where Promptfoo's red-team module is a broad sweep, Garak goes deep: it systematically probes a model or application across dozens of attack categories with hundreds of individual probes, and generates structured vulnerability reports.
| Category | What it probes |
|---|---|
| Jailbreaks | Prompt patterns that override system instructions (DAN, roleplay, encoding tricks) |
| Prompt injection | Malicious instructions hidden in user input or tool results that hijack the model |
| Data exfiltration | Attempts to extract system prompt contents or internal context the model shouldn't reveal |
| Hallucination probes | Queries designed to elicit confident false statements |
| Toxicity / harmful content | Probes for harmful, violent, or discriminatory output generation |
| Package / code risks | LLM-generated code that references malicious or non-existent packages |
| Continuation attacks | Prompts designed to make the model continue harmful completions |
# run Garak against an OpenAI endpoint
garak --model_type openai \
--model_name gpt-4o-mini \
--probes jailbreak,promptinject,leakreplay \
--report_prefix my_system_audit
# Garak outputs a structured JSONL report
# listing each probe, outcome, and severity
For healthcare or regulated environments: Garak scans are a strong artifact to produce as evidence of security due diligence, even if the full output requires expert interpretation.
Evidently AI is an open-source ML observability platform focused on monitoring models and data in production. For LLM systems it tracks text quality, embedding drift, data distribution shifts, and output quality degradation over time — answering the question traditional testing can't: "Is the system still performing the same way it was when we shipped it?"
| Monitor | What it detects | Why it matters |
|---|---|---|
| Embedding drift | Query embeddings shifting away from the distribution the system was tested on | Users are asking different things than anticipated — retrieval may be degrading silently |
| Text quality metrics | Output length, readability, OOV word rate, sentiment drift | Model behavior or output style changing post-deployment |
| Data drift (input) | Statistical distribution shift in incoming queries or documents | Data upstream of the pipeline changed — index may be stale |
| LLM quality scores | Tracks Ragas-style metrics (faithfulness, relevancy) sampled from production traffic over time | Catches gradual quality degradation without waiting for user complaints |
| Custom metrics | Any numeric metric you compute on outputs | Domain-specific KPIs (e.g. % of answers that cite a source) |
from evidently.report import Report
from evidently.metric_preset import TextEvals
from evidently import ColumnMapping
import pandas as pd
# production sample: questions + answers logged from live traffic
current_data = pd.DataFrame({
"question": [...],
"answer": [...],
"context": [...]
})
report = Report(metrics=[TextEvals()])
report.run(reference_data=baseline_data, current_data=current_data)
report.save_html("drift_report.html")
Every AI system — a RAG pipeline, an agent, a fine-tuned model endpoint — is ultimately served behind an API: a REST or GraphQL endpoint that takes a request and returns a response. Ragas, DeepEval, and Promptfoo test whether the content of that response is good. Postman and Newman test whether the service itself is correct — status codes, schema, authentication, latency, and error handling. Skipping this layer means shipping an LLM system that scores well on quality metrics but breaks under a malformed payload, a slow downstream call, or an expired token. Your EDI background maps onto this directly: a 277CA has to validate against its schema and envelope structure before anyone asks whether its content is meaningful, and an AI API is no different.
| Check | What it verifies | Why it matters for AI systems |
|---|---|---|
| Schema validation | Response body matches the expected JSON schema | An LLM API returning malformed or partial JSON breaks every downstream consumer silently |
| Status code / error handling | Correct codes for auth failure, rate limits, timeouts, bad input | Model providers rate-limit and time out constantly; the wrapping API must fail predictably |
| Auth & headers | API keys, OAuth tokens, and required headers are enforced | Same compliance discipline as HIPAA EDI transactions — access control is non-negotiable |
| Latency thresholds | Response time stays under an agreed SLA | LLM calls are slow and variable; a regression here is a real production incident |
| Contract testing | Request/response shape stays stable across versions | Prevents a backend model swap or prompt change from silently breaking client integrations |
| Chained requests | Multi-step flows — e.g. auth → retrieve → generate → log — run and pass in sequence | Mirrors real agent/RAG call chains, not just a single isolated endpoint |
// Postman test script — attached to a "Generate Answer" request
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
pm.test("Response matches schema", function () {
const body = pm.response.json();
pm.expect(body).to.have.property("answer");
pm.expect(body).to.have.property("sources").that.is.an("array");
pm.expect(body.sources.length).to.be.above(0);
});
pm.test("Latency under SLA", function () {
pm.expect(pm.response.responseTime).to.be.below(3000);
});
pm.test("Auth header enforced on 401 case", function () {
if (!pm.request.headers.has("Authorization")) {
pm.response.to.have.status(401);
}
});
# Newman — run the collection headlessly in CI/CD newman run ai-api-collection.json \ -e staging.postman_environment.json \ --reporters cli,junit \ --reporter-junit-export results/api-test-report.xml # Exit code is non-zero on any failed assertion, # which fails the pipeline build step automatically
Positioning for an interview: API testing is the layer that makes sure the AI system is a reliable service. Content-quality tools make sure it's a good service. Both are required — a system can pass every Ragas metric and still fail production if the endpoint times out under load or returns an unvalidated schema to a downstream consumer.
Click a question to expand the answer.