Mise en œuvre d'un projet informatique

Définir et conduire un projet informatique. On y montrera les outils nécessaire à tout projet : un linter et une bibliothèque de tests.

Un projet informatique a un début, lorsque l'on crée le dossier qui va le contenir, mais il n'a que rarement de fin : il y a toujours des fonctionnalités à ajouter et des bugs à corriger. Enfin, et c'est le plus important, un code est fait pour être utilisé.

De ces deux constatations, on en déduit trois règles fondamentales d'un code utile. Il faut qu'il soit :

Le langage d'application n'a que peu d'intérêt en soit. On choisit celui qui est le plus adapté à notre but. Ici, on utilisera le python mais tout ce qu'on verra est transposable pour tout autre langage sérieux. L'éditeur de texte que l'on utilisera sera vscode. Il en existe d'autres très bien aussi et tout ce qu'on verra avec vscode (les raccourcis claviers, et aides au développement) sont transposables à d'autres éditeurs en lisant la doc.

Écrire du code nécessite de nombreuses automatisations et aides pour que ce ne soit pas pénible, ne vous privez pas d'outils parce que vous n'avez pas envie d'apprendre de nouvelles choses et que ça suffit bien pour ce que je veux faire. Vous allez au final perdre plus de temps que l'apprentissage initial (ce qui est tarte).

Un projet

On va créer un projet pour comprendre comment tout ça fonctionne.

Nous allons préparer le projet dans lequel nous allons coder. Ceci se fait avec vscode en ouvrant un dossier. Ce dossier sera le départ de votre projet et s'appelle workspace.

  1. Commencez par créer le dossier hello-dev dans un explorateur de fichier
  2. dans vscode, choisissez : "fichier > ouvrir le dossier..." puis naviguez jusqu'à votre dossier hello-dev. On vous demande si vous faites confiances aux auteurs, puisque c'est vous dites oui.

Lorsque l'on code et que l'on ne veut pas de problèmes en développement, les noms de fichiers et de dossier doivent êtres sans espaces et sans accents.

Un projet informatique est contenu dans un dossier

Ce n'et pas juste un ensemble de fichiers.

Dans vscode, il faudra toujours choisir d'ouvrir un dossier lorsque l'on travaille sur un projet.

Fichier python

On va créer notre premier fichier python :

  1. allez dans menu Fichier > Nouveau Fichier
  2. et sauvez le de suite : menu Fichier > Enregistrer avec le nom main.py.

Vscode à compris que c'était du python, il l'écrit dans la barre de statut (la dernière ligne, en bleu, de la fenêtre vscode, voir user interface).

Si vous n'avez pas suivi le tuto d'installation de vscode et son interaction avec python, il vous demandera peut-être de :

  1. choisir un interpréteur : prenez le python de votre distribution
  2. choisir un linter : supprimer la fenêtre de warning, on fera ça plus tard.
  3. choisir des tests : supprimer la fenêtre de warning, on fera ça plus tard.

Exécution d'un fichier

Écrivez dans le fichier main.py :

print("bonjour les gens !")

En vous rappelant ce que vous avez vu dans le tutorial python et vscode :

Exécutez le code de deux manières différentes :

  • avec le terminal
  • avec le petit triangle

Du joli code

Vous allez passer beaucoup de temps à lire du code, le votre et celui des autres. Il est important que ce soit facile. Pour cela il faut que le style de code soit cohérent. Python donne des règle de style, c'est ce qu'on appelle la PEP8.

Linter

Un linter est un programme permettant de signaler les erreurs de style pour les corriger. Installer un linter vous permet de vous familiariser avec les règles d'un joli code.

Il existe de nombreux linter, nous allons utiliser flake8 qui s'intègre bien avec vscode.

Installation

Utilisation

Vérifions qu'il remarque bien les fautes :

Modifiez le fichier main.py pour écrire :


print ("bonjour les gens !")

Une fois le fichier sauvé vous devriez voir que l'espace entre print et la parenthèse est souligné en rouge :

vsc-linter-souligne

On peut cliquer sur la status-bar pour voir l'erreur ou passer le curseur sur la partie rouge :

style : NE JAMAIS METTRE D'ESPACE APRÈS UN NOM DE FONCTION

Parce qu'on ne voit pas immédiatement si c'est une fonction ou un nom de variable.

Vous devriez peut-être aussi avoir la parenthèse de fin souligné en jaune. C'est parce que la dernière ligne de votre fichier n'est pas vide. Si ce n'est pas le cas, c'est que vous avez bien que 2 lignes dans votre fichier, la seconde étant vide.

style : la dernière ligne d'un fichier python est vide

Prenez l'habitude d'écrire du code sans aucune erreur de style. Et, surtout, apprenez pourquoi cette règle existe. Suivre une règle sans comprendre pourquoi elle existe n'est pas efficace... Parce qu'on ne sait pas s'il faut la suivre ou pas.

Tout au long de ce projet et des prochains, il faut faire en sorte qu'il n'y ait jamais d'erreur de style. Soyez donc vigilant au début avant que cela devienne naturel.

black

Il existe des outils permettant de formatter automatiquement le code, comme l'utilitaire black par exemple.

Une fois black installé, vous pouvez l'utiliser depuis un terminal ou depuis vscode.

Séparer code et main

Un projet c'est trois choses d'égale importance :

  • le code : les fonctions utilisées
  • le main : le programme principal, c'est ce qu'on exécute lorsque veut faire marcher le projet
  • les tests : ce qui garantit que le code fonctionne

Pour séparer les différentes parties vous allez :

Créez deux fichiers dans notre projet, l'un nommé le_code.py qui contiendra notre code et l'autre nommé main.py qui sera notre programme principal

Fichier le_code.py :

def bonjour():
    return "Bonjour les gens !"

Fichier main.py :

from le_code import bonjour

print(bonjour())

On a importé le nom bonjour défini dans le fichier le_code.py grâce à un import. L'autre façon aurait été d'importer juste le fichier code. On aurait alors eu :

import le_code

print(le_code.bonjour())

La notation pointée se lit alors : exécute le nom bonjour définit dans le_code.py.

Cours sur les modules python pour plus d'information.

Ne jamais jamais jamais utiliser from le_code import * qui importe tous les noms définis dans le_code.py. On ne sait pas vraiment ce qui a été importé en lisant le_code.py. : notre code n'est pas lisible ! Le gain d'écriture de * plutôt que bonjour sera perdu au centuple plus tard lorsque l'on devra chercher dans tous les fichiers du projet où l'on a bien pu définir bonjour...

Comme on va passer plus de temps à lire/comprendre du code qu'à l'écrire, il faut optimiser la lecture et non l'écriture de code. On préférera toujours la lisibilité à la rapidité.

Tests

Les tests permettent de vérifier que notre code fonctionne. Ils font partie du programme et on peut s'y référer quand on veut. Lorsque l'on modifie le code, on pourra toujours exécuter tous les tests pour vérifier que notre programme fonctionne aussi bien qu'avant.

La commande assert

On utilise en python la commande assert. Elle fonctionne ainsi :

assert <expression logique>

Si l'expression logique est vraie, le programme continue sans rien dire et si l'expression logique est fausse, le programme s'arrête avec l'erreur : AssertionError.

Essayons ça avec la plus simple des expressions logiques : True

Créez un fichier nommé test_projet.py qui contiendra le code :

print("avant l'assert")

assert True

print("après l'assert")

Exécutez-le.

Lorsque vous exécutez ce fichier, vous devez obtenir le résultat suivant :

avant l'assert
après l'assert

La condition logique étant vraie, la commande assert n'a rien fait.

Changeons ça en mettant une condition logique fausse :

Modifiez test_projet.py pour qu'il contienne le code :

print("avant l'assert")

assert False

print("après l'assert")

Exécutez le fichier test_projet.py.

Vous devez obtenir le résultat suivant :

avant l'assert
Traceback (most recent call last):
  File "/Users/fbrucker/Documents/temp/hello-dev/test_projet.py", line 3, in 
    assert False
AssertionError

La première ligne a bien été exécutée (on voit écrit avant l'assert), puis le programme a planté. La condition logique étant fausse, la commande assert a levé une exception nommée AssertionError qui a stoppé l'exécution du programme. La ligne print("après l'assert") n'a pas été exécutée.

D'habitude, nos expressions logiques vérifie qu'un comportement observé (l'exécution d'une fonction) est conforme au comportement théorique (le résultat qu'on aimerait avoir). Pour ne pas se perdre on range ce test dans une fonction dont le nom décrit le test. Par exemple, testons la somme :

Modifiez test_projet.py pour qu'il contienne le code :


def test_somme_neutre():
    tête_a_toto = 0
    assert 0 + 0 == tête_a_toto

def test_somme_1_plus_0():
    assert 0 + 1 == 1


def test_somme_1_plus_2():
    assert 1 + 2 == 3
 

Exécutez le fichier test_projet.py.

Pour tester la somme, j'ai décidé de faire 3 tests :

Lorsque l'on exécute ce code, il ne se passe rien. Est-ce bon signe ?

Modifiez la fonction test_somme_neutre du fichier test_projet.py pour qu'elle soit égale à :

# ...

def test_somme_neutre():
    tête_a_toto = 0
    assert 0 + 0 == 42

# ...

Exécutez le fichier test_projet.py.

On a coutume de mettre des # ... pour dire que le reste du code du fichier n’est pas changé.

Ce n’est pas la peine de les copier/coller.

Le code s'exécute encore encombre. Bon, là, c'est pas normal car 0 + 0 ne peut être égal à 42.

La raison est que test_projet.py définit des fonctions mais il ne les exécute jamais. Les trois fonctions de test sont définies mais jamais utilisées.

On a donc 2 choix :

Nous allons utiliser la seconde option avec le module Pytest.

Installation de la bibliothèque de tests

Utilisation de la bibliothèque de tests

On y reviendra à de nombreuses reprises :

Les tests sont la pierre angulaire d'une bonne programmation : ils garantissent le fonctionnement de votre code et qu'il ne peut pas régresser.

Les tests sont de petites fonctions dont le but est de tester une fonctionnalité du programme (souvent le résultat de l'exécution d'une fonction). Le test consiste en une assertion que l'on veut être vraie si que le code fonctionne. Si l'assertion est fausse c'est qu'il y a un bug.

Tapez la commande python -m pytest dans un terminal.

Il vous faut utiliser le python de vscode, son nom peut donc changer.

Vous devriez obtenir quelque chose du genre :

vsc-pytest

Corrigez le test de test_projet.py qui rate et re-exécutez le code pour voir les 3 tests réussir.

Que fait pytest :

Pytest exécute toutes les fonctions commençant par test_ de tous les fichiers commençant par test_ d’un projet.

On peut aussi exécuter les tests directement avec vscode. Pour cela, cliquez sur le petit erlenmeyer. Vous pourrez ensuite :

  1. découvrir les tests du projet
  2. exécuter tous les tests
  3. n'exécuter qu'un seul test

vsc-pytest-erlenmeyer

Test du projet

Notre projet contient pour l'instant une fonction qui rend une constante. Tester une constante n'a pas de sens, modifions notre code pour que notre fonction ait plus de sens :

Modifiez le fichier le_code.py pour qu'il contienne le code :

def bonjour(nom):
    return "bonjour " + nom + " !"

On peut maintenant remplacer les tests :

Modifiez le fichier test_projet.py pour qu'il contienne le code :

from le_code import bonjour


def test_bonjour():
    assert bonjour("monde") == "bonjour monde !"

Exécutez les tests pour vérifier que votre code fonctionne.

Maintenant que les tests passent, on peut modifier le programme principal.

Modifiez le fichier main.py pour qu'il contienne le code :

from le_code import bonjour

print(bonjour("monde"))

Exécutez le programme principal.

Félicitations, vous avez fait votre premier projet fonctionnel !

Les fichiers

Les trois fichiers du projet final sont disponibles