Skip to content

Commit

Permalink
Merge pull request #376 from MTES-MCT/tech/e2e-tests
Browse files Browse the repository at this point in the history
Setup end to end tests
  • Loading branch information
pyDez authored Nov 7, 2024
2 parents c69f1be + 5610b3e commit 3979046
Show file tree
Hide file tree
Showing 18 changed files with 811 additions and 31 deletions.
64 changes: 63 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ env:
USE_DOCKER: False
LANG: 'fr_FR.UTF-8'
LC_ALL: 'fr_FR.UTF-8'
DJANGO_SETTINGS_MODULE: 'config.settings.ci'

on:
pull_request:
branches: [ "main", "envergo_haie", "feature/bootstrap-haie-bcae8" ] # TODO: keep only main
branches: [ "main" ]

push:
branches: [ "main" ]
Expand Down Expand Up @@ -98,3 +99,64 @@ jobs:

- name: Run Django Tests
run: pytest


e2e:
timeout-minutes: 60
runs-on: ubuntu-latest

# Configure the database service
services:
database:
image: postgis/postgis:14-master
env:
POSTGRES_USER: envergo
POSTGRES_PASSWORD: envergo
POSTGRES_DB: envergo
ports:
- 5432:5432
# Set health checks to wait until postgres has started
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
- name: Install dependencies
run: npm ci
- name: Install French locale
run: |
sudo apt update
sudo apt install -y language-pack-fr
sudo locale-gen fr_FR.UTF-8
sudo update-locale LANG=fr_FR.UTF-8 LC_ALL=fr_FR.UTF-8
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Create empty .env file if it does not exist
run: touch .env
- name: Launch services
run: docker compose -f docker-compose.yml -f docker-compose.e2e.yml up -d
- name: Migrate database
run: docker compose -f docker-compose.yml -f docker-compose.e2e.yml run --rm django python manage.py migrate
- name: Seed database
run: docker compose -f docker-compose.yml -f docker-compose.e2e.yml run --rm django python manage.py loaddata e2e/fixtures/db_seed.json
- name: Build assets
run: docker compose -f docker-compose.yml -f docker-compose.e2e.yml run --rm django bash bin/build_assets.sh
- name: Wait for services to be ready
run: wget --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 --tries 10 http://localhost:3000/
- name: Run Playwright tests
run: npx playwright test
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
retention-days: 30

5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -291,4 +291,9 @@ data.*
### Jetbrain's IDE
.idea/

/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/

altis/
76 changes: 63 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,27 +37,31 @@ Il est recommandé de se baser sur la version docker.

#### Avec Docker

> NB : pour les commandes `docker compose`, cette documentation utilise la syntaxe de la version 2 en remplacant le tiret (`-`) par un espace et utlisant donc `docker compose` à la place de `docker-compose`.
> Si vous avez une version plus ancienne, vous pouvez utiliser la syntaxe `docker-compose`.
> [Plus d'infos...](https://docs.docker.com/compose/releases/migrate/#what-are-the-differences-between-compose-v1-and-compose-v2)
Pour lancer l'environnement rapidement :

```bash
$ git clone … && cd envergo
$ touch .env
$ docker-compose build
$ docker-compose up
$ docker compose build
$ docker compose up
```

Pour construire la base de données (dans un autre shell) :

```bash
$ docker-compose run --rm django python manage.py migrate
$ docker compose run --rm django python manage.py migrate
```

Pour avoir accès aux fichiers `static` depuis le serveur de debug :

```bash
$ npm install
$ npm run build
$ docker-compose run --rm django python manage.py collectstatic
$ docker compose run --rm django python manage.py collectstatic

```

Expand All @@ -81,17 +85,17 @@ les droits de création de base et d'extension.
#### Résoudre l'erreur "raster does not exist"

Dans les versions les plus récentes de postgis, il est nécessaire [d'installer l'extension "raster"](https://docs.djangoproject.com/fr/5.0/ref/contrib/gis/install/postgis/#post-installation).
Si, lors du `docker-compose up` ci-dessus vous avez ce type d'erreur :
Si, lors du `docker compose up` ci-dessus vous avez ce type d'erreur :

envergo_postgres | 2024-05-13 14:35:21.651 UTC [35] ERROR: type "raster" does not exist at character 118

Il vous faudra créer cette extension (dans un autre terminal, avec le `docker-compose up` qui tourne en parallèle) :
Il vous faudra créer cette extension (dans un autre terminal, avec le `docker compose up` qui tourne en parallèle) :

```bash
$ docker-compose run --rm postgres create_raster
$ docker compose run --rm postgres create_raster
```

Puis interrompre et relancer le `docker-compose up`. Les migrations Django devraient alors s'exécuter sans erreur.
Puis interrompre et relancer le `docker compose up`. Les migrations Django devraient alors s'exécuter sans erreur.


### Qualité du code
Expand Down Expand Up @@ -196,7 +200,7 @@ pip-sync local.txt
Pour mettre à jour l'image Docker, relancer `build` puis `up`.


## Tests
## Tests unitaires

Les tests sont écrits avec [pytest](https://docs.pytest.org/). Tous les helpers de [pytest-django](https://pytest-django.readthedocs.io/en/latest/) sont disponibles.

Expand All @@ -211,9 +215,55 @@ pytest
Via Docker :

```bash
docker-compose run --rm django pytest
docker compose run --rm django pytest
```


## Tests End-to-End

Les tests end-to-end sont écrits avec [Playwright](https://playwright.dev/).
Les tests E2E permet de valider que les chemins utilisateurs critiques (faire une simulation, demander un avis, répondre à une demande d'avis, etc) fonctionnent correctement.
Cela permet en outre de vérifier le bon fonctionnement des composants JavaScript de plus en plus présent sur les pages et pour le moment non couvert par d'autre tests.

Ils se basent sur une base de données de tests dédiée contenant une jeu de données minimum présent dans ce [fichier](e2e/fixtures/db_seed.json) et que l’on peut remplir pour les besoins de chaque test.

Ils tournent dans la CI de Github.


### Lancer les tests E2E en local

#### Prérequis
Pour lancer les tests E2E en local, il faut avant tout créer une base de données dédiée similaire à celle qui sera utilisée par la CI.
Pour cela, il faut lancer les commandes suivantes :

```bash
$ . envs/postgres
$ docker compose exec postgres bash -c 'dropdb --if-exists envergo-test -U "$POSTGRES_USER" -f'
$ docker compose exec postgres bash -c 'createdb envergo-test -U "$POSTGRES_USER" -O "$POSTGRES_USER"'
$ docker compose run -e POSTGRES_DB=envergo-test --rm django python manage.py migrate
$ docker compose run -e POSTGRES_DB=envergo-test --rm django python manage.py loaddata e2e/fixtures/db_seed.json
```

Vous devez ensuite installer Playwright avec les commandes suivantes:
```bash
$ npm install @playwright/test
$ npx playwright install
```

#### Lancer les tests

Vous devez tout d'abord lancer l'application en pointant vers la base de test et avec le bon fichier de settings :

```bash
$ POSTGRES_DB=envergo-test docker compose -f docker-compose.yml -f docker-compose.e2e.yml up -d
```

Enfin vous pouvez lancer les tests avec l'une des commandes suivantes :

```bash
$ npx playwright test --ui # pour lancer les tests dans un navigateur
$ npx playwright test # pour lancer les tests dans un shell
```

## Recette et déploiement

Expand Down Expand Up @@ -307,10 +357,10 @@ Alternative : récupérer le backup nocture depuis Scalingo.

```bash
$ . envs/postgres
$ docker-compose exec postgres bash -c 'dropdb envergo -U "$POSTGRES_USER" -f'
$ docker-compose exec postgres bash -c 'createdb envergo -U "$POSTGRES_USER" -O "$POSTGRES_USER"'
$ docker compose exec postgres bash -c 'dropdb envergo -U "$POSTGRES_USER" -f'
$ docker compose exec postgres bash -c 'createdb envergo -U "$POSTGRES_USER" -O "$POSTGRES_USER"'
$ cat /tmp/envergo.dump | docker exec -i envergo_postgres psql -U $POSTGRES_USER -d $POSTGRES_DB
$ docker-compose run --rm django python manage.py migrate
$ docker compose run --rm django python manage.py migrate
```


Expand Down
15 changes: 15 additions & 0 deletions compose/django/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ RUN apt-get update && apt-get install --no-install-recommends -y \
# dependencies for building Python packages
build-essential

# build assets
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \
&& apt-get install -y nodejs
# Requirements are installed here to ensure they will be cached.
COPY ./requirements .

Expand All @@ -36,12 +39,24 @@ RUN apt-get update && apt-get install --no-install-recommends -y \
libpq-dev \
# Translations dependencies
gettext \
# localisation dependencies \
locales locales-all \
# Geo tools
binutils libproj-dev gdal-bin \
curl \
# cleaning up unused files
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
&& rm -rf /var/lib/apt/lists/*

# Install Node.js and npm
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \
&& apt-get install -y nodejs

RUN locale-gen fr_FR.UTF-8 && update-locale LANG="fr_FR.UTF-8" LC_ALL="fr_FR.UTF-8"

ENV LANG fr_FR.UTF-8
ENV LC_ALL fr_FR.UTF-8

# All absolute dir copies ignore workdir instruction. All relative dir copies are wrt to the workdir instruction
# copy python dependency wheels from python-build-stage
COPY --from=python-build-stage /usr/src/app/wheels /wheels/
Expand Down
73 changes: 73 additions & 0 deletions config/settings/ci.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""
With these settings, tests run faster.
"""

from .base import * # noqa
from .base import env

# GENERAL
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#debug
DEBUG = True
# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
SECRET_KEY = env(
"DJANGO_SECRET_KEY",
default="xa7B39ApH5wH2VZS28Hk1CfLs7Hta6iPAkModtOEft8iGv3jppqDeGSCvpW1AX4p",
)

# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
ALLOWED_HOSTS = [
"localhost",
]

# CACHES
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#caches
CACHES = {
"default": {
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
"LOCATION": "ratelimit-test",
}
}

# EMAIL
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
EMAIL_BACKEND = env(
"DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.console.EmailBackend"
)

# TEMPLATES
# ------------------------------------------------------------------------------
TEMPLATES[-1]["OPTIONS"]["loaders"] = [ # type: ignore[index] # noqa F405
(
"django.template.loaders.cached.Loader",
[
"django.template.loaders.filesystem.Loader",
"django.template.loaders.app_directories.Loader",
],
)
]

# EMAIL
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"


# django-extensions
# ------------------------------------------------------------------------------
# https://django-extensions.readthedocs.io/en/latest/installation_instructions.html#configuration
INSTALLED_APPS += ["django_extensions"] # noqa F405

# CELERY
CELERY_TASK_ALWAYS_EAGER = True
CELERY_TASK_EAGER_PROPAGATES = True


# Your stuff...
# ------------------------------------------------------------------------------

ENV_NAME = "test"
ENVERGO_AMENAGEMENT_DOMAIN = "localhost"
LANGUAGE_CODE = "en-us" # TODO: I force it in english because I can't achieve to run it in french in the github CI
12 changes: 12 additions & 0 deletions docker-compose.e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
services:
django:
environment:
- DJANGO_SETTINGS_MODULE=config.settings.ci
- POSTGRES_DB=${POSTGRES_DB:-envergo}
env_file:
- ./envs/django
- ./envs/postgres

postgres:
env_file:
- ./envs/postgres
3 changes: 3 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ services:
build:
context: .
dockerfile: ./compose/django/Dockerfile
environment:
- LANG=fr_FR.UTF-8
- LC_ALL=fr_FR.UTF-8
image: envergo_django
container_name: envergo_django
depends_on:
Expand Down
29 changes: 29 additions & 0 deletions e2e/evaluations/request.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { test, expect } from '@playwright/test';

test('User can request an evaluation', async ({ page }) => {
await page.goto('/');
await page.getByLabel('Menu principal').getByRole('link', { name: 'Demander un avis réglementaire' }).click();
await page.locator('p').filter({ hasText: 'Commencer la demande Durée : 1 min' }).getByRole('link').click();
await page.getByLabel('Address of the project Type').click();
await page.getByLabel('Address of the project Type').fill('Vue');
await page.getByRole('option', { name: 'Vue 44, Loire-Atlantique,' }).click();
await page.getByPlaceholder('15 caractères commençant par').click();
await page.getByPlaceholder('15 caractères commençant par').fill('PA1234567981011');
await page.getByLabel('Project description, comments').click();
await page.getByLabel('Project description, comments').fill('Assainissement de marécage pour faire une belle dalle béton bien propre');
await page.getByRole('button', { name: 'Poursuivre votre demande d\'' }).click();
await page.getByLabel('Adresse(s) e-mail', { exact: true }).click();
await page.getByLabel('Adresse(s) e-mail', { exact: true }).fill('[email protected]');
await page.getByLabel('Adresse(s) e-mail', { exact: true }).press('Tab');
await page.getByLabel('Urbanism department phone').fill('0601900917');
await page.getByLabel('Urbanism department phone').press('Tab');
await page.getByLabel('Urbanism department phone').click();
await page.getByLabel('Urbanism department phone').fill('0601900918');
await page.getByLabel('Adresse(s) e-mail Pé').click();
await page.getByLabel('Adresse(s) e-mail Pé').fill('[email protected]');
await page.getByRole('button', { name: 'Poursuivre votre demande d\'' }).click();
await page.getByRole('button', { name: 'Envoyer votre demande d\'avis' }).click();
await expect(page).toHaveTitle("Votre demande d'avis réglementaire a été enregistrée — EnvErgo");
await expect(page.getByText('Nous avons bien reçu votre demande d\'avis réglementaire.')).toBeVisible();

});
Loading

0 comments on commit 3979046

Please sign in to comment.