mirror of https://github.com/nocodb/nocodb
Muhammed Mustafa
2 years ago
1 changed files with 159 additions and 0 deletions
@ -0,0 +1,159 @@
|
||||
--- |
||||
title: "Unit Test" |
||||
description: "How to write unit tests" |
||||
position: 3300 |
||||
category: "Engineering" |
||||
menuTitle: "Unit Test" |
||||
--- |
||||
|
||||
## Key points |
||||
|
||||
- We use [Mocha](https://mochajs.org/) as our test runner and [chai](https://www.chaijs.com/) as our assertion library. |
||||
- We use [Supertest](https://www.npmjs.com/package/supertest) to test our API endpoints. |
||||
- All individual unit tests are independent of each other. We don't use any shared state between tests. |
||||
- Test environment also includes `sakila` database and any change on `sakila` by a test is reverted before running other tests. |
||||
- While running unit tests, it tries to connect to mysql server running on `localhost:3306` with username `root` and password `password`(which can be configured) and if not found, it will use `sqlite` as a fallback, hence no requirement of any sql server to run tests. |
||||
|
||||
## Walk through of writing a unit test |
||||
|
||||
We will create an `Table` test suite as an example. |
||||
|
||||
### Describing test suite |
||||
|
||||
Create `Table` test suite by using `describe` function of mocha. |
||||
|
||||
```typescript |
||||
export default function () { |
||||
describe('Table', tableTests); |
||||
} |
||||
``` |
||||
|
||||
### Configure test |
||||
|
||||
We will configure `beforeEach` which is called before each test is executed. We will use `init` function from `nocodb/packages/tests/unit/init/index.ts`, which is a helper function which configures the test environment(i.e resetting state, etc.). |
||||
|
||||
`init` does the following things - |
||||
|
||||
- It initializes a `Noco` instance(reused in all tests). |
||||
- Restores `meta` and `sakila` database to its initial state. |
||||
- Creates the root user. |
||||
- Returns `context` which has `auth token` for the created user, node server instance(`app`), and `dbConfig`. |
||||
|
||||
We will use `createProject` and `createProject` factories to create a project and a table. |
||||
|
||||
```typescript |
||||
let context; |
||||
|
||||
beforeEach(async function () { |
||||
context = await init(); |
||||
|
||||
project = await createProject(context); |
||||
table = await createTable(context, project); |
||||
}); |
||||
``` |
||||
|
||||
### Test case |
||||
|
||||
We will use `it` function to create a test case. We will use `supertest` to make a request to the server. We use `expect`(`chai`) to assert the response. |
||||
|
||||
```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; |
||||
}); |
||||
``` |
||||
|
||||
### Integrating the new test suite |
||||
|
||||
We create a new file `table.test.ts` in `packages/nocodb/tests/unit/rest/tests` directory. |
||||
|
||||
```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); |
||||
} |
||||
``` |
||||
|
||||
We can then import the `Table` test suite to `Rest` test suite in `packages/nocodb/tests/unit/rest/index.test.ts` file(`Rest` test suite is imported in the root test suite file which is `packages/nocodb/tests/unit/index.test.ts`). |
||||
|
||||
## Running test |
||||
|
||||
To run tests, run `npm run test:unit` in `packages/nocodb` directory. |
||||
|
||||
> NOTE: We can also run individual test by using `.only` in `describe` or `it` function and the running the test command. |
||||
|
||||
```typescript |
||||
it.only('Get table list', async () => { |
||||
``` |
||||
|
||||
## Folder structure |
||||
|
||||
The root folder for unit tests is `packages/tests/unit` |
||||
|
||||
- `rest` folder contains all the test suites for rest apis. |
||||
- `model` folder contains all the test suites for models. |
||||
- `factory` folder contains all the helper functions to create test data. |
||||
- `init` folder contains helper functions to configure test environment. |
||||
- `index.test.ts` is the root test suite file which imports all the test suites. |
||||
- `TestDbMngr.ts` is a helper class to manage test databases (i.e. creating, dropping, etc.). |
||||
|
||||
## Patterns to follow |
||||
|
||||
- **Factories** |
||||
- Use factories for create/update/delete data. No data should be directly create/updated/deleted in the test. |
||||
- While writing a factory make sure that it can be used with as less parameters as possible and use default values for other parameters. |
||||
- Use named parameters for factories. |
||||
|
||||
``` typescript |
||||
createUser({ email, password}) |
||||
``` |
||||
|
||||
- Use one file per factory. |
||||
|
||||
## Using sakila db |
||||
|
||||
To use sakila db use `createSakilaProject` from `factory/project` to create a project. This project will be seeded with `sakila` tables. |
||||
|
||||
## Configurations |
||||
|
||||
- For Mysql db configuration, use the following environment variables to configure. |
||||
- `DB_USER` : mysql username |
||||
- `DB_PASSWORD` : mysql password |
||||
- `DB_HOST` : mysql host |
||||
- `DB_PORT` : mysql port |
Loading…
Reference in new issue