This article describes a practical, production-ready design for an AI-based test-case generator that converts textual requirements (user stories, acceptance criteria, functional specs) into executable test cases.
We cover architecture, ER diagram, workflow/flowchart, sequence diagram, prompt engineering, sample prompts, backend and frontend examples, test output formats (NUnit / Jest / Cucumber), CI integration, data generation, verification, and production considerations.
All headings use the smaller style you requested. Language is simple Indian English and suitable from beginner to expert.
Overview
Goal: let product owners or developers paste requirements (or upload a spec) and automatically obtain:
Structured test cases (title, steps, preconditions, expected results)
Test code stubs (unit/integration/e2e) in desired framework (NUnit, xUnit, Jest, Cypress)
Test data suggestions and mock payloads
Test metadata (priority, tags, estimated runtime)
CI-ready artifacts (test files, runner config)
Main components: UI to submit requirements, a .NET backend that orchestrates GPT calls + rule-based post-processing, a test template library, a storage layer for test artifacts, and optional runner integration.
High-level architecture
[Angular UI] <--HTTPS--> [ASP.NET Core API] <--HTTPS--> [OpenAI / GPT API]
| | |
| Submit requirements | Builds prompt | Generates structured test JSON / code
| | Stores test artifacts |
v v v
Test Preview Database (SQL) Test Runner / CI
(edit & approve) - Requirements - Execute tests
- GeneratedTests
- Templates
ER Diagram (core entities)
+---------------------+ 1 → N +----------------------+
| Requirement |--------------- | GeneratedTest |
+---------------------+ +----------------------+
| RequirementId (PK) | | TestId (PK) |
| Title | | RequirementId (FK) |
| RawText | | TestTitle |
| CreatedBy | | Priority |
| CreatedAt | | Type (unit/e2e) |
+---------------------+ | Steps (JSON) |
| ExpectedResult |
| CodeSnippet (text) |
| Status (draft/approved)|
+----------------------+
Flowchart / Workflow
[User paste requirement]
↓
[UI sends to API]
↓
[API: Validate + Sanitize]
↓
[API: Build prompt (template + requirement + config)]
↓
[Call GPT API -> parse result JSON]
↓
[Post-process: normalise, validate schema, dedupe]
↓
[Store GeneratedTest in DB]
↓
[UI: Present test cases (edit / approve / export)]
↓
[Export: code stubs (NUnit / Jest / Cucumber) or pipeline artifact]
Sequence diagram (generate + approve + run)
User -> UI: Submit requirements
UI -> API: POST /api/tests/generate
API -> GPT: POST (prompt + schema)
GPT -> API: JSON response (tests)
API -> DB: Save tests
API -> UI: Return tests for preview
User -> UI: Approve / Edit test
UI -> API: POST /api/tests/{id}/approve
API -> CI: Push artifact or create pipeline job
CI -> Test Runner: Execute tests
Runner -> API: Report results
Core design principles
Structured JSON schema for generated tests (always validate).
Prompt templates stored and versioned.
Human-in-the-loop: provide editor UI so testers can refine generated cases.
Multiple output formats: stub code for NUnit, Jest, Cypress, or Gherkin.
Idempotency and deduplication (don’t create duplicate tests for same requirement).
Security: sanitize input, avoid leaking secrets to GPT prompts.
Audit: store prompt + GPT response for traceability.
Test JSON schema (example)
Use a strict schema the backend validates after GPT response.
{
"requirementId": "guid",
"tests": [
{
"testId": "guid",
"title": "Should create order with valid data",
"type": "integration", // unit | integration | e2e
"priority": "P1", // P1|P2|P3
"preconditions": ["User is authenticated", "Cart has items"],
"steps": [
"Call POST /api/orders with payload { ... }",
"Assert response 201"
],
"expectedResult": "Order created and saved with status 'New'",
"testData": {
"payload": { "customerId": 123, "items": [{ "sku": "A1", "qty": 2 }] }
},
"codeTemplates": {
"nunit": "// C# test stub here as string",
"jest": "// JS jest stub here"
}
}
]
}
Prompt engineering (practical templates)
A good prompt instructs the model to return structured JSON only (no prose). Always include a strict response schema and examples.
Minimal prompt (example)
You are a test-case generator. Input: a requirement text and desired output frameworks.
Produce only valid JSON matching the schema:
{ "tests": [ { "title": string, "type": "unit|integration|e2e", "priority": "P1|P2|P3", "preconditions": [string], "steps":[string], "expectedResult": string, "testData": object } ] }
Requirement:
"<PASTE REQUIREMENT HERE>"
Frameworks: ["nunit","jest"]
Rules:
- Use short titles.
- Provide 3 test cases: positive, negative, edge.
- Do not include any explanation.
Advanced prompt (with examples)
Provide 1–2 few-shot examples to improve structure. Keep token size in mind.
Backend: ASP.NET Core — core flow
Responsibilities
Build prompt from requirement + prompt template + configuration
Call GPT API (rate-limit / retry)
Validate response JSON against schema (Newtonsoft / System.Text.Json + JSON schema)
Store tests and prompt/response for audit
Generate code stubs from templates and test data
Provide endpoints for preview, edit, approve, export
API endpoints (suggested)
POST /api/tests/generate — generate tests from requirement
GET /api/tests/{id} — fetch generated tests
POST /api/tests/{id}/approve — approve and export artifacts
GET /api/tests/export/{id}?format=nunit — download code file
Sample controller snippet (C#)
[HttpPost("generate")]
public async Task<IActionResult> Generate([FromBody] GenerateRequest req)
{
// 1. Sanitize input
var text = Sanitize(req.Requirement);
// 2. Build prompt
var prompt = _promptBuilder.Build(req, text);
// 3. Call GPT
var gptResponse = await _gptService.GenerateAsync(prompt);
// 4. Validate JSON schema
var testsJson = ExtractJson(gptResponse);
if (!ValidateSchema(testsJson, out var errors)) return BadRequest(errors);
// 5. Save to DB
var gen = await _repo.SaveGeneratedTests(req.RequirementId, testsJson, prompt, gptResponse);
return Ok(gen);
}
Example GPT call and post-processing
Call GPT with system + user messages and max_tokens, temperature tuned low for deterministic output.
Use function / schema features if available (OpenAI function calling or response schema validation) to enforce JSON output.
After response, parse JSON and run these steps:
Validate required fields exist.
Ensure steps are actionable (each step contains an action + target + assertion).
Add missing test-data defaults (fuzz small values).
Deduplicate similar test cases.
Generating code stubs (templates)
Maintain a template library for each framework. Example: NUnit template (C#)
using NUnit.Framework;
[TestFixture]
public class {{ClassName}}
{
[Test]
public async Task {{TestName}}()
{
// Preconditions
{{#each Preconditions}}
// {{this}}
{{/each}}
// Test data
var payload = {{payloadJson}};
// Action
var response = await HttpClient.PostAsJsonAsync("{{endpoint}}", payload);
// Assert
Assert.AreEqual({{expectedStatus}}, (int)response.StatusCode);
// Additional asserts...
}
}
Use a templating engine (Handlebars.Net or RazorLight) to render with test JSON data.
Test data generation
For typical forms use small realistic values; for boundary cases, generate min/max strings and numbers.
Use seeded random generator for repeatability.
Optionally call a data-faker library (Bogus for .NET, faker.js) to produce realistic test data.
Example end-to-end flow (requirement → JNI test)
Requirement:
"When an authenticated user with role 'Admin' creates a product with price > 0, system must save product and return 201."
Expected generated tests (abridged):
Positive: Admin creates product price 100 → 201 and product saved.
Negative: Admin creates product price -10 → 400 validation error.
Auth: Non-admin creates product → 403 forbidden.
The system produces JSON and then renders NUnit test stubs and Jest API tests.
CI integration and runner
On approval, API can export code files and commit to a special tests repository or create a pipeline artifact (zip).
Provide azure-pipelines.yml or github-actions.yml template to run generated tests. Example GitHub Actions job for .NET tests:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: '8.0.x'
- name: Run tests
run: dotnet test ./GeneratedTests/GeneratedTests.csproj --logger trx
User interface — Angular features
Text area to paste requirement or upload doc.
Controls: target framework(s), number of test cases, test type preferences.
Preview list of generated cases (editable).
Inline code preview tab (NUnit / Jest / Gherkin).
Approve & Export button (download ZIP or push to repo).
History page showing prompt+response for audit.
Key UI endpoints: POST /api/tests/generate, GET /api/tests/{id}, POST /api/tests/{id}/approve, GET /api/tests/export/{id}.
Practical hints for quality & safety
Temperature: use low (0.0–0.3) for deterministic output.
Schema enforcement: prefer function-calling or JSON-schema validating layer.
Few-shot examples: include 1–2 high-quality examples in prompt.
Token limits: trim large requirements; optionally chunk by feature and generate per-feature.
Human review: always show generated tests for human approval before committing.
Rate limits & caching: cache similar requirement -> generated tests mapping to avoid repeated GPT calls.
Security: remove PII before sending to GPT; never send secrets.
Edge cases and advanced features
Traceability: store prompt, model name, model version, and tokens used.
Test flakiness detection: track flaky tests and mark for manual review.
Test prioritisation: auto-assign P1/P2 based on keywords (must, should, should not).
Regression grouping: map tests to requirement IDs to run only related tests on changes.
Coverage hints: attempt to map generated tests to code coverage reports (line/function level) to identify gaps.
Minimal working example (concise)
1) Minimal POST body to /api/tests/generate
{
"requirementId": "b1a6f3c2-...",
"requirementText": "Authenticated admin can create product with price > 0 and gets 201.",
"frameworks": ["nunit"],
"testCount": 3
}
2) Minimal GPT prompt (constructed server-side)
(see Prompt engineering above)
3) Example generated JSON (what API expects from GPT)
{
"tests": [
{
"title": "Admin creates product with valid price",
"type": "integration",
"priority": "P1",
"preconditions": ["Admin user token available"],
"steps": ["POST /api/products with {\"name\":\"P\",\"price\":100}", "Assert 201", "Assert product persisted"],
"testData": { "payload": {"name":"P","price":100} }
},
...
]
}
Monitoring, metrics and cost control
Log model calls and tokens used per request.
Expose usage dashboards (requests/day, tokens/day, cost estimate).
Provide fallback offline generator (simple templates) if model unavailable.
Enforce per-user quota and approval workflow for high-cost runs.
Example Implementation Roadmap (milestones)
Design JSON schema and templates, build prompt templates.
Implement ASP.NET Core service to call GPT + validate JSON.
Build simple Angular UI for requirement input and preview.
Add templating engine to generate code stubs.
Add storage and audit trail.
Add CI export and runner integration.
Add human approval flow and push-to-repo.
Add analytics and cost controls.
Conclusion
An AI-based auto-test generator is a practical productivity tool that reduces manual test writing and speeds up QA cycles. The pattern is:
With careful prompt design, schema validation, templating, and human-in-the-loop review, you can safely automate a large part of test-case generation and integrate it into your development workflow.