Vitest : Assertions

Les assertions permettent de garantir le bon fonctionnement d'un extrait de code. Découvrons leur rôle et leur syntaxe.

Icône de calendrier
Avancé
3 chapitres

Qu’est-ce qu’une assertion ?

Rôle

Dans l’écosystème des frameworks de test, le terme d’« assertion » fait référence à une déclaration qui vérifie qu’une condition spécifique est vraie pendant l’exécution d’un test unitaire.

Elle permet de garantir que le comportement du code correspond aux attentes définies par le développeur.

Si je possède une fonction utilitaire calculant la somme de 2 nombres, alors une assertion consisterait par exemple à écrire une condition qui vérifie que notre fonction :

  • « Retourne bien 4 pour la somme 1 + 3 »
  • « Retourne bien null s’il manque un argument »
  • « Retourne bien null si les arguments ne sont pas des nombres »
  • Etc.

APIs compatibles : Chai et Jest

Pour écrire des assertions, Vitest intègre les APIs (comprendre ici « les méthodes ») d’assertions de la librairie Chai ou encore du framework de test Jest.

Ces API offrent aux développeurs des approches différentes pour vérifier des conditions.

Vitest offre deux méthodes pour écrire des assertions : expect() et assert(). Bien qu’elles aient toutes deux pour but d’effectuer des assertions, elles adoptent une approche syntaxique distincte.

Ecrire des assertions

Expect

Fonctionnement

Cette approche consiste à écrire ses assertions avec la méthode expect().

Cette fonction va prendre en argument l’élément à tester (fonction, objet…) puis permettre d’y expliciter le résultat attendu en chaînant des méthodes de vérification.

Import

Importons la méthode expect().

demo.test.js
copié !
import { expect } from 'vitest'

Utilisation

Avec l’API de Chai

L’API de Chai confère une méthodologie de développement dirigée par le comportement nommée BDD (Behavior-Driven Development).

Cette méthodologie consiste à chaîner des assertions syntaxiquement proches du langage naturel, afin de rendre les tests plus lisibles et expressifs.

Une assertion se présente sous la forme de :

  • Mots-clés de liaison (to, be, is, that, which, and…)
  • Méthodes et mots-clés de vérification (equal(), empty(), true…)
demo.test.js
copié !
import { describe, test, expect } from 'vitest'
import { sum, getPseudos } from "../src/utils/demo"

describe("Fonction sum()", () => {
	test("Calcul de somme", () => {
		expect(sum(1, 3)).to.equal(4)
	})
	test("Pas d'arguments", () => {
		expect(sum()).to.be.null
	})
})

describe("Fonction getPseudos()", () => {
	test("Récupère 7 pseudos random", () => {
		expect(getPseudos(7)).to.be.an('array').that.have.lengthOf(7)
	})
	test("Pas d'arguments", () => {
		expect(getPseudos()).to.be.an('array').that.is.empty
	})
})

to.be.an('array').that.is.not.empty… Difficile de faire plus clair !

Avec l’API de Jest

L’API de Jest offre une syntaxe plus compacte, limitant le chaînage d’assertions, car elle :

  • Offre des méthodes de vérification plus spécifiques (aussi appelées « matchers »). Par exemple .to.be.below() de l’API de Chai se verra remplacé par .toBeLessThan() avec l’API de Jest.
  • N’intègre aucun mot-clé de liaison. Seul le mot-clé not permet d’inverser un test (on parle de « modifier »).
demo.test.js
copié !
import { describe, test, expect } from 'vitest'
import { sum, getPseudos } from "../src/utils/demo"

describe("Fonction sum()", () => {
	test("Calcul de somme", () => {
		expect(sum(1, 3)).toBe(4)
	})
	test("Pas d'arguments", () => {
		expect(sum()).toBeNull()
	})
})

describe("Fonction getPseudos()", () => {
	test("Récupère 7 pseudos random", () => {
		expect(getPseudos(7)).toBeInstanceOf(Array).toHaveLength(7)
	})
	test("Pas d'arguments", () => {
		expect(getPseudos()).toBeInstanceOf(Array).toHaveLength(0)
	})
})

Consulter la documentation officielle de expect().

Assert

Fonctionnement

Cette seconde approche consiste à écrire ses assertions avec la méthode assert().

Cette méthode est plus flexible qu’expect() puisqu’elle permet :

  • D’évaluer directement une expression de manière « traditionnelle » avec les opérateurs logiques et de comparaison.

OU

  • D’utiliser des méthodes de vérification (.equal(), .isTrue(), .isNull()…)

Import

Importons la méthode assert().

demo.test.js
copié !
import { assert } from 'vitest'

Utilisation

Approche traditionnelle

Utilisons assert() pour évaluer nos expressions de manière traditionnelle.

demo.test.js
copié !
import { describe, test, expect } from 'vitest'
import { sum, getPseudos } from "../src/utils/demo"

describe("Fonction sum()", () => {
	test("Calcul de somme", () => {
		assert(sum(1, 3) === 4)
	})
	test("Pas d'arguments", () => {
		assert(sum() === null)
	})
})

describe("Fonction getPseudos()", () => {
	test("Récupère 7 pseudos random", () => {
		assert(getPseudos(7) instanceof Array && getPseudos(7).length === 7)
	})
	test("Pas d'arguments", () => {
		assert(getPseudos() instanceof Array && getPseudos().length === 0)
	})
})
Approche par méthode spécifique

Utilisons assert() pour évaluer nos expressions avec les méthodes de vérification proposées par Vitest.

demo.test.js
copié !
import { describe, test, expect } from 'vitest'
import { sum, getPseudos } from "../src/utils/demo"

describe("Fonction sum()", () => {
	test("Calcul de somme", () => {
		assert.equal(sum(1, 3), 4)
	})
	test("Pas d'arguments", () => {
		assert.isNull(sum())
	})
})

describe("Fonction getPseudos()", () => {
	test("Récupère 7 pseudos random", () => {
		assert.isArray(getPseudos(7))
		assert.lengthOf(getPseudos(7), 7)
	})
	test("Pas d'arguments", () => {
		assert.isArray(getPseudos())
		assert.isEmpty(getPseudos())
	})
})

Vous remarquez ici qu’il est possible de spécifier plusieurs assert au sein d’un seul test. Cela signifie que toutes les assertions doivent être vraies pour que le test soit passé avec succès.

Consulter la documentation officielle de assert().

Expect VS Assert

Opposons dans un tableau comparatif ces deux approches :

Critèreexpect()assert()
ChaînageOuiNon
SyntaxeSyntaxe expressiveSyntaxe traditionnelle
LisibilitéFluide et lisibleExplicite mais peut être verbeuse
UsagePréféré par ceux appréciant la syntaxe expressive ou venant de contextes utilisant Jest ou ChaiPréféré par ceux habitués aux frameworks traditionnels
Exemplesexpect(foo).to.be.a('string') (Chai) ou expect(foo).toBeTypeOf('string') (Jest)assert.typeOf(foo, 'string') ou assert.typeOf(foo, 'string')

Gestion des erreurs

Les méthodes expect() et assert() prennent en charge les messages d’erreur personnalisés.

Si une assertion échoue, alors un message d’erreur accompagnera le résultat du test dans le terminal.

Avec expect() :

copié !
// Chai API
expect(foo, "foo devrait être vrai").to.be.true;

// Jest API
expect(foo, "foo devrait être vrai").toBe(true);

Avec assert() :

copié !
// Approche traditionnelle
assert(foo === true, "foo devrait être vrai");

// Approche par méthode spécifique
assert.isTrue(foo, "foo devrait être vrai");