Using LLMs to Accelerate TDD in TypeScript with Playwright
Test-Driven Development (TDD) remains a key practice for building maintainable and reliable software. But when writing tests for every Jira story becomes repetitive and time-consuming, automation can help speed up the process without compromising quality.
This tool provides a simple way to generate example Playwright tests from Jira stories using a Large Language Model (LLM). The goal is not to produce production-ready tests, but to offer a structured starting point that developers can review, adapt, and evolve into finalized test cases.
Important Notes
- The generated code is not a replacement for developer-written tests, but a baseline or example to work from.
- This approach is especially helpful for:
- New developers unfamiliar with the existing test structure.
- High-volume or repetitive test writing.
- Ensuring structural consistency in tests across modules.
- This can be integrated into CI tools or local pre-dev workflows for quick scaffolding.
What It Does
- Reads a Jira story from a
.txtfile. - Loads sample Playwright TDD
.tstest files from your existing codebase. - Constructs a well-defined prompt for the LLM.
- Sends the prompt to Google Gemini to generate Playwright + TypeScript code.
- Saves the resulting file to a given output path.
This approach is ideal for backend engineers writing integration tests, especially in systems using FastAPI, AWS Lambda, or RDS-based backends.
Script Code
Below is the full script that powers this workflow:
import os
import argparse
from pathlib import Path
from dotenv import load_dotenv
import google.generativeai as genai # type: ignore
import logging
import sys
# Setup logging
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
# Load environment variables
load_dotenv()
# Validate API Key early
GENAI_API_KEY = os.getenv("GENAI_API_KEY")
if not GENAI_API_KEY:
logging.error("Missing GENAI_API_KEY in environment.")
sys.exit(1)
def get_story_from_file(filepath: str) -> str:
path = Path(filepath)
if not path.exists():
logging.error(f"Story file not found: {filepath}")
sys.exit(1)
content = path.read_text(encoding="utf-8").strip()
if not content:
logging.error(f"Story file is empty: {filepath}")
sys.exit(1)
return content
def get_existing_tdd_text(base_path: str) -> str:
base = Path(base_path)
if not base.exists():
logging.error(f"TDD directory not found: {base_path}")
sys.exit(1)
files = list(base.rglob("*.ts"))
if not files:
logging.warning("No TDD test files found.")
return "\n\n".join(f.read_text(encoding="utf-8").strip() for f in files if f.read_text(encoding="utf-8").strip())
def generate_test_code(prompt: str) -> str:
try:
genai.configure(api_key=GENAI_API_KEY)
model = genai.GenerativeModel('gemini-2.0-flash')
response = model.generate_content(prompt)
code = response.text.strip()
if not code:
logging.error("Generated code is empty.")
sys.exit(1)
return code
except Exception as e:
logging.error(f"Error generating code: {e}")
sys.exit(1)
def build_prompt(tdd_text: str, story_text: str) -> str:
return f"""
You are a senior backend developer specializing in TDD with Playwright and TypeScript.
Follow this example TDD structure carefully:
---
{tdd_text}
---
Now, based on the following Jira story, generate a complete Playwright-based TypeScript test file:
---
{story_text}
---
Constraints:
- Ignore frontend-only scenarios
- Maintain consistent structure with provided examples
- Handle all edge cases and errors
- Ensure code is clean, commented, and ready to run
- Return only valid TypeScript code
"""
def save_to_file(content: str, path: str):
output_path = Path(path)
output_path.parent.mkdir(parents=True, exist_ok=True)
output_path.write_text(content, encoding="utf-8")
logging.info(f"Test code saved to: {output_path.resolve()}")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Generate Playwright TDD from a Jira story.")
parser.add_argument("--story-file", default="card_details.txt", help="Path to story text file.")
parser.add_argument("--tdd-dir", default="../Product-Backend-APIs/tests/Sub_Distributor_Mobile/test-sdst-registration", help="Path to existing TDD test directory.")
parser.add_argument("--output", default="api_project/app.spec.ts", help="Output test file path.")
args = parser.parse_args()
story_text = get_story_from_file(args.story_file)
tdd_text = get_existing_tdd_text(args.tdd_dir)
prompt = build_prompt(tdd_text, story_text)
test_code = generate_test_code(prompt)
save_to_file(test_code, args.output)
logging.info("Test generation complete.")
Example .env File
This .env file is only an example. You must add your own valid API key from Google Gemini:
GENAI_API_KEY=your_actual_google_gemini_api_key
requirements.txt
Install dependencies using pip:
pip install -r requirements.txt
requirements.txt:
python-dotenv
google-generativeai
Sample CLI Usage
python generate_test.py \
--story-file jira_tickets/card_payment_story.txt \
--tdd-dir tests/payment_tests \
--output generated_tests/card_payment.spec.ts
Key Benefits
- Standardizes test structure across teams and modules.
- Accelerates the initial phase of test writing.
- Encourages TDD adoption by reducing boilerplate.
- Can be plugged into any FastAPI, Lambda, or Playwright setup.
- Easy to extend for other LLMs or test frameworks.
Final Thoughts
This script provides a practical example of how LLMs can assist engineering teams with TDD. It will not give you complete, production-ready code—but it will generate structured and relevant test scaffolds you can adapt to your real stories.
Use it to enhance your developer workflow, reduce onboarding friction, and ensure test uniformity across projects.