Introduce unit testing on calculation objects
This commit is contained in:
@@ -0,0 +1,287 @@
|
||||
using Core.Entities;
|
||||
using Tests.Builders;
|
||||
|
||||
namespace Tests.Fixtures;
|
||||
|
||||
/// <summary>
|
||||
/// Pre-configured test data fixtures for different testing scenarios.
|
||||
/// </summary>
|
||||
public static class TestDataFixtures
|
||||
{
|
||||
/// <summary>
|
||||
/// Small dataset for simple unit tests (5 events, 6 students, minimal teams).
|
||||
/// </summary>
|
||||
public static class Small
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a small set of test data: 5 events, 6 students, and 3 teams.
|
||||
/// Suitable for simple unit tests that don't require realistic volume.
|
||||
/// </summary>
|
||||
public static (EventDefinition[] Events, Student[] Students, Team[] Teams) Full()
|
||||
{
|
||||
BuilderExtensions.ResetAllBuilders();
|
||||
|
||||
var events = new[]
|
||||
{
|
||||
EventDefinitionBuilder.Individual("Flight").Build(),
|
||||
EventDefinitionBuilder.Individual("Coding").Build(),
|
||||
EventDefinitionBuilder.Team("Biotechnology", 2, 6).WithInterview().Build(),
|
||||
EventDefinitionBuilder.Team("Robotics", 2, 5).AsOnSite().Build(),
|
||||
EventDefinitionBuilder.Individual("Essays on Technology").Build()
|
||||
};
|
||||
|
||||
var students = new[]
|
||||
{
|
||||
StudentBuilder.Default().WithName("Alice", "Anderson").WithGrade(9).Build(),
|
||||
StudentBuilder.Default().WithName("Bob", "Brown").WithGrade(10).Build(),
|
||||
StudentBuilder.Default().WithName("Carol", "Clark").WithGrade(11).Build(),
|
||||
StudentBuilder.Default().WithName("David", "Davis").WithGrade(9).Build(),
|
||||
StudentBuilder.Default().WithName("Eve", "Evans").WithGrade(10).Build(),
|
||||
StudentBuilder.Default().WithName("Frank", "Foster").WithGrade(11).Build()
|
||||
};
|
||||
|
||||
var teams = new[]
|
||||
{
|
||||
TeamBuilder.Default().ForEvent(events[2]) // Biotechnology
|
||||
.WithStudentsAndCaptain(students[0], students[1])
|
||||
.Build(),
|
||||
TeamBuilder.Default().ForEvent(events[3]) // Robotics
|
||||
.WithStudentsAndCaptain(students[2], students[3], students[4])
|
||||
.Build(),
|
||||
TeamBuilder.Default().ForEvent(events[0]) // Flight (individual)
|
||||
.WithStudent(students[5])
|
||||
.Build()
|
||||
};
|
||||
|
||||
return (events, students, teams);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns just events from the small fixture.
|
||||
/// </summary>
|
||||
public static EventDefinition[] Events()
|
||||
{
|
||||
BuilderExtensions.ResetAllBuilders();
|
||||
return Full().Events;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns just students from the small fixture.
|
||||
/// </summary>
|
||||
public static Student[] Students()
|
||||
{
|
||||
BuilderExtensions.ResetAllBuilders();
|
||||
return Full().Students;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Large dataset for algorithm tests requiring realistic volume (25 events, 18 students, 15+ teams).
|
||||
/// </summary>
|
||||
public static class Large
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a realistic large set of test data: 25 events, 18 students, and 15+ teams.
|
||||
/// Includes real TSA event names and realistic team configurations.
|
||||
/// Suitable for testing algorithms like EventAssignment and TeamScheduler.
|
||||
/// </summary>
|
||||
public static (EventDefinition[] Events, Student[] Students, Team[] Teams) Full()
|
||||
{
|
||||
BuilderExtensions.ResetAllBuilders();
|
||||
|
||||
// Real TSA events with realistic configurations
|
||||
var events = new[]
|
||||
{
|
||||
// Individual events (some are regional)
|
||||
EventDefinitionBuilder.Individual("Architectural Design").WithStateCount(3).AsRegionalEvent().Build(),
|
||||
EventDefinitionBuilder.Individual("Biotechnology Design").WithInterview().AsRegionalEvent().Build(),
|
||||
EventDefinitionBuilder.Individual("Coding").WithStateCount(3).Build(),
|
||||
EventDefinitionBuilder.Individual("Digital Photography").AsRegionalEvent().Build(),
|
||||
EventDefinitionBuilder.Individual("Essays on Technology").Build(),
|
||||
EventDefinitionBuilder.Individual("Extemporaneous Speech").AsOnSite().Build(),
|
||||
EventDefinitionBuilder.Individual("Flight").WithStateCount(3).AsRegionalEvent().Build(),
|
||||
EventDefinitionBuilder.Individual("Prepared Speech").AsOnSite().Build(),
|
||||
EventDefinitionBuilder.Individual("Scientific Visualization").Build(),
|
||||
EventDefinitionBuilder.Individual("System Control Technology").Build(),
|
||||
|
||||
// Team events (2-6 members, many are regional)
|
||||
EventDefinitionBuilder.Team("Animatronics", 2, 6).WithInterview().AsRegionalEvent().Build(),
|
||||
EventDefinitionBuilder.Team("Chapter Team", 6, 6).WithPresentation().Build(),
|
||||
EventDefinitionBuilder.Team("Cybersecurity", 2, 6).AsRegionalEvent().Build(),
|
||||
EventDefinitionBuilder.Team("Debate", 2, 2).AsOnSite().Build(),
|
||||
EventDefinitionBuilder.Team("Dragster", 1, 3).AsRegionalEvent().Build(),
|
||||
EventDefinitionBuilder.Team("Engineering Design", 3, 6).WithInterview().AsRegionalEvent().Build(),
|
||||
EventDefinitionBuilder.Team("Fashion Design", 2, 6).WithInterview().AsRegionalEvent().Build(),
|
||||
EventDefinitionBuilder.Team("Forensic Technology", 2, 6).Build(),
|
||||
EventDefinitionBuilder.Team("Future Technology Teacher", 2, 6).WithPresentation().AsRegionalEvent().Build(),
|
||||
EventDefinitionBuilder.Team("Junior Solar Sprint", 2, 3).AsRegionalEvent().Build(),
|
||||
EventDefinitionBuilder.Team("Music Production", 2, 6).WithInterview().AsRegionalEvent().Build(),
|
||||
EventDefinitionBuilder.Team("On Demand Video", 2, 6).Build(),
|
||||
EventDefinitionBuilder.Team("Promotional Marketing", 1, 6).WithPresentation().Build(),
|
||||
EventDefinitionBuilder.Team("Software Development", 2, 6).WithInterview().AsRegionalEvent().Build(),
|
||||
EventDefinitionBuilder.Team("Video Game Design", 2, 6).WithInterview().AsRegionalEvent().Build()
|
||||
};
|
||||
|
||||
// 18 students with varied grades and rankings
|
||||
var students = new[]
|
||||
{
|
||||
StudentBuilder.Default().WithName("Alice", "Anderson").WithGrade(9).WithTsaYear(1).Build(),
|
||||
StudentBuilder.Default().WithName("Bob", "Brown").WithGrade(10).WithTsaYear(2).Build(),
|
||||
StudentBuilder.Default().WithName("Carol", "Clark").WithGrade(11).WithTsaYear(3).Build(),
|
||||
StudentBuilder.Default().WithName("David", "Davis").WithGrade(9).WithTsaYear(1).Build(),
|
||||
StudentBuilder.Default().WithName("Eve", "Evans").WithGrade(10).WithTsaYear(2).Build(),
|
||||
StudentBuilder.Default().WithName("Frank", "Foster").WithGrade(11).WithTsaYear(3).Build(),
|
||||
StudentBuilder.Default().WithName("Grace", "Garcia").WithGrade(9).WithTsaYear(1).Build(),
|
||||
StudentBuilder.Default().WithName("Henry", "Harris").WithGrade(10).WithTsaYear(2).Build(),
|
||||
StudentBuilder.Default().WithName("Ivy", "Irwin").WithGrade(11).WithTsaYear(3).Build(),
|
||||
StudentBuilder.Default().WithName("Jack", "Johnson").WithGrade(9).WithTsaYear(1).Build(),
|
||||
StudentBuilder.Default().WithName("Kelly", "King").WithGrade(10).WithTsaYear(2).Build(),
|
||||
StudentBuilder.Default().WithName("Leo", "Lopez").WithGrade(11).WithTsaYear(3).Build(),
|
||||
StudentBuilder.Default().WithName("Maria", "Martinez").WithGrade(9).WithTsaYear(1).Build(),
|
||||
StudentBuilder.Default().WithName("Noah", "Nelson").WithGrade(10).WithTsaYear(2).Build(),
|
||||
StudentBuilder.Default().WithName("Olivia", "O'Brien").WithGrade(11).WithTsaYear(3).Build(),
|
||||
StudentBuilder.Default().WithName("Paul", "Patel").WithGrade(9).WithTsaYear(1).Build(),
|
||||
StudentBuilder.Default().WithName("Quinn", "Quinn").WithGrade(10).WithTsaYear(2).Build(),
|
||||
StudentBuilder.Default().WithName("Rachel", "Robinson").WithGrade(11).WithTsaYear(3).Build()
|
||||
};
|
||||
|
||||
// Add event rankings for students (realistic preferences)
|
||||
AddRankingsToStudent(students[0], events, new[] { 0, 2, 6, 10, 12 }); // Individual + teams
|
||||
AddRankingsToStudent(students[1], events, new[] { 1, 3, 11, 13, 16 });
|
||||
AddRankingsToStudent(students[2], events, new[] { 4, 5, 14, 17, 20 });
|
||||
AddRankingsToStudent(students[3], events, new[] { 6, 7, 15, 18, 21 });
|
||||
AddRankingsToStudent(students[4], events, new[] { 8, 9, 16, 19, 22 });
|
||||
AddRankingsToStudent(students[5], events, new[] { 0, 2, 12, 20, 23 });
|
||||
AddRankingsToStudent(students[6], events, new[] { 1, 3, 10, 13, 24 });
|
||||
AddRankingsToStudent(students[7], events, new[] { 4, 5, 11, 14, 15 });
|
||||
AddRankingsToStudent(students[8], events, new[] { 6, 7, 16, 17, 18 });
|
||||
AddRankingsToStudent(students[9], events, new[] { 8, 9, 19, 21, 22 });
|
||||
AddRankingsToStudent(students[10], events, new[] { 0, 10, 12, 14, 23 });
|
||||
AddRankingsToStudent(students[11], events, new[] { 1, 11, 13, 15, 24 });
|
||||
AddRankingsToStudent(students[12], events, new[] { 2, 12, 16, 18, 20 });
|
||||
AddRankingsToStudent(students[13], events, new[] { 3, 13, 17, 19, 21 });
|
||||
AddRankingsToStudent(students[14], events, new[] { 4, 14, 18, 20, 22 });
|
||||
AddRankingsToStudent(students[15], events, new[] { 5, 15, 19, 21, 23 });
|
||||
AddRankingsToStudent(students[16], events, new[] { 6, 16, 20, 22, 24 });
|
||||
AddRankingsToStudent(students[17], events, new[] { 7, 10, 11, 12, 13 });
|
||||
|
||||
// Create representative teams (some will be created by algorithm tests)
|
||||
var teams = new[]
|
||||
{
|
||||
TeamBuilder.Default().ForEvent(events[10]) // Animatronics
|
||||
.WithStudentsAndCaptain(students[0], students[1], students[2])
|
||||
.WithIdentifier("Team A")
|
||||
.Build(),
|
||||
TeamBuilder.Default().ForEvent(events[11]) // Chapter Team
|
||||
.WithStudentsAndCaptain(students[3], students[4], students[5], students[6], students[7], students[8])
|
||||
.WithIdentifier("Chapter")
|
||||
.Build(),
|
||||
TeamBuilder.Default().ForEvent(events[12]) // Cybersecurity
|
||||
.WithStudentsAndCaptain(students[9], students[10])
|
||||
.WithIdentifier("Team C")
|
||||
.Build(),
|
||||
TeamBuilder.Default().ForEvent(events[13]) // Debate
|
||||
.WithStudentsAndCaptain(students[11], students[12])
|
||||
.WithIdentifier("Team D")
|
||||
.Build(),
|
||||
TeamBuilder.Default().ForEvent(events[16]) // Fashion Design
|
||||
.WithStudentsAndCaptain(students[13], students[14], students[15])
|
||||
.WithIdentifier("Team F")
|
||||
.Build(),
|
||||
TeamBuilder.Default().ForEvent(events[24]) // Video Game Design
|
||||
.WithStudentsAndCaptain(students[16], students[17])
|
||||
.WithIdentifier("Team V")
|
||||
.Build()
|
||||
};
|
||||
|
||||
return (events, students, teams);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper to add event rankings to a student.
|
||||
/// </summary>
|
||||
private static void AddRankingsToStudent(Student student, EventDefinition[] events, int[] eventIndices)
|
||||
{
|
||||
for (int i = 0; i < eventIndices.Length; i++)
|
||||
{
|
||||
var eventIndex = eventIndices[i];
|
||||
if (eventIndex >= 0 && eventIndex < events.Length)
|
||||
{
|
||||
StudentEventRankingBuilder.Default()
|
||||
.ForStudent(student)
|
||||
.ForEvent(events[eventIndex])
|
||||
.WithRank(i + 1)
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns just events from the large fixture.
|
||||
/// </summary>
|
||||
public static EventDefinition[] Events()
|
||||
{
|
||||
BuilderExtensions.ResetAllBuilders();
|
||||
return Full().Events;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns just students from the large fixture.
|
||||
/// </summary>
|
||||
public static Student[] Students()
|
||||
{
|
||||
BuilderExtensions.ResetAllBuilders();
|
||||
return Full().Students;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Custom helpers for creating specific numbers of minimal test entities.
|
||||
/// </summary>
|
||||
public static class Custom
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates N simple individual events with generic names.
|
||||
/// </summary>
|
||||
public static EventDefinition[] MinimalEvents(int count)
|
||||
{
|
||||
BuilderExtensions.ResetAllBuilders();
|
||||
var events = new EventDefinition[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
events[i] = EventDefinitionBuilder.Individual($"Event{i + 1}").Build();
|
||||
}
|
||||
return events;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates N simple students with sequential names.
|
||||
/// </summary>
|
||||
public static Student[] MinimalStudents(int count)
|
||||
{
|
||||
BuilderExtensions.ResetAllBuilders();
|
||||
return BuilderExtensions.CreateStudents(count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates N simple teams for a given event.
|
||||
/// </summary>
|
||||
public static Team[] MinimalTeams(EventDefinition eventDef, int teamCount, int studentsPerTeam)
|
||||
{
|
||||
var allStudents = MinimalStudents(teamCount * studentsPerTeam);
|
||||
var teams = new Team[teamCount];
|
||||
|
||||
for (int i = 0; i < teamCount; i++)
|
||||
{
|
||||
var teamStudents = allStudents.Skip(i * studentsPerTeam).Take(studentsPerTeam).ToArray();
|
||||
teams[i] = TeamBuilder.Default().ForEvent(eventDef)
|
||||
.WithStudents(teamStudents)
|
||||
.WithCaptain(teamStudents[0])
|
||||
.WithIdentifier($"Team{i + 1}")
|
||||
.Build();
|
||||
}
|
||||
|
||||
return teams;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user