Reescrita dos geradores: biblioteca IGenerator, minimal API e novo frontend
- GeradoresService: cada tipo passa a ser um IGenerator (NIF, NIPC, NISS, CC, passaporte, IBAN, NIB, cartões, referência MB, pessoa, telefone, código postal, email, matrícula, EAN, UUID) registado em GeneratorRegistry; remove DAL/EF - GeradoresWS: minimal APIs em /api/v1 com OpenAPI + Scalar e health check - UnitTest: testes de ida e volta, valores conhecidos, detecção e API - geradoresfe: UI construída a partir dos metadados da API, validador livre, exportação CSV/JSON/TXT, nginx com API_UPSTREAM configurável - Docker, docker-compose e Jenkinsfile actualizados Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
107
UnitTest/GeneratorRoundTripTests.cs
Normal file
107
UnitTest/GeneratorRoundTripTests.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using GeradoresService;
|
||||
using GeradoresService.Core;
|
||||
|
||||
namespace UnitTest;
|
||||
|
||||
/// <summary>
|
||||
/// Para cada gerador e cada valor de cada opção, os valores gerados têm de passar no próprio validador.
|
||||
/// </summary>
|
||||
public class GeneratorRoundTripTests
|
||||
{
|
||||
private static readonly GeneratorRegistry Registry = new();
|
||||
|
||||
public static TheoryData<string, string, string> AllOptionValues()
|
||||
{
|
||||
var data = new TheoryData<string, string, string>();
|
||||
foreach (var g in Registry.All)
|
||||
{
|
||||
if (g.Options.Count == 0)
|
||||
data.Add(g.Id, "", "");
|
||||
foreach (var o in g.Options)
|
||||
foreach (var c in o.Choices)
|
||||
data.Add(g.Id, o.Key, c.Value);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(AllOptionValues))]
|
||||
public void Generated_values_are_valid(string generatorId, string optionKey, string optionValue)
|
||||
{
|
||||
var generator = Registry.Find(generatorId)!;
|
||||
var options = new Dictionary<string, string?>();
|
||||
if (optionKey != "")
|
||||
options[optionKey] = optionValue;
|
||||
|
||||
var items = Registry.Generate(generator, 300, options, seed: 42);
|
||||
|
||||
Assert.All(items, item => Assert.False(string.IsNullOrWhiteSpace(item.Value)));
|
||||
if (!generator.CanValidate)
|
||||
return;
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
var result = generator.Validate(item.Value);
|
||||
Assert.True(result.IsValid, $"{generatorId} gerou '{item.Value}' que não valida: {result.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Pessoa_fields_are_all_valid()
|
||||
{
|
||||
var pessoa = Registry.Find("pessoa")!;
|
||||
foreach (var item in Registry.Generate(pessoa, 200, new Dictionary<string, string?>(), seed: 7))
|
||||
{
|
||||
var f = item.Fields!;
|
||||
Assert.True(Registry.Find("nif")!.Validate(f["NIF"]).IsValid);
|
||||
Assert.True(Registry.Find("niss")!.Validate(f["NISS"]).IsValid);
|
||||
Assert.True(Registry.Find("cc")!.Validate(f["Cartão de Cidadão"]).IsValid);
|
||||
Assert.True(Registry.Find("iban")!.Validate(f["IBAN"]).IsValid);
|
||||
Assert.True(Registry.Find("telefone")!.Validate(f["Telemóvel"]).IsValid);
|
||||
Assert.True(Registry.Find("email")!.Validate(f["Email"]).IsValid);
|
||||
Assert.True(Registry.Find("codigo-postal")!.Validate(f["Código postal"]).IsValid);
|
||||
|
||||
var age = DateTime.UtcNow.Year - DateOnly.Parse(f["Data de nascimento"]).Year;
|
||||
Assert.InRange(age, 18, 81);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Same_seed_gives_same_values()
|
||||
{
|
||||
var nif = Registry.Find("nif")!;
|
||||
var a = Registry.Generate(nif, 20, new Dictionary<string, string?>(), seed: 123);
|
||||
var b = Registry.Generate(nif, 20, new Dictionary<string, string?>(), seed: 123);
|
||||
Assert.Equal(a.Select(x => x.Value), b.Select(x => x.Value));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Generated_values_are_not_all_equal()
|
||||
{
|
||||
var items = Registry.Generate(Registry.Find("nif")!, 50, new Dictionary<string, string?>());
|
||||
Assert.True(items.Select(i => i.Value).Distinct().Count() > 40);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Invalid_option_value_throws()
|
||||
{
|
||||
var nif = Registry.Find("nif")!;
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
Registry.Generate(nif, 1, new Dictionary<string, string?> { ["tipo"] = "4" }));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0)]
|
||||
[InlineData(GeneratorRegistry.MaxBatch + 1)]
|
||||
public void Count_out_of_range_throws(int count)
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||
Registry.Generate(Registry.Find("nif")!, count, new Dictionary<string, string?>()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Ids_are_unique()
|
||||
{
|
||||
Assert.Equal(Registry.All.Count, Registry.All.Select(g => g.Id).Distinct().Count());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user