23 Commits

Author SHA1 Message Date
db413e4a35 Réparation du tri
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-28 14:50:37 +01:00
e8fc6d0816 On remplace les if en elif pour avoir un résultat correct
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-28 14:47:20 +01:00
be7efbbfa7 Pour vérifier les calculs, on commence par transformer les entrées en entiers
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-28 14:45:58 +01:00
b8161eef93 Réparation des blagues
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-28 14:44:02 +01:00
bcfd13442f Réparation du séminaire
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-28 14:42:23 +01:00
f3dd9157c7 Ajout de tests pour tester toutes les fonctions
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-27 15:46:24 +01:00
40076ad3c1 Ajout d'un README pour les badges
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-26 18:57:48 +01:00
60e09751da Calcul de la couverture
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-26 18:47:18 +01:00
1fc558a2ad On utilise une classe pour les tests
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-26 18:37:12 +01:00
df223bd19e La fonction d'aide renvoie le texte à afficher au lieu de l'afficher directement
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-26 17:45:44 +01:00
7c2d082cf4 On lint le fichier de tests également
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-26 17:39:54 +01:00
1ba9934438 Pytest est requis
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-26 17:08:30 +01:00
d4d595ed68 Ajout d'un fichier de test avec pytest
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-26 17:07:12 +01:00
9026dd56cc Changement dans l'exécution du script
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-26 16:52:15 +01:00
6bd2b3c66c On exécute le programme
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-26 16:50:52 +01:00
01337279fc Ajout de docstrings. Pylint est content
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-26 16:47:46 +01:00
d8c6b6e6bf Factorisation de tests
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-26 16:45:23 +01:00
ecec88e230 Il faut aussi renommer les variables dans leurs usages
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-26 16:43:18 +01:00
9018ab4996 On renomme a, b et c qui ne sont pas suffisamment explicites
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-26 16:41:07 +01:00
ca69954315 On quitte un programme avec sys.exit
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-26 16:37:48 +01:00
4c241eeb60 On ne redéfinit pas des fonctions pré-implémentées
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-26 16:35:59 +01:00
5e55a65b3f Pas d'espace entre le nom du paramètre et la valeur par défaut. flake8 est content
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-26 16:33:45 +01:00
e551f8b98d Les lignes ne doivent pas être trop longues
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
2021-01-26 16:32:03 +01:00
5 changed files with 183 additions and 53 deletions

5
.gitignore vendored
View File

@ -1 +1,6 @@
*.pyc
.pytest_cache
.coverage
venv

View File

@ -1,5 +1,6 @@
stages:
- linting
- test
flake8:
@ -7,7 +8,7 @@ flake8:
image: python:3-alpine
before_script:
- pip install flake8 --no-cache-dir
script: flake8 main.py
script: flake8 main.py main_test.py
allow_failure: true
@ -16,5 +17,13 @@ pylint:
image: python:3-alpine
before_script:
- pip install pylint --no-cache-dir
script: pylint main.py
script: pylint main.py main_test.py
allow_failure: true
test:
stage: test
image: python:3-alpine
before_script:
- pip install pytest pytest-cov --no-cache-dir
script: pytest --showlocals --cov=main --cov=main_test --cov-report=term-missing .

6
README.md Normal file
View File

@ -0,0 +1,6 @@
[![pipeline status](https://gitlab.crans.org/ynerant/seminaire-ci/badges/master/pipeline.svg)](https://gitlab.crans.org/ynerant/seminaire-ci/-/commits/master)
[![coverage report](https://gitlab.crans.org/ynerant/seminaire-ci/badges/master/coverage.svg)](https://gitlab.crans.org/ynerant/seminaire-ci/-/commits/master)
# Séminaire intégration continue
Ce dépôt contient le script utilisé lors du séminaire Crans du 11 février 2021, ainsi que les slides.

123
main.py Normal file → Executable file
View File

@ -1,99 +1,120 @@
#!/usr/bin/env python
#!/usr/bin/env python3
"""
Ce script est utilisé en guise d'appui pour le séminaire Crans d'introduction
à l'intégration continue.
Le dépôt est présent sur https://gitlab.crans.org/ynerant/seminaire-ci.git
Plus d'informations sur les séminaires : https://www.crans.org/fr/seminaire/
"""
from random import choice
import sys
def main():
"""
Fonction principale, qui va attendre les instructions de l'utilisateur.
"""
print("Bienvenue dans le chatbot du séminaire de l'intégration continue !")
print("Veuillez taper une commande. Tapez \"help\" pour afficher l'aide.")
print("Veuillez taper une commande. Tapez \"aide\" pour afficher l'aide.")
while True:
command = input("> ")
args = command.split(" ")
print(globals()[args[0]](*args[1:]))
print(commande(args[0], *args[1:]))
def help():
def commande(name: str, *args):
"""
Exécute la commande `name` avec les arguments donnés.
"""
return globals()[name](*args)
def aide():
"""
Affiche l'aide
"""
print("help\t\tAffiche l'aide")
print("seminaire\tLance le séminaire")
print("blague\t\tRaconte une blague")
print("calcul\t\tVérifie une opération arithmétique. Par exemple, check(1, 2, 3, '+') renvoie True")
print("tri\t\tTrie une liste d'entiers.")
print("quit\t\tQuitte le programme")
return "aide\t\tAffiche l'aide\n" \
"seminaire\tLance le séminaire\n" \
"blague\t\tRaconte une blague\n" \
"calcul\t\tVérifie une opération arithmétique. " \
"Par exemple, check(1, 2, 3, '+') renvoie True\n" \
"tri\t\tTrie une liste d'entiers.\n" \
"stop\t\tQuitte le programme"
def seminaire():
"""
Affiche les slides du séminaire.
"""
print("\x4c\x61\x69\x73\x73\x65\x20\x74\x6f\x6d\x62\x65\x72\x2c\x20\x74\x6f\x6e\x20\x74\x72\x75\x63\x20\x65\x73\x74\x20\x74\x72\x6f\x70\x20\x62\x65\x75\x67\x75\xe9\x2c\x20\x74\x75\x20\x64\x65\x76\x72\x61\x69\x73\x20\x70\x61\x73\x73\x65\x72\x20\x64\x75\x20\x74\x65\x6d\x70\x73\x20\xe0\x20\xe9\x63\x72\x69\x72\x65\x20\x64\x65\x73\x20\x74\x65\x73\x74\x73\x20\x65\x74\x20\x66\x61\x69\x72\x65\x20\x64\xe9\x66\x69\x6c\x65\x72\x20\x74\x65\x73\x20\x73\x6c\x69\x64\x65\x73")
return "\x4c\x61\x69\x73\x73\x65\x20\x74\x6f\x6d\x62\x65" \
"\x72\x2c\x20\x74\x6f\x6e\x20\x74\x72\x75\x63\x20" \
"\x65\x73\x74\x20\x74\x72\x6f\x70\x20\x62\x65\x75" \
"\x67\x75\xe9\x2c\x20\x74\x75\x20\x64\x65\x76\x72" \
"\x61\x69\x73\x20\x70\x61\x73\x73\x65\x72\x20\x64" \
"\x75\x20\x74\x65\x6d\x70\x73\x20\xe0\x20\xe9\x63" \
"\x72\x69\x72\x65\x20\x64\x65\x73\x20\x74\x65\x73" \
"\x74\x73\x20\x65\x74\x20\x66\x61\x69\x72\x65\x20" \
"\x64\xe9\x66\x69\x6c\x65\x72\x20\x74\x65\x73\x20" \
"\x73\x6c\x69\x64\x65\x73"
def blague():
"""
Renvoie une blague aléatoire.
"""
return choice(["Je vais vous raconter une blague sur, mais vous ne l'aurez peut-être pas.", "Connaissez-vous la différence entre la théroie et la pratique ? Il n'y en a pas, en théorie."])
return choice(
["Je vais vous raconter une blague sur UDP, mais vous "
"ne l'aurez peut-être pas.",
"Connaissez-vous la différence entre la théorie "
"et la pratique ? Il n'y en a pas, en théorie."])
def calcul(a, b, c, operation = '+'):
def calcul(left: int, right: int, res: int, operation='+'):
"""
Vérifie si a operation b == c, où a, b et c sont des entiers.
Vérifie si left operation b == c, où a, b et c sont des entiers.
L'opération peut être +, -, *, /, &, |, ^, % ou l'un de ses alias anglais.
"""
if operation == '+':
result = a + b
if operation == 'sum':
result = a + b
if operation == 'add':
result = a + b
if operation == '-':
result = a - b
if operation == 'sub':
result = a - b
if operation == '*':
result = a * b
if operation == 'mul':
result = a * b
if operation == 'prod':
result = a * b
if operation == '/':
result = a / b
if operation == 'div':
result = a / b
if operation == '&':
result = a & b
if operation == 'and':
result = a & b
if operation == '|':
result = a | b
if operation == 'or':
result = a | b
if operation == '^':
result = a ^ b
if operation == 'xor':
result = a ^ b
left = int(left)
right = int(right)
res = int(res)
if operation in ['+', 'add', 'sum']:
result = left + right
elif operation in ['-', 'sub']:
result = left - right
elif operation in ['*', 'mul', 'prod']:
result = left * right
elif operation in ['/', 'div']:
result = left / right
elif operation in ['&', 'and']:
result = left & right
elif operation in ['|', 'or']:
result = left | right
elif operation in ['^', 'xor']:
result = left ^ right
else:
result = a % b
return c == result
result = left % right
return res == result
def tri(*args):
"""
Trie les éléments donnés en argument.
"""
return sorted(args)
return sorted(int(number) for number in args)
def quit(exit_code: int = 0):
def stop(exit_code: int = 0):
"""
Stoppe le programme avec le code d'erreur donné.
"""
print("Fin du programme, merci !")
exit(exit_code)
sys.exit(exit_code)
if __name__ == '__main__':

89
main_test.py Executable file
View File

@ -0,0 +1,89 @@
#!/usr/bin/env python3
"""
Exécution des tests du script.
"""
from random import randint, seed, shuffle
import unittest
import main
class TestMain(unittest.TestCase):
"""
Cette classe permet d'executer l'ensemble des scripts
"""
def test_aide(self):
"""
On essaie d'afficher l'aide,
et on vérifie si ça affiche la bonne chose.
"""
res = main.commande("aide")
lines = res.split("\n")
self.assertEqual(len(lines), 6)
self.assertTrue(lines[0].startswith("aide"))
self.assertTrue(lines[1].startswith("seminaire"))
self.assertTrue(lines[2].startswith("blague"))
self.assertTrue(lines[3].startswith("calcul"))
self.assertTrue(lines[4].startswith("tri"))
self.assertTrue(lines[5].startswith("stop"))
def test_seminaire(self):
"""
Test de l'affichage du "séminaire".
"""
res = main.commande("seminaire")
self.assertEqual(len(res), 114)
def test_blague(self):
"""
On teste les blagues, et on vérifie si
elles fonctionnent bien.
"""
seed(1)
res = main.commande("blague")
self.assertEqual(res, "Je vais vous raconter une blague sur UDP, "
"mais vous ne l'aurez peut-être pas.")
seed(5)
res = main.commande("blague")
self.assertEqual(res, "Connaissez-vous la différence entre la "
"théorie et la pratique ? "
"Il n'y en a pas, en théorie.")
def test_calcul(self):
"""
On vérifie que certains calculs basiques, puis aléatoires,
marchent bien.
"""
self.assertTrue(main.commande("calcul", 1, 2, 3))
self.assertFalse(main.commande("calcul", 1, 2, 2, '+'))
self.assertTrue(main.commande("calcul", 1, 2, 2, '*'))
self.assertTrue(main.commande("calcul", 42, 3, 14, 'div'))
self.assertTrue(main.commande("calcul", 16777215, 42, 42, 'and'))
self.assertTrue(main.commande("calcul", 16777213, 42, 16777215, 'or'))
self.assertFalse(main.commande("calcul", 15, 20, 35, 'xor'))
self.assertTrue(main.commande("calcul", 15, 20, 27, '^'))
self.assertTrue(main.commande("calcul", 100, 76, 24, 'unknown'))
left, right = randint(0, 0x7FFFFFFF), randint(0, 0x7FFFFFFF)
self.assertTrue(main.commande("calcul", left, right,
left - right, "-"))
def test_tri(self):
"""
À partir d'une liste donnée, on trie la liste
et on vérifie qu'elle est bien triée.
"""
my_list = ["23", "16", "234567", "-4"]
shuffle(my_list)
sorted_list = [-4, 16, 23, 234567]
self.assertEqual(main.commande("tri", *my_list), sorted_list)
def test_stop(self):
"""
On vérifie que le programme s'arrête bien.
"""
self.assertRaises(SystemExit, main.commande, "stop", 0)