- Fix TypeError in check_steal_opportunity by properly mocking catcher defense - Correct tag_from_third test calculation to account for all adjustment conditions - Fix pitcher replacement test by setting appropriate allowed runners threshold - Add comprehensive test coverage for AI service business logic - Implement VS Code testing panel configuration with pytest integration - Create pytest.ini for consistent test execution and warning management - Add test isolation guidelines and factory pattern implementation - Establish 102 passing tests with zero failures 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
341 lines
10 KiB
Python
341 lines
10 KiB
Python
"""
|
|
Unit tests for Team model.
|
|
|
|
Tests data validation, field constraints, model behavior, and properties.
|
|
"""
|
|
|
|
import pytest
|
|
import datetime
|
|
from pydantic import ValidationError
|
|
from sqlmodel import Session, SQLModel, create_engine, text, select, func
|
|
|
|
from app.models.team import Team, TeamBase
|
|
from tests.factories.team_factory import TeamFactory
|
|
|
|
|
|
# Using centralized fixtures from conftest.py for proper test isolation
|
|
|
|
|
|
class TestTeamBase:
|
|
"""Test TeamBase model validation."""
|
|
|
|
def test_create_with_minimal_required_fields(self):
|
|
"""Test creating Team with minimal required fields."""
|
|
team = TeamBase(
|
|
id=12345,
|
|
abbrev="LAD",
|
|
sname="Dodgers",
|
|
lname="Los Angeles Dodgers",
|
|
gmid=67890,
|
|
gmname="Test GM",
|
|
gsheet="sheet-url",
|
|
wallet=25000,
|
|
team_value=100000,
|
|
collection_value=75000,
|
|
color="005a9c",
|
|
season=9,
|
|
career=1,
|
|
ranking=15,
|
|
has_guide=False,
|
|
is_ai=False
|
|
)
|
|
|
|
assert team.id == 12345
|
|
assert team.abbrev == "LAD"
|
|
assert team.sname == "Dodgers"
|
|
assert team.lname == "Los Angeles Dodgers"
|
|
assert team.gmid == 67890
|
|
assert team.gmname == "Test GM"
|
|
assert team.gsheet == "sheet-url"
|
|
assert team.wallet == 25000
|
|
assert team.team_value == 100000
|
|
assert team.collection_value == 75000
|
|
assert team.logo is None # Default value
|
|
assert team.color == "005a9c"
|
|
assert team.season == 9
|
|
assert team.career == 1
|
|
assert team.ranking == 15
|
|
assert team.has_guide is False
|
|
assert team.is_ai is False
|
|
assert isinstance(team.created, datetime.datetime)
|
|
|
|
def test_create_with_all_fields(self):
|
|
"""Test creating Team with all fields including optional ones."""
|
|
team = TeamBase(
|
|
id=12345,
|
|
abbrev="NYY",
|
|
sname="Yankees",
|
|
lname="New York Yankees",
|
|
gmid=67890,
|
|
gmname="Test GM",
|
|
gsheet="sheet-url",
|
|
wallet=50000,
|
|
team_value=150000,
|
|
collection_value=125000,
|
|
logo="https://example.com/logo.png",
|
|
color="c4ced4",
|
|
season=9,
|
|
career=3,
|
|
ranking=1,
|
|
has_guide=True,
|
|
is_ai=True
|
|
)
|
|
|
|
assert team.logo == "https://example.com/logo.png"
|
|
assert team.has_guide is True
|
|
assert team.is_ai is True
|
|
|
|
def test_description_property_human_team(self):
|
|
"""Test description property for human team."""
|
|
team = TeamBase(
|
|
id=100,
|
|
abbrev="SF",
|
|
lname="San Francisco Giants",
|
|
is_ai=False,
|
|
# ... other required fields
|
|
sname="Giants",
|
|
gmid=200,
|
|
gmname="Test GM",
|
|
gsheet="sheet-url",
|
|
wallet=25000,
|
|
team_value=100000,
|
|
collection_value=75000,
|
|
color="fd5a1e",
|
|
season=9,
|
|
career=1,
|
|
ranking=10,
|
|
has_guide=False
|
|
)
|
|
|
|
assert team.description == "100. SF San Francisco Giants, Human"
|
|
|
|
def test_description_property_ai_team(self):
|
|
"""Test description property for AI team."""
|
|
team = TeamBase(
|
|
id=200,
|
|
abbrev="AI",
|
|
lname="AI Team",
|
|
is_ai=True,
|
|
# ... other required fields
|
|
sname="AI",
|
|
gmid=300,
|
|
gmname="AI Manager",
|
|
gsheet="sheet-url",
|
|
wallet=25000,
|
|
team_value=100000,
|
|
collection_value=75000,
|
|
color="000000",
|
|
season=9,
|
|
career=1,
|
|
ranking=50,
|
|
has_guide=False
|
|
)
|
|
|
|
assert team.description == "200. AI AI Team, AI"
|
|
|
|
|
|
class TestTeamModel:
|
|
"""Test Team model database operations."""
|
|
|
|
def test_create_team_in_database(self, db_session):
|
|
"""Test creating and saving Team to database."""
|
|
team = TeamFactory.create(
|
|
db_session,
|
|
abbrev="BOS",
|
|
lname="Boston Red Sox",
|
|
wallet=40000
|
|
)
|
|
|
|
# Verify team was saved
|
|
assert team.id is not None
|
|
assert team.abbrev == "BOS"
|
|
assert team.lname == "Boston Red Sox"
|
|
assert team.wallet == 40000
|
|
|
|
# Verify we can retrieve it
|
|
retrieved = db_session.get(Team, team.id)
|
|
assert retrieved is not None
|
|
assert retrieved.abbrev == "BOS"
|
|
|
|
def test_team_uniqueness(self, db_session):
|
|
"""Test that team IDs must be unique."""
|
|
from tests.conftest import generate_unique_id
|
|
team_id = generate_unique_id()
|
|
|
|
# Create first team
|
|
team1 = TeamFactory.create(db_session, id=team_id, abbrev="T1")
|
|
assert team1.id == team_id
|
|
|
|
# Attempt to create second team with same ID should fail
|
|
with pytest.raises(Exception): # Database integrity error
|
|
team2 = TeamFactory.build(id=team_id, abbrev="T2")
|
|
db_session.add(team2)
|
|
db_session.commit()
|
|
|
|
def test_multiple_teams_different_ids(self, db_session):
|
|
"""Test creating multiple teams with different IDs."""
|
|
teams = TeamFactory.build_multiple(3)
|
|
|
|
for team in teams:
|
|
db_session.add(team)
|
|
db_session.commit()
|
|
|
|
# Verify all teams were saved
|
|
all_teams = db_session.exec(select(func.count(Team.id))).first()
|
|
assert all_teams >= 3
|
|
|
|
def test_ai_team_factory(self):
|
|
"""Test AI team factory creates correct AI team."""
|
|
ai_team = TeamFactory.build_ai_team(abbrev="AI1")
|
|
|
|
assert ai_team.is_ai is True
|
|
assert ai_team.abbrev == "AI1"
|
|
assert ai_team.lname == "AI Team"
|
|
assert ai_team.gmname == "AI Manager"
|
|
|
|
def test_human_team_factory(self):
|
|
"""Test human team factory creates correct human team."""
|
|
human_team = TeamFactory.build_human_team(abbrev="HUM1")
|
|
|
|
assert human_team.is_ai is False
|
|
assert human_team.abbrev == "HUM1"
|
|
assert human_team.lname == "Human Team"
|
|
assert human_team.gmname == "Human Manager"
|
|
assert human_team.wallet == 50000
|
|
|
|
def test_team_field_validation(self):
|
|
"""Test field validation and constraints."""
|
|
# Test that required fields are actually required
|
|
with pytest.raises(ValidationError):
|
|
TeamBase() # Missing required fields
|
|
|
|
# Test that fields accept expected types
|
|
team = TeamBase(
|
|
id=12345,
|
|
abbrev="TEST",
|
|
sname="Test",
|
|
lname="Test Team",
|
|
gmid=67890,
|
|
gmname="Test GM",
|
|
gsheet="sheet-url",
|
|
wallet=25000,
|
|
team_value=100000,
|
|
collection_value=75000,
|
|
color="ff0000",
|
|
season=9,
|
|
career=1,
|
|
ranking=15,
|
|
has_guide=False,
|
|
is_ai=False
|
|
)
|
|
|
|
# Verify types are preserved
|
|
assert isinstance(team.id, int)
|
|
assert isinstance(team.wallet, int)
|
|
assert isinstance(team.has_guide, bool)
|
|
assert isinstance(team.is_ai, bool)
|
|
|
|
def test_default_values(self):
|
|
"""Test that default values are applied correctly."""
|
|
team = TeamBase(
|
|
id=12345,
|
|
abbrev="TEST",
|
|
sname="Test",
|
|
lname="Test Team",
|
|
gmid=67890,
|
|
gmname="Test GM",
|
|
gsheet="sheet-url",
|
|
wallet=25000,
|
|
team_value=100000,
|
|
collection_value=75000,
|
|
color="ff0000",
|
|
season=9,
|
|
career=1,
|
|
ranking=15,
|
|
has_guide=False,
|
|
is_ai=False
|
|
)
|
|
|
|
# Test default values
|
|
assert team.logo is None
|
|
assert isinstance(team.created, datetime.datetime)
|
|
|
|
# Test that created timestamp is recent (within last minute)
|
|
now = datetime.datetime.now()
|
|
assert (now - team.created).total_seconds() < 60
|
|
|
|
def test_team_string_representations(self):
|
|
"""Test various string field scenarios."""
|
|
team = TeamFactory.build(
|
|
abbrev="LONG", # Test longer abbreviations
|
|
sname="S", # Test single character
|
|
lname="Very Long Team Name Here", # Test long names
|
|
gmname="Manager with Spaces",
|
|
color="ffffff" # Test hex color
|
|
)
|
|
|
|
assert len(team.abbrev) > 3
|
|
assert len(team.sname) == 1
|
|
assert " " in team.lname
|
|
assert " " in team.gmname
|
|
assert team.color == "ffffff"
|
|
|
|
|
|
class TestTeamFactoryEdgeCases:
|
|
"""Test edge cases and advanced scenarios with TeamFactory."""
|
|
|
|
def test_factory_override_all_defaults(self):
|
|
"""Test that all factory defaults can be overridden."""
|
|
custom_team = TeamFactory.build(
|
|
id=999,
|
|
abbrev="CUST",
|
|
sname="Custom",
|
|
lname="Custom Team",
|
|
gmid=888,
|
|
gmname="Custom GM",
|
|
gsheet="custom-sheet",
|
|
wallet=99999,
|
|
team_value=200000,
|
|
collection_value=150000,
|
|
logo="custom-logo.png",
|
|
color="abcdef",
|
|
season=10,
|
|
career=5,
|
|
ranking=1,
|
|
has_guide=True,
|
|
is_ai=True
|
|
)
|
|
|
|
assert custom_team.id == 999
|
|
assert custom_team.abbrev == "CUST"
|
|
assert custom_team.wallet == 99999
|
|
assert custom_team.season == 10
|
|
assert custom_team.career == 5
|
|
assert custom_team.is_ai is True
|
|
|
|
def test_multiple_teams_unique_ids(self):
|
|
"""Test that multiple teams have unique IDs."""
|
|
teams = TeamFactory.build_multiple(5)
|
|
|
|
ids = [team.id for team in teams]
|
|
assert len(set(ids)) == 5 # All IDs should be unique
|
|
|
|
gmids = [team.gmid for team in teams]
|
|
assert len(set(gmids)) == 5 # All GM IDs should be unique
|
|
|
|
def test_factory_build_vs_create(self, db_session):
|
|
"""Test difference between build (unsaved) and create (saved)."""
|
|
# Build doesn't save to database
|
|
built_team = TeamFactory.build(abbrev="BUILD")
|
|
|
|
# Should not exist in database yet
|
|
retrieved = db_session.get(Team, built_team.id)
|
|
assert retrieved is None
|
|
|
|
# Create saves to database
|
|
created_team = TeamFactory.create(db_session, abbrev="CREATE")
|
|
|
|
# Should exist in database
|
|
retrieved = db_session.get(Team, created_team.id)
|
|
assert retrieved is not None
|
|
assert retrieved.abbrev == "CREATE" |