***

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`sakila`exemple 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:3306`avec nom d’utilisateur`root`et mot de passe`password`(qui peut être configuré) et s’il n’est pas trouvé, il utilisera`sqlite`comme 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

```bash
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

```bash
pnpm run test:unit
```

### Structure des dossiers

Le dossier racine des tests unitaires est`packages/nocodb/tests/unit`

* `rest`Le dossier contient toutes les suites de tests pour les API restantes.
* Le dossier `rest` contient toutes les suites de tests pour les API restantes.
* Le dossier `model` contient toutes les suites de tests pour les modèles.
* Le dossier `factory` contient toutes les fonctions d’aide pour créer des données de test.
* `init`Le dossier contient des fonctions d'assistance pour configurer l'environnement de test.
* `index.test.ts` est le fichier racine de la suite de tests et importe toutes les suites de tests.
* `TestDbMngr.ts` est 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.
  ```ts
  createUser({ email, password})
  ```
* Utilisez un fichier par usine.

### Procédure pas à pas pour l'écriture d'un test unitaire

Nous allons créer un`Table` suite de tests à titre d’exemple.

#### Configurer le test

Nous allons configurer`beforeEach`qui est appelé avant l’exécution de chaque test. Nous utiliserons`init`fonction de`nocodb/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.).

`init`fait les choses suivantes -

* Il initialise un`Noco`instance (réutilisée dans tous les tests).
* Restaure`meta`et`sakila`base de données à son état initial.
* Crée l'utilisateur root.
* Retour`context`qui a`auth token`pour l'utilisateur créé, instance de serveur de nœud (`app`), et`dbConfig`.

Nous utiliserons`createProject`et`createProject`usines pour créer un projet et une table.

```typescript
let context;

beforeEach(async function () {
  context = await init();

  project = await createProject(context);
  table = await createTable(context, project);
});
```

#### Cas de test

Nous utiliserons`it`fonction pour créer un scénario de test. Nous utiliserons`supertest`pour faire une requête au serveur. Nous utilisons`expect`(`chai`) pour affirmer la réponse.

```typescript
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 `.only`dans`describe`ou`it`fonction et l’exécution de la commande test.

:::

```typescript
it.only('Get table list', async () => {
```

#### Intégration de la nouvelle suite de tests

Nous créons un nouveau fichier`table.test.ts`dans`packages/nocodb/tests/unit/rest/tests`annuaire.

```typescript
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 le`Table`suite de tests pour`Rest`suite de tests dans`packages/nocodb/tests/unit/rest/index.test.ts`déposer(`Rest`la suite de tests est importée dans le fichier racine de la suite de tests qui est`packages/nocodb/tests/unit/index.test.ts`).

### Base de données d'échantillons d'ensemencement (Sakila)

```typescript

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');
  });
}
```