Files
Omika/tests/Omika.Tests/Mobile/VocabulaireModeleTests.cs
2026-10-23 18:46:50 +02:00

118 lines
3.7 KiB
C#

using Omika.App.Local.Models;
namespace Omika.Tests.Mobile;
/// <summary>
/// Tests du vocabulaire du modèle (<c>vocab.json</c>) : conversion pièce ↔
/// identifiant et traduction des identifiants du <c>.spm</c> vers ceux du modèle.
///
/// <para>
/// Les identifiants utilisés sont <b>réels</b>, mesurés sur
/// <c>opus-mt-es-fr</c> : dans son vocabulaire, <c>▁Ho</c> vaut 584 et <c>,</c>
/// vaut 3, alors que le fichier <c>.spm</c> du même modèle les numérote 5293 et
/// 4. C'est cette divergence qui rend ce fichier indispensable.
/// </para>
/// </summary>
public class VocabulaireModeleTests
{
private const string Json = """
{
"</s>": 0,
"<unk>": 1,
"▁de": 2,
",": 3,
".": 4,
"▁la": 5,
"▁Ho": 584,
">>fra<<": 14666,
"<pad>": 74821
}
""";
/// <summary>Pièces telles que le <c>.spm</c> les numérote (5293, 4, 5…).</summary>
private static string? PieceSpm(int id) => id switch
{
5293 => "▁Ho",
4 => ",",
5 => "▁la",
_ => null
};
[Fact]
public void DepuisJson_LitLesIdentifiants()
{
VocabulaireModele? vocabulaire = VocabulaireModele.DepuisJson(Json);
Assert.NotNull(vocabulaire);
Assert.Equal(9, vocabulaire.Taille);
Assert.Equal(584, vocabulaire.IdDePiece("▁Ho"));
Assert.Equal(14666, vocabulaire.IdDePiece(">>fra<<"));
Assert.Equal(0, vocabulaire.IdFin);
Assert.Equal(1, vocabulaire.IdInconnu);
}
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData(" ")]
[InlineData("{}")]
[InlineData("null")]
public void DepuisJson_ContenuVideOuNul_EstTraiteCommeAbsent(string? json)
{
Assert.Null(VocabulaireModele.DepuisJson(json));
}
[Fact]
public void DepuisJson_JsonInvalide_EstRefuse()
{
Assert.Throws<FormatException>(() => VocabulaireModele.DepuisJson("{ pas du json"));
}
[Fact]
public void PieceDeId_EstLInverseDeIdDePiece()
{
VocabulaireModele vocabulaire = VocabulaireModele.DepuisJson(Json)!;
Assert.Equal("▁Ho", vocabulaire.PieceDeId(584));
Assert.Equal(">>fra<<", vocabulaire.PieceDeId(14666));
Assert.Null(vocabulaire.PieceDeId(999));
}
[Fact]
public void MapperIdentifiants_RemplaceLaNumerotationSpmParCelleDuModele()
{
VocabulaireModele vocabulaire = VocabulaireModele.DepuisJson(Json)!;
// La segmentation donne les identifiants du .spm (5293, 4, 5) : le modèle,
// lui, attend 584, 3 et 5. Mapper l'identifiant par lui-même donnerait du
// charabia, d'où le passage par la pièce.
IReadOnlyList<int> mappes = vocabulaire.MapperIdentifiants([5293, 4, 5], PieceSpm);
Assert.Equal([584, 3, 5], mappes);
}
[Fact]
public void MapperIdentifiants_PieceInconnue_DevientLeJetonInconnu()
{
VocabulaireModele vocabulaire = VocabulaireModele.DepuisJson(Json)!;
// « ▁inconnu » n'est pas dans le vocabulaire : la position est conservée
// avec le jeton inconnu, plutôt que de décaler la suite de la phrase.
IReadOnlyList<int> mappes = vocabulaire.MapperIdentifiants(
[5, 999], id => id == 5 ? "▁la" : "▁inconnu");
Assert.Equal([5, 1], mappes);
}
[Fact]
public void PiecesDeIds_OmetLesIdentifiantsHorsVocabulaire()
{
VocabulaireModele vocabulaire = VocabulaireModele.DepuisJson(Json)!;
// 74820 est une ligne de remplissage : aucune pièce, donc aucun texte.
IReadOnlyList<string> pieces = vocabulaire.PiecesDeIds([584, 74820, 3]);
Assert.Equal(["▁Ho", ","], pieces);
}
}