Angular Testing Masterclass

Présentation

Il s’agit de la prise de notes réalisées pendant le suivi de la formation Angular Testing Masterclass

Section 1 : Course Kickoff - Development Environment Setup

  • Visual Studio Settings : rien à voir mais bon … c’est galère quand c’est mal configuré. Donc pour que tous les fichiers passent en tab = espace et qu’un tab = 4 espaces (parce que c’est que J’AIME)
    "editor.tabSize": 4,
    "editor.insertSpaces": true,
    "editor.detectIndentation": false,
    "[javascript]": {
        "editor.tabSize": 4
    },
    "[typescript]": {
        "editor.tabSize": 4
    }
  • Mise en place d’un espion :
spyOn(logger, 'log');
// [...]
expect(logger.log).toHaveBeenCalledTimes(1);
  • Autre version (plus proche du Mock) : const logger = jasmine.createSpyObj('LoggerService', ['log']);,
  • Parce que mon éditeur le trouve pas : import { TestBed } from '@angular/core/testing';.
  • Une phrase que j’aime bien : “Il ne faut pas utiliser des implémentations réelles de dépendances mais des mocks, sinon c’est pas un test unitaire mais un test fonctionnel”,
  • RAPPEL : Chaque test doit être indépendant et ne pas dépendre d’un ordre d’exécution,
  • Pour désactiver :
    • Une suite de tests : describe -> __x__describe,
    • Un test en particulier : it -> -> __x__it,
    • Bref faut mettre une X,
  • Pour être focus sur un test :
    • Pareil mais avec un f,

Section 2 - Angular Service Testing In Depth

req.flush({
            ...COURSES[12],
            ...changes
        });
  • Un point avec lequel je suis pas super à l’aise et que par moment, le test porte finalement sur les données de test plus que le service lui même,

Section 3 : Angular Component Testing In Depth

Presentation Component

  • Plutôt que de charger composants par composants : import du module qui va tout charger …
  • Pour gérer une fonction asynchrone dans une fonction comme beforeEach : async() qui attend une fonction en paramètre,
  • Point d’entrée pour naviguer dans le DOM : DebugElement (import { DebugElement } from '@angular/core';) accessible via fixture.debugElement

La formation utilise compileComponents dans la cas de l’initialisation du test. La documentation dans le cas basic n’en fait pas mention. En fait, d’après le (doc)[https://angular.io/guide/testing#calling-compilecomponents] ce n’est que si les tests sont exécutés en dehors de ng test.

Le composant récupérer par la méthode classique ne donne accès qu’aux propriétés publiques du composants. Pour accéder aux éléments tel que le DOM, agir sur l’interne, il faut passer par le “Debug Element”:

fixture = TestBed.createComponent([ComponenentATester]);
component = fixture.componentInstance;
el = fixture.debugElement;

Smart or Container Component

  • Par rapport à un composant de présentation, il récupère “lui-même” ses données via un service alors que le précédente reçoit les données en paramètre,
  • Gestion des animations dans les tests : (NoopAnimationsModule)[https://angular.io/api/platform-browser/animations/NoopAnimationsModule] permet d’annuler les animations sans tout casser,
  • Sur la gestion des tabs, validation que le tab affiché est le bon :
    const title = tabs[0].query(By.css('.mat-tab-label-content'));
    expect(title.nativeElement.textContent).toBe('Advanced');

Section 4 : Section 4 : Asynchronous Angular Testing In Depth

  • Solution 1 : utiliser une DoneFn en paramètre du test pour indiquer à Jasmine d’attendre jusqu’à son appel,
  • Solution 2 : (fakeAsync)[https://angular.io/guide/testing#component-with-async-service]. Composant fournit par Angular et qui propose un mécanisme utilisé par Angular pour détecter les appels asynchrone,
    • Créer une zone de test qui détecte les différents appels asynchrones, les enregistre et permet ensuite de débloquer les différentes files d’attente,
    • tick(): permet de simuler l’avance du temps !,
      • PI : dans le cas de fakeAsync, la fonction setTimeOut est remplacée par une version qui ne fait rien. Pour que le temps avance, il faut faire tick !,
      • Par contre tellement c’est simple quand on gère les TimeOut mais pour le reste, comment tu gères le temps ?,
    • flush() : gère tous les files d’attente :),
    • flushMicrotasks() : uniquement les microtasks (promesse),
  • Solution 3 : (async)[https://angular.io/guide/testing#async-test-with-async]. Il s’agit du composant utilisé dans le beforeEach pour gérer l’asynchrone,
    • Créer également une zone de test mais semble-t-il différente,
    • fixture.whenStable() : au sein d’async tous les appels sont captés et quand ils sont tous finis, whenStable() agit !
    • Obligatoire dans le cadre d’un appel http qui n’est pas supporté par fakeAsync,
    • Obligatoire aussi si les tests ne s’executent pas avec ng test (les css et autres templates seraient chargés pas une requête http …),

Gestion des tasks et microtasks : le gestionnaire “Event loop” gère les différentes actions en fonction de différentes files d’attente. Il semble que le navigateur puisse venir jouer les troubles fêtes mais c’est à savoir,
* Un (article)[https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/] qui date un peu mais avec de bons exemples,
* Si une promesse est exécutée dans une promesse : elle est ajoutée dans la pile quid d’un setTimeOut ?

Section 5 : Angular E2E (End to End) Testing with Cypress

Ayant fait pas mal de Cypress dernièrement : pas grand de neuf. Le chapitre est même un peu léger je trouve. Après ce n’est pas une formation à Cypress.

Section 6 : Section 6 : Preparing an Angular Application for Continuous Integration

Je n’utilise pas Travis et à titre perso, je n’ai pas de CI donc je n’ai fait que suivre.