class: center, middle # Premiers pas pour assurer la qualité de vos applications Python ## [Arthur Vuillard](mailto:arthur@hashbang.fr) PyConFr 16/10/2016 --- # À propos de moi ??? --- count: false class: center # À propos de moi Développeur Pythoniste ??? Je suis un développeur Python --- count: false class: center # À propos de moi Développeur Pythoniste AdminSys Linuxien ??? et un administrateur système linux Est ce que je suis un devops ? --- count: false class: center # À propos de moi Développeur Pythoniste AdminSys Linuxien ![Logo d'Hashbang](logo hashbang.png) | | :-------------------------------------:|:------:|:------: ??? le créateur d'hashbang développement et maintenance d'applications webs pour les entrepreneures/entrepreneuses et PMEs remporte beaucoup de succès et qui a déjà au moins un salarié ! --- count: false class: center # À propos de moi Développeur Pythoniste AdminSys Linuxien ![Logo d'Hashbang](logo hashbang.png) | ![Logo de localghost](logo_Localghost_small.png) | :-------------------------------------:|:------------------------------------------------:|:------: ??? membre de Localghost regroupement d'éditeurs et d'intégrateurs autour de meilleures pratiques d'admin sys infogérance de serveurs avec de grands outils --- count: false class: center # À propos de moi Développeur Pythoniste AdminSys Linuxien ![Logo d'Hashbang](logo hashbang.png) | ![Logo de localghost](logo_Localghost_small.png) | ![Logo de l'AFPy](afpy.png) :-------------------------------------:|:------------------------------------------------:|:---------------------------: ??? et je suis aussi Bénévole à l'AFPy association francophone python trésorier organisateur de conférence et de meetup enthousiaste du langage --- Qualité ? ========= ??? De quoi parle-t-on quand on parle de qualité ? --- count: false Qualité ? ========= > la **qualité** est la « manière d'être », bonne ou mauvaise, de quelque chose [Wikipedia](https://fr.wikipedia.org/wiki/Qualit%C3%A9) ??? d'apres wikipedia, la qualité est la manière d'être bonne ou mauvaise de quelque chose on peut aussi parler de la valeur intrinsèque de la chose, c'est à dire les usages remplis par la chose et dont j'ai besoin --- Référentiel =========== ??? pour savoir si notre objet remplis des usages, il faut d'abord les connaitre --- Référentiel =========== définir ses exigences ??? on va donc définir nos exigences c'est à dire qu'on va faire la liste des conditions que doit remplir notre objet --- Référentiel =========== définir ses exigences mesures relatives ??? la qualité utilise la relativité on va chercher à savoir où on se situe par rapport à notre référentiel et pour le savoir, il faut définir des mesures --- Processus ========= ??? dans l'industrie, la qualité est avant tout une gestion des processus de l'entreprise de manière à faire en sorte que la production soit au niveau du référentiel --- count: false Processus ========= .w33.centered-block[ - fabrication ] ??? le processus principal est celui de la fabrication, on va coder un logiciel on a beau être très adroit, on n'est pas à l'abri d'une erreur, d'un outil qui fonctionne mal, d'une faute occasionnelle --- count: false Processus ========= .w33.centered-block[ - fabrication - détection ] ??? il faut donc mettre en place un processus pour détecter cette erreur on parle de controle, c'est juste une vérification on vérifie notre code vis à vis du référentiel défini --- count: false Processus ========= .w33.centered-block[ - fabrication - détection - gestion ] ??? si jamais on trouve une erreur, il faut alors la gérer on ne va pas simplement ignorer l'erreur on a donc un processus de gestion des infractions détectés --- count: false Processus ========= .w33.centered-block[ - fabrication - détection - gestion - mise à jour ] ??? enfin, depuis l'analyse l'ensemble de ces processus, on peut définir de nouvelles règles de qualité auxquelles il faudrait se conformer on a donc un processus pour mettre à jour le référentiel de qualité --- .w50.left[ .center[Dans le code] ===================== ] --- count: false .w50.left[ .center[Dans le code] ===================== - lisibilité ] --- count: false .w50.left[ .center[Dans le code] ===================== - lisibilité - style ] --- count: false .w50.left[ .center[Dans le code] ===================== - lisibilité - style - bonne exécution ] --- count: false .w50.left[ .center[Dans le code] ===================== - lisibilité - style - bonne exécution - bon fonctionnement ] --- count: false .w50.left[ .center[Dans le code] ===================== - lisibilité - style - bonne exécution - bon fonctionnement ] .w50.left[ .center[En python] ================== ] --- count: false .w50.left[ .center[Dans le code] ===================== - lisibilité - style - bonne exécution - bon fonctionnement ] .w50.left[ .center[En python] ================== - compilation ] --- count: false .w50.left[ .center[Dans le code] ===================== - lisibilité - style - bonne exécution - bon fonctionnement ] .w50.left[ .center[En python] ================== - compilation - complexité ] --- count: false .w50.left[ .center[Dans le code] ===================== - lisibilité - style - bonne exécution - bon fonctionnement ] .w50.left[ .center[En python] ================== - compilation - complexité - tests ] --- Howto ===== --- count: false Howto ===== [pytest](http://doc.pytest.org/en/latest/) et ses plugins --- count: false Howto ===== [pytest](http://doc.pytest.org/en/latest/) et ses plugins [spec pep8](https://www.python.org/dev/peps/pep-0008/), [outil pep8](http://pep8.readthedocs.io/), [pytest-pep8](https://pypi.python.org/pypi/pytest-pep8) --- count: false Howto ===== [pytest](http://doc.pytest.org/en/latest/) et ses plugins [spec pep8](https://www.python.org/dev/peps/pep-0008/), [outil pep8](http://pep8.readthedocs.io/), [pytest-pep8](https://pypi.python.org/pypi/pytest-pep8) [isort](https://pypi.python.org/pypi/isort/), [pytest-isort](https://pypi.python.org/pypi/pytest-isort/0.1.0) --- count: false Howto ===== [pytest](http://doc.pytest.org/en/latest/) et ses plugins [spec pep8](https://www.python.org/dev/peps/pep-0008/), [outil pep8](http://pep8.readthedocs.io/), [pytest-pep8](https://pypi.python.org/pypi/pytest-pep8) [isort](https://pypi.python.org/pypi/isort/), [pytest-isort](https://pypi.python.org/pypi/pytest-isort/0.1.0) [mccabe](https://pypi.python.org/pypi/mccabe/), [pytest-mccabe](https://pypi.python.org/pypi/pytest-mccabe/0.1) --- Howto ===== --- count: false Howto ===== ```shell $ pip install pytest pytest-pep8 pytest-isort pytest-mccabe ``` --- count: false Howto ===== ```shell $ pip install pytest pytest-pep8 pytest-isort pytest-mccabe $ py.test # exécute les tests ``` --- count: false Howto ===== ```shell $ pip install pytest pytest-pep8 pytest-isort pytest-mccabe $ py.test # exécute les tests $ py.test --pep8 # tests + style ``` --- count: false Howto ===== ```shell $ pip install pytest pytest-pep8 pytest-isort pytest-mccabe $ py.test # exécute les tests $ py.test --pep8 # tests + style $ py.test --isort # tests + ordre des imports ``` --- count: false Howto ===== ```shell $ pip install pytest pytest-pep8 pytest-isort pytest-mccabe $ py.test # exécute les tests $ py.test --pep8 # tests + style $ py.test --isort # tests + ordre des imports $ py.test --mccabe # tests + complexité ``` --- class: middle, center # Demo --- Exécution ========= --- count: false Exécution ========= - dans l'éditeur (vim + [syntastic](https://github.com/scrooloose/syntastic)) --- count: false Exécution ========= - dans l'éditeur (vim + [syntastic](https://github.com/scrooloose/syntastic)) - en codant en TDD (pytest) --- count: false Exécution ========= - dans l'éditeur (vim + [syntastic](https://github.com/scrooloose/syntastic)) - en codant en TDD (pytest) - avec gestionnaire de code (py.test dans un hook) --- count: false Exécution ========= - dans l'éditeur (vim + [syntastic](https://github.com/scrooloose/syntastic)) - en codant en TDD (pytest) - avec gestionnaire de code (py.test dans un hook) - serveur d'intégration continue ([gitlab ci](https://about.gitlab.com/gitlab-ci/) ou [drone](https://drone.io/)) --- Exemple hook git ================ ```shell $ cat .git/hooks/pre-commit #!/bin/bash set -ex py.test --pep8 --isort --mccabe ``` --- Exemple gitlab ci ================= ```shell $ cat .gitlab-ci.yml ``` ```yaml image: python:3.5 qa: script: - pip install pytest pytest-pep8 pytest-isort pytest-mccabe - py.test --pep8 --isort --mccabe ``` --- Exemple Drone Ci ================ ```shell $ cat .drone.yml ``` ```yaml build: image: python:3.4 commands: - pip install pytest pytest-pep8 pytest-isort pytest-mccabe - py.test --pep8 --isort --mccabe ``` --- Commencer ========= --- count: false Commencer ========= .w66.centered-block[ - détecter ] --- count: false Commencer ========= .w66.centered-block[ - détecter - activer un plugin à la fois ] --- count: false Commencer ========= .w66.centered-block[ - détecter - activer un plugin à la fois - ignorer certains infractions ] --- count: false Commencer ========= .w66.centered-block[ - détecter - activer un plugin à la fois - ignorer certains infractions - utiliser [autopep8](https://pypi.python.org/pypi/autopep8) ] --- count: false Commencer ========= .w66.centered-block[ - détecter - activer un plugin à la fois - ignorer certains infractions - utiliser [autopep8](https://pypi.python.org/pypi/autopep8) - utiliser [isort](https://pypi.python.org/pypi/isort) ] --- count: false Commencer ========= .w66.centered-block[ - détecter - activer un plugin à la fois - ignorer certains infractions - utiliser [autopep8](https://pypi.python.org/pypi/autopep8) - utiliser [isort](https://pypi.python.org/pypi/isort) - utiliser [diff_cover](https://pypi.python.org/pypi/diff_cover) ] --- count: false Commencer ========= .w66.centered-block[ - détecter - activer un plugin à la fois - ignorer certains infractions - utiliser [autopep8](https://pypi.python.org/pypi/autopep8) - utiliser [isort](https://pypi.python.org/pypi/isort) - utiliser [diff_cover](https://pypi.python.org/pypi/diff_cover) - écrire des tests ] --- class: middle # Des questions ? ## .center[[arthur@hashbang.fr](mailto:arthur@hashbang.fr)]