- Enable pytest-xdist with -n auto for parallel test execution - Consolidate migrated_db fixture in conftest.py (was duplicated in 4 files) - Remove local fixture definitions and unused imports from test files Test execution: ~24s -> ~5s (~5x speedup) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
231 lines
8.0 KiB
Python
231 lines
8.0 KiB
Python
# ABOUTME: Tests for the reference data seeder.
|
|
# ABOUTME: Validates that seeding populates correct data and is idempotent.
|
|
|
|
from animaltrack.models.reference import ProductUnit, UserRole
|
|
from animaltrack.repositories import (
|
|
FeedTypeRepository,
|
|
LocationRepository,
|
|
ProductRepository,
|
|
SpeciesRepository,
|
|
UserRepository,
|
|
)
|
|
from animaltrack.seeds import run_seeds
|
|
|
|
|
|
class TestSeedCounts:
|
|
"""Tests that seeding creates the correct number of records."""
|
|
|
|
def test_seeds_three_users(self, migrated_db):
|
|
"""Seeding creates 3 users."""
|
|
run_seeds(migrated_db)
|
|
repo = UserRepository(migrated_db)
|
|
assert len(repo.list_all()) == 3
|
|
|
|
def test_seeds_eight_locations(self, migrated_db):
|
|
"""Seeding creates 8 locations."""
|
|
run_seeds(migrated_db)
|
|
repo = LocationRepository(migrated_db)
|
|
assert len(repo.list_all()) == 8
|
|
|
|
def test_seeds_three_species(self, migrated_db):
|
|
"""Seeding creates 3 species."""
|
|
run_seeds(migrated_db)
|
|
repo = SpeciesRepository(migrated_db)
|
|
assert len(repo.list_all()) == 3
|
|
|
|
def test_seeds_seven_products(self, migrated_db):
|
|
"""Seeding creates 7 products."""
|
|
run_seeds(migrated_db)
|
|
repo = ProductRepository(migrated_db)
|
|
assert len(repo.list_all()) == 7
|
|
|
|
def test_seeds_three_feed_types(self, migrated_db):
|
|
"""Seeding creates 3 feed types."""
|
|
run_seeds(migrated_db)
|
|
repo = FeedTypeRepository(migrated_db)
|
|
assert len(repo.list_all()) == 3
|
|
|
|
|
|
class TestSeedIdempotency:
|
|
"""Tests that seeding is idempotent."""
|
|
|
|
def test_seeding_twice_same_user_count(self, migrated_db):
|
|
"""Seeding twice produces same number of users."""
|
|
run_seeds(migrated_db)
|
|
run_seeds(migrated_db)
|
|
repo = UserRepository(migrated_db)
|
|
assert len(repo.list_all()) == 3
|
|
|
|
def test_seeding_twice_same_location_count(self, migrated_db):
|
|
"""Seeding twice produces same number of locations."""
|
|
run_seeds(migrated_db)
|
|
run_seeds(migrated_db)
|
|
repo = LocationRepository(migrated_db)
|
|
assert len(repo.list_all()) == 8
|
|
|
|
def test_seeding_twice_same_species_count(self, migrated_db):
|
|
"""Seeding twice produces same number of species."""
|
|
run_seeds(migrated_db)
|
|
run_seeds(migrated_db)
|
|
repo = SpeciesRepository(migrated_db)
|
|
assert len(repo.list_all()) == 3
|
|
|
|
def test_seeding_twice_same_product_count(self, migrated_db):
|
|
"""Seeding twice produces same number of products."""
|
|
run_seeds(migrated_db)
|
|
run_seeds(migrated_db)
|
|
repo = ProductRepository(migrated_db)
|
|
assert len(repo.list_all()) == 7
|
|
|
|
def test_seeding_twice_same_feed_type_count(self, migrated_db):
|
|
"""Seeding twice produces same number of feed types."""
|
|
run_seeds(migrated_db)
|
|
run_seeds(migrated_db)
|
|
repo = FeedTypeRepository(migrated_db)
|
|
assert len(repo.list_all()) == 3
|
|
|
|
|
|
class TestUserSeedData:
|
|
"""Tests for correct user seed data."""
|
|
|
|
def test_ppetru_is_admin(self, migrated_db):
|
|
"""User ppetru has admin role."""
|
|
run_seeds(migrated_db)
|
|
repo = UserRepository(migrated_db)
|
|
user = repo.get("ppetru")
|
|
assert user is not None
|
|
assert user.role == UserRole.ADMIN
|
|
assert user.active is True
|
|
|
|
def test_ines_is_admin(self, migrated_db):
|
|
"""User ines has admin role."""
|
|
run_seeds(migrated_db)
|
|
repo = UserRepository(migrated_db)
|
|
user = repo.get("ines")
|
|
assert user is not None
|
|
assert user.role == UserRole.ADMIN
|
|
|
|
def test_guest_is_recorder(self, migrated_db):
|
|
"""User guest has recorder role."""
|
|
run_seeds(migrated_db)
|
|
repo = UserRepository(migrated_db)
|
|
user = repo.get("guest")
|
|
assert user is not None
|
|
assert user.role == UserRole.RECORDER
|
|
|
|
|
|
class TestLocationSeedData:
|
|
"""Tests for correct location seed data."""
|
|
|
|
def test_strip_locations_exist(self, migrated_db):
|
|
"""All 4 strip locations exist."""
|
|
run_seeds(migrated_db)
|
|
repo = LocationRepository(migrated_db)
|
|
for i in range(1, 5):
|
|
location = repo.get_by_name(f"Strip {i}")
|
|
assert location is not None, f"Strip {i} not found"
|
|
assert location.active is True
|
|
|
|
def test_nursery_locations_exist(self, migrated_db):
|
|
"""All 4 nursery locations exist."""
|
|
run_seeds(migrated_db)
|
|
repo = LocationRepository(migrated_db)
|
|
for i in range(1, 5):
|
|
location = repo.get_by_name(f"Nursery {i}")
|
|
assert location is not None, f"Nursery {i} not found"
|
|
assert location.active is True
|
|
|
|
def test_location_ids_are_valid_ulids(self, migrated_db):
|
|
"""All location IDs are 26 characters (ULID format)."""
|
|
run_seeds(migrated_db)
|
|
repo = LocationRepository(migrated_db)
|
|
for location in repo.list_all():
|
|
assert len(location.id) == 26
|
|
|
|
|
|
class TestSpeciesSeedData:
|
|
"""Tests for correct species seed data."""
|
|
|
|
def test_duck_is_active(self, migrated_db):
|
|
"""Species duck is active."""
|
|
run_seeds(migrated_db)
|
|
repo = SpeciesRepository(migrated_db)
|
|
species = repo.get("duck")
|
|
assert species is not None
|
|
assert species.name == "Duck"
|
|
assert species.active is True
|
|
|
|
def test_goose_is_active(self, migrated_db):
|
|
"""Species goose is active."""
|
|
run_seeds(migrated_db)
|
|
repo = SpeciesRepository(migrated_db)
|
|
species = repo.get("goose")
|
|
assert species is not None
|
|
assert species.name == "Goose"
|
|
assert species.active is True
|
|
|
|
def test_sheep_is_inactive(self, migrated_db):
|
|
"""Species sheep is inactive."""
|
|
run_seeds(migrated_db)
|
|
repo = SpeciesRepository(migrated_db)
|
|
species = repo.get("sheep")
|
|
assert species is not None
|
|
assert species.name == "Sheep"
|
|
assert species.active is False
|
|
|
|
|
|
class TestProductSeedData:
|
|
"""Tests for correct product seed data."""
|
|
|
|
def test_egg_duck_product(self, migrated_db):
|
|
"""Product egg.duck has correct attributes."""
|
|
run_seeds(migrated_db)
|
|
repo = ProductRepository(migrated_db)
|
|
product = repo.get("egg.duck")
|
|
assert product is not None
|
|
assert product.name == "Duck Egg"
|
|
assert product.unit == ProductUnit.PIECE
|
|
assert product.collectable is True
|
|
assert product.sellable is True
|
|
|
|
def test_meat_products_use_kg(self, migrated_db):
|
|
"""All meat-related products use kg unit."""
|
|
run_seeds(migrated_db)
|
|
repo = ProductRepository(migrated_db)
|
|
kg_products = ["meat", "offal", "fat", "bones", "feathers", "down"]
|
|
for code in kg_products:
|
|
product = repo.get(code)
|
|
assert product is not None, f"Product {code} not found"
|
|
assert product.unit == ProductUnit.KG, f"Product {code} should use kg"
|
|
|
|
|
|
class TestFeedTypeSeedData:
|
|
"""Tests for correct feed type seed data."""
|
|
|
|
def test_starter_feed_type(self, migrated_db):
|
|
"""Feed type starter has correct attributes."""
|
|
run_seeds(migrated_db)
|
|
repo = FeedTypeRepository(migrated_db)
|
|
feed_type = repo.get("starter")
|
|
assert feed_type is not None
|
|
assert feed_type.name == "Starter Feed"
|
|
assert feed_type.default_bag_size_kg == 20
|
|
|
|
def test_grower_feed_type(self, migrated_db):
|
|
"""Feed type grower has correct attributes."""
|
|
run_seeds(migrated_db)
|
|
repo = FeedTypeRepository(migrated_db)
|
|
feed_type = repo.get("grower")
|
|
assert feed_type is not None
|
|
assert feed_type.name == "Grower Feed"
|
|
assert feed_type.default_bag_size_kg == 20
|
|
|
|
def test_layer_feed_type(self, migrated_db):
|
|
"""Feed type layer has correct attributes."""
|
|
run_seeds(migrated_db)
|
|
repo = FeedTypeRepository(migrated_db)
|
|
feed_type = repo.get("layer")
|
|
assert feed_type is not None
|
|
assert feed_type.name == "Layer Feed"
|
|
assert feed_type.default_bag_size_kg == 20
|