6.5 KiB
titre : "Écrire des tests unitaires" description: "Présentation des tests unitaires" balises : ['Ingénierie']
Tests unitaires
- Tous les tests unitaires individuels sont indépendants les uns des autres. Nous n'utilisons aucun état partagé entre les tests.
- L’environnement de test comprend
sakilaexemple de base de données et toute modification apportée à celle-ci par un test est annulée avant l’exécution d’autres tests. - Lors de l’exécution de tests unitaires, il essaie de se connecter au serveur MySQL exécuté sur
localhost:3306avec nom d’utilisateurrootet mot de passepassword(qui peut être configuré) et s’il n’est pas trouvé, il utiliserasqlitecomme solution de secours, donc aucune exigence d’un serveur SQL pour exécuter des tests.
Conditions préalables
- MySQL est préférable, mais les tests peuvent également s’appuyer sur SQLite
Installation
pnpm --filter=-nocodb install
# add a .env file
cp tests/unit/.env.sample tests/unit/.env
# open .env file
open tests/unit/.env
Configurez les variables suivantes
DB_HOST : hôte DB_PORT : port DB_USER : nom d'utilisateur DB_PASSWORD : mot de passe
Exécuter des tests
pnpm run test:unit
Structure des dossiers
Le dossier racine des tests unitaires estpackages/nocodb/tests/unit
restLe dossier contient toutes les suites de tests pour les API restantes.- Le dossier
restcontient toutes les suites de tests pour les API restantes. - Le dossier
modelcontient toutes les suites de tests pour les modèles. - Le dossier
factorycontient toutes les fonctions d’aide pour créer des données de test. initLe dossier contient des fonctions d'assistance pour configurer l'environnement de test.index.test.tsest le fichier racine de la suite de tests et importe toutes les suites de tests.TestDbMngr.tsest une classe d'assistance pour gérer les bases de données de test (c'est-à-dire la création, la suppression, etc.).
Modèle d'usine
- Utilisez des usines pour créer/mettre à jour/supprimer des données. Aucune donnée ne doit être directement créée/mise à jour/supprimée dans le test.
- Lors de l'écriture d'une usine, assurez-vous qu'elle peut être utilisée avec le moins de paramètres possible et utilisez les valeurs par défaut pour les autres paramètres.
- Utilisez des paramètres nommés pour les usines.
createUser({ email, password}) - Utilisez un fichier par usine.
Procédure pas à pas pour l'écriture d'un test unitaire
Nous allons créer unTablesuite de tests à titre d'exemple.
Configurer le test
Nous allons configurerbeforeEachqui est appelé avant l’exécution de chaque test. Nous utiliseronsinitfonction denocodb/packages/nocodb/tests/unit/init/index.ts, qui est une fonction d'assistance qui configure l'environnement de test (c'est-à-dire la réinitialisation de l'état, etc.).
initfait les choses suivantes -
- Il initialise un
Nocoinstance (réutilisée dans tous les tests). - Restaure
metaetsakilabase de données à son état initial. - Crée l'utilisateur root.
- Retour
contextqui aauth tokenpour l'utilisateur créé, instance de serveur de nœud (app), etdbConfig.
Nous utiliseronscreateProjectetcreateProjectusines pour créer un projet et une table.
let context;
beforeEach(async function () {
context = await init();
project = await createProject(context);
table = await createTable(context, project);
});
Cas de test
Nous utiliseronsitfonction pour créer un scénario de test. Nous utiliseronssupertestpour faire une requête au serveur. Nous utilisonsexpect(chai) pour affirmer la réponse.
it('Get table list', async function () {
const response = await request(context.app)
.get(`/api/v1/db/meta/projects/${project.id}/tables`)
.set('xc-auth', context.token)
.send({})
.expect(200);
expect(response.body.list).to.be.an('array').not.empty;
});
:::Info
We can also run individual test by using .onlydansdescribeouitfonction et l’exécution de la commande test.
:::
it.only('Get table list', async () => {
Intégration de la nouvelle suite de tests
Nous créons un nouveau fichiertable.test.tsdanspackages/nocodb/tests/unit/rest/testsannuaire.
import 'mocha';
import request from 'supertest';
import init from '../../init';
import { createTable, getAllTables } from '../../factory/table';
import { createProject } from '../../factory/project';
import { defaultColumns } from '../../factory/column';
import Model from '../../../../src/lib/models/Model';
import { expect } from 'chai';
function tableTest() {
let context;
let project;
let table;
beforeEach(async function () {
context = await init();
project = await createProject(context);
table = await createTable(context, project);
});
it('Get table list', async function () {
const response = await request(context.app)
.get(`/api/v1/db/meta/projects/${project.id}/tables`)
.set('xc-auth', context.token)
.send({})
.expect(200);
expect(response.body.list).to.be.an('array').not.empty;
});
}
export default function () {
describe('Table', tableTests);
}
Nous pouvons alors importer leTablesuite de tests pourRestsuite de tests danspackages/nocodb/tests/unit/rest/index.test.tsdéposer(Restla suite de tests est importée dans le fichier racine de la suite de tests qui estpackages/nocodb/tests/unit/index.test.ts).
Base de données d'échantillons d'ensemencement (Sakila)
function tableTest() {
let context;
let sakilaProject: Project;
let customerTable: Model;
beforeEach(async function () {
context = await init();
/******* Start : Seeding sample database **********/
sakilaProject = await createSakilaProject(context);
/******* End : Seeding sample database **********/
customerTable = await getTable({project: sakilaProject, name: 'customer'})
});
it('Get table data list', async function () {
const response = await request(context.app)
.get(`/api/v1/db/data/noco/${sakilaProject.id}/${customerTable.id}`)
.set('xc-auth', context.token)
.send({})
.expect(200);
expect(response.body.list[0]['FirstName']).to.equal('MARY');
});
}