{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["# 1A.soft - Tests unitaires, setup et ing\u00e9ni\u00e9rie logicielle\n", "\n", "On v\u00e9rifie toujours qu'un code fonctionne quand on l'\u00e9crit mais cela ne veut pas dire qu'il continuera \u00e0 fonctionner \u00e0 l'avenir. La robustesse d'un code vient de tout ce qu'on fait autour pour s'assurer qu'il continue d'ex\u00e9cuter correctement."]}, {"cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [{"data": {"text/html": ["
run previous cell, wait for 2 seconds
\n", ""], "text/plain": [""]}, "execution_count": 2, "metadata": {}, "output_type": "execute_result"}], "source": ["from jyquickhelper import add_notebook_menu\n", "add_notebook_menu()"]}, {"cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": ["from pyensae.graphhelper import draw_diagram"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Petite histoire\n", "\n", "Supposons que vous ayez impl\u00e9ment\u00e9 trois fonctions qui d\u00e9pendent les unes des autres. la fonction ``f3`` utilise les fonctions ``f1`` et ``f2``."]}, {"cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [{"data": {"image/png": "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\n", "text/plain": [""]}, "execution_count": 4, "metadata": {}, "output_type": "execute_result"}], "source": ["draw_diagram(\"blockdiag { f0 -> f1 -> f3; f2 -> f3;}\")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Six mois plus tard, vous cr\u00e9ez une fonction ``f5`` qui appelle une fonction ``f4`` et la fonction ``f2``."]}, {"cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [{"data": {"image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAEYCAIAAABDctDHAAAfcUlEQVR4nO3dX2wc1aHH8XPm387serNrJ7mAaLn0iSuBUCWqSpC2QBAiMaC06gNV3qqrttwkQqEpD0WpCJD00iRSqwpC+1AhkIoIVC20JAV0JYTUJ6oqah8KKkqClIc6Ns069jq73jkz5z6cZLQ1hTpeZ8+e8fejKLKd/jme/c385syc3ZFaawEAAIbLsz0AAADWIgoYAAALKGAAACyggAEAsIACBgDAAgoYAAALKGAAACyggAEAsIACBgDAAgoYAAALKGAAACyggAEAsIACBgDAAgoYAAALKGAAACyggAEAsIACBgDAAgoYAAALKGAAACyggAEAsIACBgDAAgoYAAALKGAAACyggAEAsIACBgDAAgoYAAALKGAAACyggAEAsIACBgDAAgoYAAALKGAAACyggAEAsIACBgDAAgoYAAALKGAAACyggAEAsCCwPYBBKaV837c9irUry7IgcDhF5Mcu8oNBuJ4fqbW2PQYAANYcV88dtNZSyk6nc+TIke3bt8dxzJnEkEkpu93uiy++uGPHjiRJzCtie1DLRX6sIz8YhNP5Kbg6Azabe3Z2dnx8/Oqrrw6CwNFfxF1SSqXU1NRUq9VqNptu7QDkxzryg0E4nZ+CqzNgQ2t93XXXvf322+Pj4+wAQyalbLVad955Z57ntseyQuTHIvKDQZQgP6IEBZxl2YYNG9atW2d7LGtREARZlpkdwByA3DoJJT92kR8MwvX8CNcL2EjTVGvt6CUIR5mtnaapECLLMnFpBzDceiHIz/CRHwyiNPkpQwFLKc0Wd2i7l0Cx2Xu9nlKqeD+Ac68C+bGC/GAQ5chPGQoYFmmtO51Ot9s13xbvyXNrN4At5AeDcD0/FDAGorWen59fWFjwfd+ck5ovbI8LbiA/GITr+XG7gFl5aJ3WutVqNRqNOI593/c8z/M8VxZEkB/ryA8G4XR+RDkK2IkNXUpSSq31+fPn5+fntdZRFIVhaHYD20NbFvJjF/nBIFzPj+BhDBiQ2QHa7Xa3203TNMsysyLU9rjgBvKDQbieHwoYA9FaLywsdDqdNE2VUnmeO5R+WEd+MAjX8+N2Abu1rUtJa724uNjr9fpPP115XVwZZ4mRHwzC6fwI1wsYo8C8D8+cezoUfYwI8oNBOJ0fChgrZ5af6H9me1BwBvnBIEqQH7dXQTtKa62UEkKYBXvmW8/zHH2yd57n/bdeRnMf0Frnee7oFl5iSX7EpWOQQ4s/+5GfIeP4MzooYAuklGEYmq+11sW3eZ47egwd8dNPpVQQBL7vO11Uhf78iEu/ndNvhiE/w/RJxx93jXh+PoXbSXKOSUm73X7sscd27tx57NgxKWWv19u1a9frr7/ueZ75YHG3jHLuzdhmZ2e3bdv2xhtvSCk9zzOfnm97aCuxJD/Hjx8XQgRBMDs7+4c//EEI4eKj2Ub5tSh9fqSUMzMzu3bt+s1vfpOmKfkZMgp4qJRSUspDhw4dPXo0SRKt9ezs7Pbt24UQP/jBD44fP+77vosdXKyAGE2VSuX111/funXrli1b3nrrrTAMPc9TSmnXdt2P52dxcfHIkSPbtm17+eWXxaUnwziH/AzHkvx4nnfu3LlbbrlFCLF///4nnniieMSQW5x7IQoU8FBprU+fPv3BBx9s3rx5//7999133xNPPFGpVJ5++ul9+/Y9+eSTnU5HuJanIAgqlUocx3EcJ0mSJIk5QskRYIZRqVQajYaU8s0335ycnHz88cf/8Y9/BEEQRZFbm7o/PwcOHLj33nullJOTk5/97GfdvS5KfoZmSX62bNly+PDhycnJp59++o477jh79qx0+UaGi7gHPFRZlh07duzMmTMffvjhM8888/DDD/d6vfXr16dpunnz5u985zsXLlwwMxvbI10urfXMzMyZM2cWFxfn5uYajYY5gI7Ugo52u20uGwZBoJTat2/fkSNHHnzwwQceeCAMQ4e2dn9+nn322W9961txHF9//fUbNmxwceIiRiY/Ukqtte/7lUrlwoUL5tviX0ucn71792qt5+bmZmdn169fb3uAaw4FPFRhGO7atev06dNCiD179pgfKqXCMPzoo4+iKHLuDDTP8/fee6/VatXr9Xq9niRJFEWj9nGs3W7XLPvMssxc5J+enj5w4MBNN90Ux7FD973687N7927z9kdzOdS55BgjlZ9Wq/X+++/feuutS5ZDljg/5qzi8OHDL7300qlTp4QQI3XqXHoU8FBprZVS5jqzWVpprnFprcMwdPEGnu/7d91114033njttddec801ExMTxSM5R8rBgwfNJCbLsomJiYceemjPnj1a6927dzt0xFmSH+3+wwBGKj8zMzOvvPLK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\n", "text/plain": [""]}, "execution_count": 5, "metadata": {}, "output_type": "execute_result"}], "source": ["draw_diagram('blockdiag { f0 -> f1 -> f3; f2 -> f3; f2 -> f5 [color=\"red\"]; f4 -> f5 [color=\"red\"]; }')"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Ah au fait, ce faisant, vous modifiez la fonction ``f2`` et vous avez un peu oubli\u00e9 ce que faisait la fonction ``f3``... Bref, vous ne savez pas si la fonction ``f3`` sera impact\u00e9e par la modification introduite dans la fonction ``f2`` ? C'est ce type de probl\u00e8me qu'on rencontre tous les jours quand on \u00e9crit un logiciel \u00e0 plusieurs et sur une longue dur\u00e9e. Ce notebook pr\u00e9sente les briques classiques pour s'assurer de la robustesse d'un logiciel.\n", "\n", "* les tests unitaires\n", "* un logiciel de suivi de source\n", "* calcul de couverture\n", "* l'int\u00e9gration continue\n", "* \u00e9crire un setup\n", "* \u00e9crire la documentation\n", "* publier sur [PyPi](https://pypi.python.org/pypi)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Ecrire une fonction\n", "\n", "N'importe quel fonction qui fait un calcul, par exemple une fonction qui r\u00e9soud une \u00e9quation du second degr\u00e9."]}, {"cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": ["def solve_polynom(a, b, c):\n", " # ....\n", " return None"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Ecrire un test unitaire\n", "\n", "Un [test unitaire](https://fr.wikipedia.org/wiki/Test_unitaire) est une fonction qui s'assure qu'une autre fonction retourne bien le r\u00e9sultat souhait\u00e9. Le plus simple est d'utiliser le module standard [unittest](https://docs.python.org/3/library/unittest.html) et de quitter les notebooks pour utiliser des fichiers. Parmi les autres alternatives : [pytest](https://docs.pytest.org/en/latest/) et [nose](http://nose.readthedocs.io/en/latest/)."]}, {"cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## Couverture ou coverage\n", "\n", "La [couverture de code](https://fr.wikipedia.org/wiki/Couverture_de_code) est l'ensemble des lignes ex\u00e9cut\u00e9es par les tests unitaires. Cela ne signifie pas toujours qu'elles soient correctes mais seulement qu'elles ont \u00e9t\u00e9 ex\u00e9cut\u00e9es une ou plusieurs sans provoquer d'erreur. Le module le plus simple est [coverage](https://coverage.readthedocs.io/en/coverage-4.4.1/). Il produit des rapports de ce type : [mlstatpy/coverage](https://codecov.io/github/sdpython/mlstatpy?branch=master)."]}, {"cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## Cr\u00e9er un compte GitHub\n", "\n", "[GitHub](https://github.com/) est un site qui contient la majorit\u00e9 des codes des projets open-source. Il faut cr\u00e9er un compte si vous n'en avez pas, c'est gratuit pour les projets open souce, puis cr\u00e9er un projet et enfin y ins\u00e9rer votre projet. Votre ordinateur a besoin de :\n", "\n", "* [git](https://git-scm.com/)\n", "* [GitHub destkop](https://desktop.github.com/)\n", "\n", "Vous pouvez lire [GitHub Pour les Nuls : Pas de Panique, Lancez-Vous ! (Premi\u00e8re Partie)](https://www.christopheducamp.com/2013/12/15/github-pour-nuls-partie-1/) et bien s\u00fbr faire plein de recherches internet.\n", "\n", "**Note**\n", "\n", "Tout ce que vous mettez sur GitHub pour un projet open-source est en acc\u00e8s libre. Veillez \u00e0 ne rien mettre de personnel. Un compte GitHub fait aussi partie des choses qu'un recruteur ira regarder en premier."]}, {"cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## Int\u00e9gration continue\n", "\n", "L'[int\u00e9gration continue](https://fr.wikipedia.org/wiki/Int%C3%A9gration_continue) a pour objectif de r\u00e9duire le temps entre une modification et sa mise en production. Typiquement, un d\u00e9veloppeur fait une modification, une machine ex\u00e9cute tous les tests unitaires. On en d\u00e9duit que le logiciel fonctionne sous tous les angles, on peut sans crainte le mettre \u00e0 disposition des utilisateurs. Si je r\u00e9sume, l'int\u00e9gration continue consiste \u00e0 lancer une batterie de tests d\u00e8s qu'une modification est d\u00e9tect\u00e9e. Si tout fonctionne, le logiciel est construit et pr\u00eat \u00e0 \u00eatre partag\u00e9 ou d\u00e9ploy\u00e9 si c'est un site web.\n", "\n", "\n", "L\u00e0 encore pour des projets open-source, il est possible de trouver des sites qui offre ce service gratuitement :\n", "\n", "* [travis](https://travis-ci.com/) - [Linux](https://fr.wikipedia.org/wiki/Linux)\n", "* [appveyor](https://www.appveyor.com/) - [Windows](https://fr.wikipedia.org/wiki/Microsoft_Windows) - 1 job \u00e0 la fois, pas plus d'une heure.\n", "* [circle-ci](https://circleci.com/) - [Linux](https://fr.wikipedia.org/wiki/Linux) et [Mac OSX](https://fr.wikipedia.org/wiki/MacOS) (payant)\n", "* [GitLab-ci](https://about.gitlab.com/features/gitlab-ci-cd/)\n", "\n", "A part [GitLab-ci](https://about.gitlab.com/features/gitlab-ci-cd/), ces trois services font tourner les tests unitaires sur des machines h\u00e9berg\u00e9s par chacun des soci\u00e9t\u00e9s. Il faut s'enregistrer sur le site, d\u00e9finir un fichier [.travis.yml](https://docs.travis-ci.com/user/customizing-the-build), [.appveyor.yml](https://www.appveyor.com/docs/appveyor-yml/) ou [circle.yml](https://circleci.com/docs/1.0/config-sample/) puis activer le projet sur le site correspondant. Quelques exemples sont disponibles \u00e0 [pyquickhelper](https://github.com/sdpython/pyquickhelper) ou [scikit-learn](https://github.com/scikit-learn/scikit-learn). Le fichier doit \u00eatre ajout\u00e9 au projet sur *GitHub* et activ\u00e9 sur le site d'int\u00e9gration continue choisi. La moindre modification d\u00e9clenchera un nouveau *build*.permet\n", "\n", "La plupart des sites permettent l'insertion de [badge](https://docs.travis-ci.com/user/status-images/) de fa\u00e7on \u00e0 signifier que le *build* fonctionne."]}, {"cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [{"data": {"image/png": "iVBORw0KGgoAAAANSUhEUgAAAEwAAAAUCAYAAAAnStuxAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAAA81JREFUWIXtWM9LMlsYfsY5DubItTJT1EWbFnGtCEILooIWrcqkiFxkbeJbhd8yqD+gVh8tKi6zaVEQQrXKaFdxIaMWcm83QmpnP6jATE3DceauErUZ9YvL5yzuAy+c877nPOeZZ+YVZ6ixsbEahmF+qNVqD4DfoAAMDAxUW0IBMpmMGI1G/wmHwz2EYZgfhJBvoihWW1cOStICAIQQymg02gVB+JPQNO1RmkCl6flAXV3d70QURUW0YT6UahghhCJKFKdETR9QiaIIudjY2JCtVRqlOP4L/l8dJQ0D8CXSzc3Niji+yl/NKNuS5epS6Ovrg8ViqYhDqvaVM38Vyhrm8XgwODiISCSC5eVlPD4+AgC2trYwMTGRW5c/Pzo6Kqh9nNHY2AifzwebzYaDg4OCWj6kchqNBr29vbBYLIjH4zg+PsbT0xMAYGZmBsFgEK2trWBZFhzHSeZ0Oh36+/vR0NCA5+dnHB4eIpFIyHJIoWxLJpNJuN1unJ6eYnJyUrad8udyY6/Xi5OTE7jdbqTT6U8cpaKrqwvn5+eYm5vD7u4uenp6Cs7QaDRYWlrC7OysbK67uxtXV1dYWFhAOByG0+ksyfGlltze3gbLstjZ2cH6+nrB3S/eK1f7GLe0tGBxcREsy8Lv92N8fLziJ8xqtaK5uRmjo6OfbggABAIBmEwmWK3WXL44Zzab4ff70dTUhGAwCIfDUZajGGUN02q1SKVS0Gq1BRcjCAIoioIgCGAYpiLDSvHlQ07T/Pw8YrFYbm6323NjvV4PmqYL9hbnRFFEfX09eJ6HwWD4ZLoURzHKtuTQ0BA0Gg1cLhdCoVCudnd3B4fDAYZhMDw8nBNUqiVDoVABX36tXFxeXsLr9aKzsxNOpxM+n6/gDJVK9Ul7ce7m5gbt7e0ghKCjowPX19cl10tFWcMEQQDHcbDb7VhbW8vVVlZWMD09DY7jkEqlKjJsdXUVbW1t4DgOPM//lGH7+/tIp9PweDxwuVw4OzuT/T2Vy+3t7cFoNGJqagoGgwGBQKDkeqmg3G637PP38PAAlmXx9vYGQghqa2tB0zQA4P39Ha+vrxAEATqdDvF4HGazObdPapzNZvHy8gKe56HVapFMJnO1fEh9rchms7i/v0c8HgdN0zCZTNDr9QCAi4uLgvaUy2UyGUQiEaRSKdTU1MBms0GtVsuulwI1MjKiuD89Svu8k4//3yV/EkQUxQQAXbWF5EOphvE8LxKVSrWZzWa/VVtMPpRqWCKR+FsVjUa/0zT9B0VRr9UWpFTwPC/GYrG/bm9ve/8FR/MRqjuhxXgAAAAASUVORK5CYII=\n", "text/plain": [""]}, "execution_count": 10, "metadata": {}, "output_type": "execute_result"}], "source": ["from IPython.display import Image\n", "try:\n", " im = Image(\"https://travis-ci.com/sdpython/ensae_teaching_cs.png\")\n", "except TimeoutError:\n", " im = None\n", "im"]}, {"cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [{"data": {"image/svg+xml": ["\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " codecov\n", " codecov\n", " 75%\n", " 75%\n", " \n", " \n", " \n", " \n", ""], "text/plain": [""]}, "execution_count": 11, "metadata": {}, "output_type": "execute_result"}], "source": ["from IPython.display import SVG\n", "try:\n", " im = SVG(\"https://codecov.io/github/sdpython/ensae_teaching_cs/coverage.svg\")\n", "except TimeoutError:\n", " im = None\n", "im"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Il y a des badges un peu pour tout."]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Ecrire un setup\n", "\n", "Le fichier ``setup.py`` d\u00e9termin la fa\u00e7on dont le module python doit \u00eatre install\u00e9 pour un utilisateur qui ne l'a pas d\u00e9velopp\u00e9. Comment construire un setup : [setup](https://docs.python.org/3.6/distutils/setupscript.html)."]}, {"cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## Ecrire la documentation\n", "\n", "L'outil est le plus utilis\u00e9 est [sphinx](http://www.sphinx-doc.org/en/stable/). Saurez-vous l'utiliser ?"]}, {"cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## Derni\u00e8re \u00e9tape : PyPi\n", "\n", "[PyPi](https://pypi.python.org/pypi) est un serveur qui permet de mettre un module \u00e0 la disposition de tout le monde. Il suffit d'uploader le module... [Packaging and Distributing Projects](https://packaging.python.org/tutorials/distributing-packages/) ou [How to submit a package to PyPI](http://peterdowns.com/posts/first-time-with-pypi.html). PyPi permet aussi l'insertion de badge."]}, {"cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [{"data": {"image/svg+xml": ["\n", "\n", "\n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " pypi package\n", " \n", " \n", " pypi package\n", " \n", " \n", " 0.9.2894\n", " \n", " \n", " 0.9.2894\n", " \n", " \n", ""], "text/plain": [""]}, "execution_count": 14, "metadata": {}, "output_type": "execute_result"}], "source": ["try:\n", " im = SVG(\"https://badge.fury.io/py/ensae_teaching_cs.svg\")\n", "except TimeoutError:\n", " im = None\n", "im"]}, {"cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": []}], "metadata": {"kernelspec": {"display_name": "Python 3", "language": "python", "name": "python3"}, "language_info": {"codemirror_mode": {"name": "ipython", "version": 3}, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.2"}}, "nbformat": 4, "nbformat_minor": 2}