kaauh_ats/load_tests/test_data_generator.py
2025-12-10 13:56:51 +03:00

347 lines
14 KiB
Python

"""
Test data generator for ATS load testing.
This module provides utilities to generate realistic test data
for load testing scenarios including jobs, users, and applications.
"""
import os
import json
import random
from datetime import datetime, timedelta
from faker import Faker
from typing import List, Dict, Any
import django
from django.conf import settings
# Initialize Faker
fake = Faker()
class TestDataGenerator:
"""Generates test data for ATS load testing."""
def __init__(self):
self.job_titles = [
"Software Engineer", "Senior Developer", "Frontend Developer",
"Backend Developer", "Full Stack Developer", "DevOps Engineer",
"Data Scientist", "Machine Learning Engineer", "Product Manager",
"UX Designer", "UI Designer", "Business Analyst",
"Project Manager", "Scrum Master", "QA Engineer",
"System Administrator", "Network Engineer", "Security Analyst",
"Database Administrator", "Cloud Engineer", "Mobile Developer"
]
self.departments = [
"Engineering", "Product", "Design", "Marketing", "Sales",
"HR", "Finance", "Operations", "Customer Support", "IT"
]
self.locations = [
"Riyadh", "Jeddah", "Dammam", "Mecca", "Medina",
"Khobar", "Tabuk", "Abha", "Hail", "Najran"
]
self.skills = [
"Python", "JavaScript", "Java", "C++", "Go", "Rust",
"React", "Vue.js", "Angular", "Django", "Flask", "FastAPI",
"PostgreSQL", "MySQL", "MongoDB", "Redis", "Elasticsearch",
"Docker", "Kubernetes", "AWS", "Azure", "GCP",
"Git", "CI/CD", "Agile", "Scrum", "TDD"
]
def generate_job_posting(self, job_id: int = None) -> Dict[str, Any]:
"""Generate a realistic job posting."""
if job_id is None:
job_id = random.randint(1, 1000)
title = random.choice(self.job_titles)
department = random.choice(self.departments)
location = random.choice(self.locations)
# Generate job description
description = f"""
We are seeking a talented {title} to join our {department} team in {location}.
Responsibilities:
- Design, develop, and maintain high-quality software solutions
- Collaborate with cross-functional teams to deliver projects
- Participate in code reviews and technical discussions
- Mentor junior developers and share knowledge
- Stay updated with latest technologies and best practices
Requirements:
- Bachelor's degree in Computer Science or related field
- {random.randint(3, 8)}+ years of relevant experience
- Strong programming skills in relevant technologies
- Excellent problem-solving and communication skills
- Experience with agile development methodologies
"""
# Generate qualifications
qualifications = f"""
Required Skills:
- {random.choice(self.skills)}
- {random.choice(self.skills)}
- {random.choice(self.skills)}
- Experience with version control (Git)
- Strong analytical and problem-solving skills
Preferred Skills:
- {random.choice(self.skills)}
- {random.choice(self.skills)}
- Cloud computing experience
- Database design and optimization
"""
# Generate benefits
benefits = """
Competitive salary and benefits package
Health insurance and medical coverage
Professional development opportunities
Flexible work arrangements
Annual performance bonuses
Employee wellness programs
"""
# Generate application instructions
application_instructions = """
To apply for this position:
1. Submit your updated resume
2. Include a cover letter explaining your interest
3. Provide portfolio or GitHub links if applicable
4. Complete the online assessment
5. Wait for our recruitment team to contact you
"""
# Generate deadlines and dates
posted_date = fake.date_between(start_date="-30d", end_date="today")
application_deadline = posted_date + timedelta(days=random.randint(30, 90))
return {
"id": job_id,
"title": title,
"slug": f"{title.lower().replace(' ', '-')}-{job_id}",
"description": description.strip(),
"qualifications": qualifications.strip(),
"benefits": benefits.strip(),
"application_instructions": application_instructions.strip(),
"department": department,
"location": location,
"employment_type": random.choice(["Full-time", "Part-time", "Contract", "Temporary"]),
"experience_level": random.choice(["Entry", "Mid", "Senior", "Lead"]),
"salary_min": random.randint(5000, 15000),
"salary_max": random.randint(15000, 30000),
"is_active": True,
"posted_date": posted_date.isoformat(),
"application_deadline": application_deadline.isoformat(),
"internal_job_id": f"JOB-{job_id:06d}",
"hash_tags": f"#{title.replace(' ', '')},#{department},#{location},#hiring",
"application_url": f"/jobs/{title.lower().replace(' ', '-')}-{job_id}/apply/"
}
def generate_user_profile(self, user_id: int = None) -> Dict[str, Any]:
"""Generate a realistic user profile."""
if user_id is None:
user_id = random.randint(1, 1000)
first_name = fake.first_name()
last_name = fake.last_name()
email = fake.email()
return {
"id": user_id,
"username": f"{first_name.lower()}.{last_name.lower()}{user_id}",
"email": email,
"first_name": first_name,
"last_name": last_name,
"phone": fake.phone_number(),
"location": fake.city(),
"bio": fake.text(max_nb_chars=200),
"linkedin_profile": f"https://linkedin.com/in/{first_name.lower()}-{last_name.lower()}{user_id}",
"github_profile": f"https://github.com/{first_name.lower()}{last_name.lower()}{user_id}",
"portfolio_url": f"https://{first_name.lower()}{last_name.lower()}{user_id}.com",
"is_staff": random.choice([True, False]),
"is_active": True,
"date_joined": fake.date_between(start_date="-2y", end_date="today").isoformat(),
"last_login": fake.date_between(start_date="-30d", end_date="today").isoformat()
}
def generate_application(self, application_id: int = None, job_id: int = None, user_id: int = None) -> Dict[str, Any]:
"""Generate a realistic job application."""
if application_id is None:
application_id = random.randint(1, 5000)
if job_id is None:
job_id = random.randint(1, 100)
if user_id is None:
user_id = random.randint(1, 500)
statuses = ["PENDING", "REVIEWING", "SHORTLISTED", "INTERVIEW", "OFFER", "HIRED", "REJECTED"]
status = random.choice(statuses)
# Generate application date
applied_date = fake.date_between(start_date="-60d", end_date="today")
# Generate cover letter
cover_letter = f"""
Dear Hiring Manager,
I am writing to express my strong interest in the position at your organization.
With my background and experience, I believe I would be a valuable addition to your team.
{fake.text(max_nb_chars=300)}
I look forward to discussing how my skills and experience align with your needs.
Best regards,
{fake.name()}
"""
return {
"id": application_id,
"job_id": job_id,
"user_id": user_id,
"status": status,
"applied_date": applied_date.isoformat(),
"cover_letter": cover_letter.strip(),
"resume_file": f"resume_{application_id}.pdf",
"portfolio_url": fake.url() if random.choice([True, False]) else None,
"linkedin_url": fake.url() if random.choice([True, False]) else None,
"github_url": fake.url() if random.choice([True, False]) else None,
"expected_salary": random.randint(5000, 25000),
"available_start_date": (fake.date_between(start_date="+1w", end_date="+2m")).isoformat(),
"notice_period": random.choice(["Immediate", "1 week", "2 weeks", "1 month"]),
"source": random.choice(["LinkedIn", "Company Website", "Referral", "Job Board", "Social Media"]),
"notes": fake.text(max_nb_chars=100) if random.choice([True, False]) else None
}
def generate_interview(self, interview_id: int = None, application_id: int = None) -> Dict[str, Any]:
"""Generate a realistic interview schedule."""
if interview_id is None:
interview_id = random.randint(1, 2000)
if application_id is None:
application_id = random.randint(1, 500)
interview_types = ["Phone Screen", "Technical Interview", "Behavioral Interview", "Final Interview", "HR Interview"]
interview_type = random.choice(interview_types)
# Generate interview date and time
interview_datetime = fake.date_time_between(start_date="-30d", end_date="+30d")
return {
"id": interview_id,
"application_id": application_id,
"type": interview_type,
"scheduled_date": interview_datetime.isoformat(),
"duration": random.randint(30, 120), # minutes
"location": random.choice(["Office", "Video Call", "Phone Call"]),
"interviewer": fake.name(),
"interviewer_email": fake.email(),
"status": random.choice(["SCHEDULED", "COMPLETED", "CANCELLED", "RESCHEDULED"]),
"notes": fake.text(max_nb_chars=200) if random.choice([True, False]) else None,
"meeting_id": f"meeting_{interview_id}" if random.choice([True, False]) else None,
"meeting_url": f"https://zoom.us/j/{interview_id}" if random.choice([True, False]) else None
}
def generate_message(self, message_id: int = None, sender_id: int = None, recipient_id: int = None) -> Dict[str, Any]:
"""Generate a realistic message between users."""
if message_id is None:
message_id = random.randint(1, 3000)
if sender_id is None:
sender_id = random.randint(1, 500)
if recipient_id is None:
recipient_id = random.randint(1, 500)
message_types = ["DIRECT", "SYSTEM", "NOTIFICATION"]
message_type = random.choice(message_types)
return {
"id": message_id,
"sender_id": sender_id,
"recipient_id": recipient_id,
"subject": fake.sentence(nb_words=6),
"content": fake.text(max_nb_chars=500),
"message_type": message_type,
"is_read": random.choice([True, False]),
"created_at": fake.date_time_between(start_date="-30d", end_date="today").isoformat(),
"read_at": fake.date_time_between(start_date="-29d", end_date="today").isoformat() if random.choice([True, False]) else None
}
def generate_bulk_data(self, config: Dict[str, int]) -> Dict[str, List[Dict]]:
"""Generate bulk test data based on configuration."""
data = {
"jobs": [],
"users": [],
"applications": [],
"interviews": [],
"messages": []
}
# Generate jobs
for i in range(config.get("job_count", 100)):
data["jobs"].append(self.generate_job_posting(i + 1))
# Generate users
for i in range(config.get("user_count", 50)):
data["users"].append(self.generate_user_profile(i + 1))
# Generate applications
for i in range(config.get("application_count", 500)):
job_id = random.randint(1, len(data["jobs"]))
user_id = random.randint(1, len(data["users"]))
data["applications"].append(self.generate_application(i + 1, job_id, user_id))
# Generate interviews (for some applications)
interview_count = len(data["applications"]) // 2 # Half of applications have interviews
for i in range(interview_count):
application_id = random.randint(1, len(data["applications"]))
data["interviews"].append(self.generate_interview(i + 1, application_id))
# Generate messages
message_count = config.get("user_count", 50) * 5 # 5 messages per user on average
for i in range(message_count):
sender_id = random.randint(1, len(data["users"]))
recipient_id = random.randint(1, len(data["users"]))
data["messages"].append(self.generate_message(i + 1, sender_id, recipient_id))
return data
def save_test_data(self, data: Dict[str, List[Dict]], output_dir: str = "load_tests/test_data"):
"""Save generated test data to JSON files."""
os.makedirs(output_dir, exist_ok=True)
for data_type, records in data.items():
filename = os.path.join(output_dir, f"{data_type}.json")
with open(filename, 'w') as f:
json.dump(records, f, indent=2, default=str)
print(f"Saved {len(records)} {data_type} to {filename}")
def create_test_files(self, count: int = 100, output_dir: str = "load_tests/test_files"):
"""Create test files for upload testing."""
os.makedirs(output_dir, exist_ok=True)
for i in range(count):
# Create a simple text file
content = fake.text(max_nb_chars=1000)
filename = os.path.join(output_dir, f"test_file_{i + 1}.txt")
with open(filename, 'w') as f:
f.write(content)
print(f"Created {count} test files in {output_dir}")
if __name__ == "__main__":
# Example usage
generator = TestDataGenerator()
# Generate test data
config = {
"job_count": 50,
"user_count": 25,
"application_count": 200
}
test_data = generator.generate_bulk_data(config)
generator.save_test_data(test_data)
generator.create_test_files(50)
print("Test data generation completed!")