FallenBirdyForm/test/fixtures.py
2025-06-07 19:24:41 +02:00

365 lines
11 KiB
Python

"""
Test fixtures and utilities for Django FBF tests.
"""
import pytest
from django.contrib.auth.models import User
from django.utils import timezone
from decimal import Decimal
from bird.models import Bird, BirdStatus, Circumstance
from aviary.models import Aviary
from costs.models import Costs
from contact.models import Contact
class TestDataMixin:
"""Mixin class providing common test data setup."""
def create_test_user(self, username='testuser', email='test@example.com', is_staff=False):
"""Create a test user."""
return User.objects.create_user(
username=username,
email=email,
password='testpass123',
is_staff=is_staff
)
def create_test_aviary(self, user, name='Test Aviary'):
"""Create a test aviary."""
return Aviary.objects.create(
name=name,
location='Test Location',
description='Test description',
capacity=20,
current_occupancy=5,
contact_person='Test Contact',
contact_phone='123456789',
contact_email='contact@example.com',
created_by=user
)
def create_test_bird_status(self, name='Gesund'):
"""Create a test bird status."""
return BirdStatus.objects.create(
name=name,
description=f'{name} bird status'
)
def create_test_circumstance(self, name='Gefunden'):
"""Create a test circumstance."""
return Circumstance.objects.create(
name=name,
description=f'{name} circumstance'
)
def create_test_bird(self, user, aviary, status, circumstance, name='Test Bird'):
"""Create a test bird."""
return Bird.objects.create(
name=name,
species='Test Species',
age_group='adult',
gender='unknown',
weight=Decimal('100.50'),
wing_span=Decimal('25.00'),
found_date=timezone.now().date(),
found_location='Test Location',
finder_name='Test Finder',
finder_phone='123456789',
finder_email='finder@example.com',
aviary=aviary,
status=status,
circumstance=circumstance,
notes='Test notes',
created_by=user
)
def create_test_contact(self, user, first_name='John', last_name='Doe'):
"""Create a test contact."""
return Contact.objects.create(
first_name=first_name,
last_name=last_name,
email=f'{first_name.lower()}.{last_name.lower()}@example.com',
phone='123456789',
address='123 Test Street',
city='Test City',
postal_code='12345',
country='Test Country',
is_active=True,
created_by=user
)
def create_test_cost(self, user, bird, amount='50.00', description='Test Cost'):
"""Create a test cost entry."""
return Costs.objects.create(
bird=bird,
description=description,
amount=Decimal(amount),
cost_date=timezone.now().date(),
category='medical',
invoice_number=f'INV-{timezone.now().timestamp()}',
vendor='Test Vendor',
notes='Test cost notes',
created_by=user
)
@pytest.fixture
def test_user():
"""Fixture for creating a test user."""
return User.objects.create_user(
username='fixtureuser',
email='fixture@example.com',
password='fixturepass123'
)
@pytest.fixture
def admin_user():
"""Fixture for creating an admin user."""
return User.objects.create_user(
username='admin',
email='admin@example.com',
password='adminpass123',
is_staff=True,
is_superuser=True
)
@pytest.fixture
def test_aviary(test_user):
"""Fixture for creating a test aviary."""
return Aviary.objects.create(
name='Fixture Aviary',
location='Fixture Location',
capacity=15,
current_occupancy=3,
created_by=test_user
)
@pytest.fixture
def bird_status():
"""Fixture for creating a bird status."""
return BirdStatus.objects.create(
name='Fixture Status',
description='Fixture bird status'
)
@pytest.fixture
def circumstance():
"""Fixture for creating a circumstance."""
return Circumstance.objects.create(
name='Fixture Circumstance',
description='Fixture circumstance'
)
@pytest.fixture
def test_bird(test_user, test_aviary, bird_status, circumstance):
"""Fixture for creating a test bird."""
return Bird.objects.create(
name='Fixture Bird',
species='Fixture Species',
age_group='adult',
gender='male',
weight=Decimal('95.75'),
aviary=test_aviary,
status=bird_status,
circumstance=circumstance,
created_by=test_user
)
class TestUtilities:
"""Utility functions for tests."""
@staticmethod
def assert_model_fields(instance, expected_values):
"""Assert that model instance has expected field values."""
for field, expected_value in expected_values.items():
actual_value = getattr(instance, field)
assert actual_value == expected_value, f"Field {field}: expected {expected_value}, got {actual_value}"
@staticmethod
def assert_form_errors(form, expected_errors):
"""Assert that form has expected validation errors."""
assert not form.is_valid(), "Form should be invalid"
for field, error_messages in expected_errors.items():
assert field in form.errors, f"Field {field} should have errors"
for error_message in error_messages:
assert any(error_message in str(error) for error in form.errors[field]), \
f"Error message '{error_message}' not found in {form.errors[field]}"
@staticmethod
def assert_response_contains(response, expected_content):
"""Assert that response contains expected content."""
if isinstance(expected_content, list):
for content in expected_content:
assert content in response.content.decode(), f"Content '{content}' not found in response"
else:
assert expected_content in response.content.decode(), f"Content '{expected_content}' not found in response"
@staticmethod
def create_form_data(**kwargs):
"""Create form data with default values."""
defaults = {
'name': 'Test Name',
'species': 'Test Species',
'age_group': 'adult',
'gender': 'unknown',
'weight': '100.00'
}
defaults.update(kwargs)
return defaults
@staticmethod
def assert_redirect(response, expected_url=None):
"""Assert that response is a redirect."""
assert response.status_code in [301, 302], f"Expected redirect, got {response.status_code}"
if expected_url:
assert expected_url in response.url, f"Expected redirect to {expected_url}, got {response.url}"
def sample_bird_data():
"""Return sample bird data for testing."""
return [
{
'name': 'Robin',
'species': 'European Robin',
'age_group': 'adult',
'gender': 'male',
'weight': Decimal('18.5')
},
{
'name': 'Sparrow',
'species': 'House Sparrow',
'age_group': 'juvenile',
'gender': 'female',
'weight': Decimal('22.3')
},
{
'name': 'Falcon',
'species': 'Peregrine Falcon',
'age_group': 'adult',
'gender': 'unknown',
'weight': Decimal('750.0')
}
]
def sample_aviary_data():
"""Return sample aviary data for testing."""
return [
{
'name': 'Forest Sanctuary',
'location': 'Black Forest',
'capacity': 25,
'current_occupancy': 8
},
{
'name': 'Lake Resort',
'location': 'Lake Constance',
'capacity': 30,
'current_occupancy': 12
},
{
'name': 'Mountain Refuge',
'location': 'Bavarian Alps',
'capacity': 15,
'current_occupancy': 5
}
]
def create_test_database_state():
"""Create a complete test database state with relationships."""
# Create users
admin = User.objects.create_user(
username='testadmin',
email='admin@testfbf.com',
password='adminpass123',
is_staff=True
)
user = User.objects.create_user(
username='testuser',
email='user@testfbf.com',
password='userpass123'
)
# Create aviaries
aviaries = []
for aviary_data in sample_aviary_data():
aviary = Aviary.objects.create(
**aviary_data,
created_by=admin
)
aviaries.append(aviary)
# Create statuses and circumstances
statuses = [
BirdStatus.objects.create(name='Gesund', description='Healthy bird'),
BirdStatus.objects.create(name='Krank', description='Sick bird'),
BirdStatus.objects.create(name='Verletzt', description='Injured bird'),
]
circumstances = [
Circumstance.objects.create(name='Gefunden', description='Found bird'),
Circumstance.objects.create(name='Gebracht', description='Brought bird'),
Circumstance.objects.create(name='Übertragen', description='Transferred bird'),
]
# Create birds
birds = []
for i, bird_data in enumerate(sample_bird_data()):
bird = Bird.objects.create(
**bird_data,
aviary=aviaries[i % len(aviaries)],
status=statuses[i % len(statuses)],
circumstance=circumstances[i % len(circumstances)],
found_date=timezone.now().date(),
created_by=user
)
birds.append(bird)
# Create contacts
contacts = []
contact_data = [
('John', 'Doe', 'john.doe@example.com'),
('Jane', 'Smith', 'jane.smith@example.com'),
('Bob', 'Johnson', 'bob.johnson@example.com'),
]
for first_name, last_name, email in contact_data:
contact = Contact.objects.create(
first_name=first_name,
last_name=last_name,
email=email,
phone='123456789',
created_by=user
)
contacts.append(contact)
# Create costs
costs = []
for i, bird in enumerate(birds):
cost = Costs.objects.create(
bird=bird,
description=f'Treatment for {bird.name}',
amount=Decimal(f'{50 + i * 10}.75'),
cost_date=timezone.now().date(),
category='medical',
created_by=user
)
costs.append(cost)
return {
'users': [admin, user],
'aviaries': aviaries,
'statuses': statuses,
'circumstances': circumstances,
'birds': birds,
'contacts': contacts,
'costs': costs
}