Files
LehrerApp/LehrerApp.Tests/ExamScoringServiceTests.cs
T
adminandClaude Sonnet 5.5 c0f8b98202
CI / build-and-test (push) Canceled after 0s
Nachschreibarbeiten und Arbeitsarten (Test, kontrollierte Hausaufgabe)
Nachschreibarbeiten nutzen die Wiederholungs-Verknüpfung, ersetzen aber nur
fehlende Noten; mehrere Folgearbeiten je erster Arbeit sind möglich.
Exam.Kind trennt Klausuren (schriftlich) von Tests u. Ä. (Sonstige).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 22:54:31 +02:00

142 lines
5.5 KiB
C#

using LehrerApp.Core.Models;
using LehrerApp.Core.Services;
using Xunit;
namespace LehrerApp.Tests;
public class ExamScoringServiceTests
{
[Fact]
public void BonusUndFassungen_VerwendenJeweilsDenRichtigenGrundwert()
{
var tasks = new List<ExamTask>
{
new() { MaxPoints = 10 },
new() { MaxPoints = 5, Variant = ExamVariant.A },
new() { MaxPoints = 8, Variant = ExamVariant.B },
new() { MaxPoints = 2, IsBonus = true },
};
Assert.Equal(15, ExamScoringService.Maximum(tasks, ExamVariant.A));
Assert.Equal(18, ExamScoringService.Maximum(tasks, ExamVariant.B));
Assert.Equal(17, ExamScoringService.Achieved(tasks, [10, 5, 8, 2], ExamVariant.A));
Assert.Equal(20, ExamScoringService.Achieved(tasks, [10, 5, 8, 2], ExamVariant.B));
}
[Fact]
public void TaskLabels_ZählenBonusaufgabenNichtMit()
{
var tasks = new List<ExamTask>
{
new() { Nr = 1 },
new() { Nr = 2, IsBonus = true },
new() { Nr = 3, Title = "Titration" },
new() { Nr = 4, IsBonus = true, Title = "Knobelei" },
};
Assert.Equal(["1", "Bonus 1", "2", "Bonus 2"],
ExamScoringService.TaskNumbers(tasks.Select(t => t.IsBonus)));
Assert.Equal(["Aufgabe 1", "Bonus 1", "2. Titration", "Bonus 2: Knobelei"],
ExamScoringService.TaskLabels(tasks));
}
[Fact]
public void TaskNumbers_EinzelneBonusaufgabeHeisstNurBonus() =>
Assert.Equal(["1", "Bonus", "2"], ExamScoringService.TaskNumbers([false, true, false]));
[Theory]
[InlineData(RepeatGradeRule.Better, GradingSystem.Grades1To6, "2", "4", "2")]
[InlineData(RepeatGradeRule.Better, GradingSystem.Points0To15, "8", "11", "11")]
[InlineData(RepeatGradeRule.Repeat, GradingSystem.Grades1To6, "2", "4", "4")]
[InlineData(RepeatGradeRule.Original, GradingSystem.Grades1To6, "2", "4", "2")]
public void Wiederholung_ZaehltGenauEinmalNachRegel(RepeatGradeRule rule,
GradingSystem system, string first, string second, string expected)
{
var original = new Exam();
var repeat = new Exam { RepeatOfExamId = original.Id, RepeatGradeRule = rule };
var other = new Exam();
var grades = ExamScoringService.EffectiveGrades(
[(original, first), (repeat, second), (other, "3")], system);
Assert.Equal(2, grades.Count);
Assert.Contains(expected, grades);
Assert.Contains("3", grades);
}
[Fact]
public void Wiederholung_BessereNoteBeruecksichtigtTendenzUndFehlendesErgebnis()
{
var original = new Exam();
var repeat = new Exam { RepeatOfExamId = original.Id };
Assert.Equal(["2+"], ExamScoringService.EffectiveGrades(
[(original, "2"), (repeat, "2+")], GradingSystem.Grades1To6));
Assert.Equal(["2"], ExamScoringService.EffectiveGrades(
[(original, "2")], GradingSystem.Grades1To6));
}
[Fact]
public void Nachschreibarbeit_ErsetztFehlendeNote()
{
var original = new Exam();
var makeUp = new Exam { RepeatOfExamId = original.Id, IsMakeUp = true };
// Schüler war bei der ersten Arbeit abwesend: nur die Nachschreibarbeit liegt vor.
Assert.Equal(["4"], ExamScoringService.EffectiveGrades([(makeUp, "4")], GradingSystem.Grades1To6));
}
[Fact]
public void Nachschreibarbeit_VerdraengtErsteNoteNie()
{
var original = new Exam();
var makeUp = new Exam { RepeatOfExamId = original.Id, IsMakeUp = true };
// Hat der Schüler beide geschrieben, zählt die erste — auch wenn die zweite besser ist.
Assert.Equal(["4"], ExamScoringService.EffectiveGrades(
[(original, "4"), (makeUp, "1")], GradingSystem.Grades1To6));
}
[Fact]
public void MehrereFolgearbeiten_ZaehlenGenauEinmal()
{
var original = new Exam { Date = new DateOnly(2026, 9, 1) };
var makeUp = new Exam { RepeatOfExamId = original.Id, IsMakeUp = true, Date = new DateOnly(2026, 9, 15) };
var repeat = new Exam { RepeatOfExamId = original.Id, Date = new DateOnly(2026, 10, 1) };
// Original versäumt, Nachschreiben mit 4, Wiederholung mit 3 (Regel "Bessere") → eine Note.
Assert.Equal(["3"], ExamScoringService.EffectiveGrades(
[(makeUp, "4"), (repeat, "3")], GradingSystem.Grades1To6));
// Alle drei geschrieben: Original 3, Nachschreiben ignoriert, Wiederholung 2 → 2.
Assert.Equal(["2"], ExamScoringService.EffectiveGrades(
[(original, "3"), (makeUp, "1"), (repeat, "2")], GradingSystem.Grades1To6));
}
[Fact]
public void EffectiveGradesByKind_TrenntKlausurenVonTests()
{
var klausur = new Exam();
var test = new Exam { Kind = ExamKind.Test };
var testMakeUp = new Exam { Kind = ExamKind.Test, RepeatOfExamId = test.Id, IsMakeUp = true };
var (written, other) = ExamScoringService.EffectiveGradesByKind(
[(klausur, "2"), (test, "3"), (testMakeUp, "5")], GradingSystem.Grades1To6);
Assert.Equal(["2"], written);
Assert.Equal(["3"], other);
}
[Fact]
public void ExamWeekLoad_ZaehltTestsNichtAlsKlausur()
{
var monday = new DateOnly(2026, 9, 7);
var exams = new[]
{
new Exam { Date = monday },
new Exam { Date = monday.AddDays(1), Kind = ExamKind.Test },
};
Assert.Equal(1, ExamWeekLoadService.CountInSameWeek(exams, monday.AddDays(2)));
}
}