Qualité et livraison : tests, sécurité, performance et CI dans Mes Recettes

Piliers Qualité & Livraison : Tests · Sécurité · Performance · CI/CD

Qualité et livraison : tests, sécurité, performance et CI dans Mes Recettes

Partie 3 sur 3 de la série Mes Recettes : Partie 1 – Aperçu · Partie 2 – Architecture | English

Philosophie de test

Focus actuel : exactitude des modèles & règles de validation. Portée réduite = moins de fragilité tout en protégeant les invariants.

CoucheStatutNotes
Validation modèleImplémentéeBornes de note, champs requis
RelationsImplémentéesIntégrité Livre–Auteur–Recette
Tests flux authÀ faireMock auth Supabase
Tests d’intégrationPrévuSchéma Supabase de staging
Tests composants UIDifféréQuand la logique interactive augmentera

Exemple validation de note

[Theory]
[InlineData(1,true)]
[InlineData(5,true)]
[InlineData(0,false)]
[InlineData(6,false)]
public void Rating_Range_Validation(int value, bool expected)
{
    var recipe = new Recipe { Name = "Test", Rating = value };
    var ctx = new ValidationContext(recipe);
    var results = new List<ValidationResult>();
    var valid = Validator.TryValidateObject(recipe, ctx, results, true);
    Assert.Equal(expected, valid);
}

Posture de sécurité (actif + prévu)

SujetApproche
AuthSupabase GoTrue (email/mot de passe)
TransportHTTPS via hébergeur/CDN
RLSPatterns de politiques rédigés
Validation entréeEncodage + DataAnnotations
Gestion secretsClés via configuration (env vars en CI plus tard)
Moindre privilègePolitiques BD limiteront la visibilité

Exemple conceptuel RLS :

ALTER TABLE recettes ENABLE ROW LEVEL SECURITY;

CREATE POLICY select_own ON recettes
  FOR SELECT USING (auth.uid() = user_id);

(Suppose une colonne user_id — migration à ajouter.)

Stratégie performance

DomaineMesure
Taille bundleTree-shaking, chargement différé futur
Sur‑fetchPagination + .Range()
Appels dupliquésDécorateur cache mémoire
Latence perçueUI optimiste, squelettes
RechercheIndex GIN + vecteur full‑text

Index planifié :

CREATE INDEX idx_recipes_search ON recettes USING gin(
  to_tsvector('english', name || ' ' || coalesce(notes,''))
);

Pattern de cache (prévu)

public class CachedRecipeService : IRecipeService
{
    private readonly IRecipeService _inner;
    private readonly IMemoryCache _cache;
    public async Task<List<Recipe>> GetRecipesAsync() =>
        await _cache.GetOrCreateAsync("recipes_all", _ => _inner.GetRecipesAsync());
}

Activé après justification métrique.

Schéma CI/CD

Étapes pipeline :

  1. Restore
  2. Build
  3. Test
  4. (Futur) Lint & scan sécurité
  5. Publish static
  6. Déploiement CDN

Extrait workflow :

- name: Test
  run: dotnet test --no-build --verbosity normal

Extensions possibles : couverture, SAST, audit dépendances, diff schéma BD.

Feuille de route observabilité

CoucheCourt termeLong terme
LogsConsole + devtoolsLogs structurés externes
MetricsTimings manuelsExport OpenTelemetry
ErreursError boundary BlazorPipeline centralisé
Perf frontLighthouse localSeuils automatisés CI

Cibles de déploiement

Initial : GitHub Pages / Azure Static Web Apps.
Futur : Serveur minimal si SSR ou endpoints protégés requis.

Risques condensés

RisqueMitigation
Dérive schéma vs docsNotes migrations /docs
Couplage fournisseurAbstraction progressive
Logique UI non testéeAjouter tests composants
Cas limites refresh tokenSurveiller logs, gérer explicitement

Prochaines actions qualité

  1. Ajouter RLS + colonne user_id
  2. Intégration test Supabase jetable
  3. Badge couverture
  4. Error boundary + logging dialogues

Source : https://github.com/mongeon/RecettesIndex



Suggestions de lecture :