Add variable question distractor pools
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
using QuestionsApi.Models;
|
||||
using QuestionsApi.Services;
|
||||
using Xunit;
|
||||
|
||||
namespace QuestionsApi.Tests;
|
||||
|
||||
public sealed class ChoicePoolTests
|
||||
{
|
||||
[Fact]
|
||||
public void LegacyResponseContainsFiveChoicesAndAlwaysIncludesCorrectAnswer()
|
||||
{
|
||||
var question = BuildQuestion(9);
|
||||
|
||||
for (var iteration = 0; iteration < 50; iteration++)
|
||||
{
|
||||
var response = QuestionResponse.FromModel(question, includeChoicePool: false);
|
||||
Assert.Equal(5, response.Choices.Count);
|
||||
Assert.Equal(5, response.Choices.Select(choice => choice.Id).Distinct().Count());
|
||||
Assert.Contains(response.Choices, choice => choice.Id == question.CorrectChoiceId);
|
||||
Assert.All(response.ChoiceExplanations.Keys, id => Assert.Contains(response.Choices, choice => choice.Id == id));
|
||||
Assert.All(response.WrongAnswerFollowups.Keys, id => Assert.Contains(response.Choices, choice => choice.Id == id));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PoolCapableResponseContainsCompletePool()
|
||||
{
|
||||
var question = BuildQuestion(9);
|
||||
var response = QuestionResponse.FromModel(question, includeChoicePool: true);
|
||||
Assert.Equal(9, response.Choices.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PublishedQuestionRequiresCompletePerChoiceTeachingContent()
|
||||
{
|
||||
var request = BuildRequest(6);
|
||||
Assert.Null(QuestionValidator.Validate(request));
|
||||
|
||||
request.WrongAnswerFollowups.Remove("F");
|
||||
Assert.Contains("every incorrect choice", QuestionValidator.Validate(request));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PublishedQuestionRequiresAtLeastFiveUniqueChoices()
|
||||
{
|
||||
var request = BuildRequest(4);
|
||||
Assert.Contains("at least five", QuestionValidator.Validate(request));
|
||||
|
||||
request = BuildRequest(5);
|
||||
request.Choices[4].Id = "A";
|
||||
Assert.Contains("unique", QuestionValidator.Validate(request));
|
||||
}
|
||||
|
||||
private static Question BuildQuestion(int count)
|
||||
{
|
||||
var request = BuildRequest(count);
|
||||
return new Question
|
||||
{
|
||||
ExternalId = request.ExternalId,
|
||||
Stem = request.Stem,
|
||||
LeadIn = request.LeadIn,
|
||||
Choices = request.Choices,
|
||||
CorrectChoiceId = request.CorrectChoiceId,
|
||||
Explanation = request.Explanation,
|
||||
ChoiceExplanations = request.ChoiceExplanations,
|
||||
WrongAnswerFollowups = request.WrongAnswerFollowups,
|
||||
ChoiceSelectionPercentages = request.ChoiceSelectionPercentages
|
||||
};
|
||||
}
|
||||
|
||||
private static UpsertQuestionRequest BuildRequest(int count)
|
||||
{
|
||||
var ids = Enumerable.Range(0, count).Select(index => ((char)('A' + index)).ToString()).ToList();
|
||||
var choices = ids.Select(id => new QuestionChoice { Id = id, Text = $"Choice {id}" }).ToList();
|
||||
return new UpsertQuestionRequest
|
||||
{
|
||||
ExternalId = "choice-pool-test",
|
||||
Stem = "A complete clinical vignette.",
|
||||
LeadIn = "Which option is most appropriate?",
|
||||
Choices = choices,
|
||||
CorrectChoiceId = "A",
|
||||
Explanation = "Explanation",
|
||||
ChoiceExplanations = ids.ToDictionary(id => id, id => id == "A" ? "Correct." : "Incorrect."),
|
||||
WrongAnswerFollowups = ids.Where(id => id != "A").ToDictionary(
|
||||
id => id,
|
||||
id => new WrongAnswerFollowup
|
||||
{
|
||||
Prompt = "Which finding makes this less appropriate?",
|
||||
Choices =
|
||||
[
|
||||
new QuestionChoice { Id = "A", Text = "Finding one" },
|
||||
new QuestionChoice { Id = "B", Text = "Finding two" }
|
||||
],
|
||||
CorrectChoiceId = "A",
|
||||
TeachingPoint = "Teaching point"
|
||||
}),
|
||||
ChoiceSelectionPercentages = ids.ToDictionary(id => id, _ => 0),
|
||||
Discipline = "Medicine",
|
||||
System = "Cardiovascular System",
|
||||
Difficulty = 2,
|
||||
IsPublished = true
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
<ProjectReference Include="..\QuestionsApi\QuestionsApi.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user