{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Les tests en python\n",
    "\n",
    "(code sous licence creative commun CC BY-NC-SA BY Alexis Dendiével)"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {
    "raw_mimetype": "text/restructuredtext"
   },
   "source": [
    ":download:`Télécharger le pdf <./05-tests.pdf>`\n",
    "\n",
    ":download:`Télécharger le notebook <./05-tests.ipynb>`\n",
    "\n",
    ":download:`Lancer le notebook sur binder (lent) <https://mybinder.org/v2/gl/pyspc%2Fpyspc/master?filepath=05-bases%2F05-tests.ipynb>`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Les tests constituent, avec les boucles, l'une des bases fondamentales de la programmation.\n",
    "Régulièrement en effet, nous devons faire des tests afin de dérouler l'algorithme.\n",
    "\n",
    "\n",
    "- Si telle condition est vrai \n",
    "    alors faire ceci \n",
    "- sinon \n",
    "    faire cela\n",
    "\n",
    "## if / else"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "n est inférieur ou égal à 3\n"
     ]
    }
   ],
   "source": [
    "n = 2\n",
    "if n > 3:\n",
    "    print(\"n est supérieur à 3\")\n",
    "else:\n",
    "    print(\"n est inférieur ou égal à 3\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Un exemple lié à la classification périodique des éléments:\n",
    "    On se propose de savoir si l'élément, défini par son numéro atomique, apparient ou non aux trois premières linges de la classification"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Elément de numéro atomique 3 :\n",
      "  fait partie des trois premières lignes de la classification\n",
      "Elément de numéro atomique 5 :\n",
      "  fait partie des trois premières lignes de la classification\n"
     ]
    }
   ],
   "source": [
    "# premier test\n",
    "\n",
    "def ligne(Z):\n",
    "    \"\"\"\n",
    "    Dit si un élément fait partie des trois premières lignes du tableau périodique.\n",
    "    \n",
    "    :param Z: numéro atomique\n",
    "    \"\"\"\n",
    "    # test vérifiant si l'élément fait partie des trois premières lignes\n",
    "    print(\"Elément de numéro atomique\", Z, \":\")\n",
    "    if Z<= 18:\n",
    "        print(\"  fait partie des trois premières lignes de la classification\")\n",
    "    else:\n",
    "        print(\"  ne fait pas partie des trois premières lignes de la classification\")\n",
    "        \n",
    "ligne(3)\n",
    "ligne(5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "La syntaxe traduit l'algorythme en langage python:\n",
    "\n",
    "prenons un exemple plus conséquent afin de voir l'utilité du test if en contexte. Il s'agit d'un programme calculant les forces électromagnétiques et gravitationnelles, et les comparant. A la lecture du programme, vous trouverez deux tests:\n",
    "- le premier donne le côté attractif ou répulsif de la force électromagnétique\n",
    "- le second compare les deux forces afin de définir la prédominance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Comparaison des forces de gravitation et électromagnétiques : \n",
      "  - objet 1 : masse 5.00e-07 kg, charge 6.40e-17 C\n",
      "  - objet 2 : masse 5.00e-07 kg, charge 6.40e-17 C\n",
      "\n",
      "Résultat:\n",
      "\n",
      "- la valeur de la force de gravitation est: 1.85e-12  N\n",
      "    cette force est attractive\n",
      "- la valeur de la force électromagnétique est: 4.10e-12  N\n",
      "    cette force est répulsive\n",
      "- la force électromagnétique est prépondérante\n",
      "- le rapport de ces deux forces est: 2.21e+00\n"
     ]
    }
   ],
   "source": [
    "# comparaison des forces de gravitation et électromagnétique\n",
    "# entre deux masses m1 et m2 de charge q1 et q2 séparées d'une distance d\n",
    "\n",
    "def comparaison_forces(m1, e1, m2, e2, d):\n",
    "    \"\"\"\n",
    "    Comparaison des forces de gravitation et électromagnétique entre deux\n",
    "    masses m1 et m2 (en kg), de charge q1 et q2 (en multiple de e, la\n",
    "    charge élémentaire), séparées d'une distance d (en mètres)\n",
    "    \n",
    "    :param m1: masse m1 (en kg)\n",
    "    :param e1: charge q1 (en multiple de e)\n",
    "    :param m2: masse m2 (en kg)\n",
    "    :param e2: charge q2 (en multiple de e)\n",
    "    :param d: distance séparant m1 et m2 (en mètres)  \n",
    "        \"\"\"\n",
    "    # les constantes utilisées\n",
    "    G = 6.67e-11\n",
    "    k = 9.0e9\n",
    "    e = 1.6e-19\n",
    "\n",
    "    # présentation du programme\n",
    "    print(\"Comparaison des forces de gravitation et électromagnétiques : \")\n",
    "    print(\"  - objet 1 : masse {0:.2e} kg, charge {1:.2e} C\".format(m1, e1*e))\n",
    "    print(\"  - objet 2 : masse {0:.2e} kg, charge {1:.2e} C\".format(m2, e2*e))\n",
    "\n",
    "    # caractère attractif ou répulsif\n",
    "    if e1*e2 > 0:\n",
    "        caractere = \"répulsive\"\n",
    "    else:\n",
    "        caractere = \"attractif\"\n",
    "\n",
    "    # calcul des forces\n",
    "    FG = G*m1*m2/d**2\n",
    "    FE = abs(k*e*e1*e*e2/d**2)\n",
    "\n",
    "    # comparaison des forces\n",
    "    if FG > FE:\n",
    "        preponderant = \"force de gravitation\"\n",
    "        comparaison = FG/FE\n",
    "    else:\n",
    "        preponderant = \"force électromagnétique\"\n",
    "        comparaison = FE/FG\n",
    "\n",
    "    # impression des résultats\n",
    "\n",
    "    print(\"\\nRésultat:\\n\")\n",
    "    print(\"- la valeur de la force de gravitation est: {0:.2e}\".format(FG), ' N')\n",
    "    print(\"    cette force est attractive\")\n",
    "    print(\"- la valeur de la force électromagnétique est: {0:.2e}\".format(FE), ' N')\n",
    "    print(\"    cette force est\", caractere)\n",
    "    print(\"- la\", preponderant, \"est prépondérante\")\n",
    "    print(\"- le rapport de ces deux forces est: {0:.2e}\".format(comparaison))\n",
    "\n",
    "    \n",
    "# Utilisation de la fonction\n",
    "comparaison_forces(m1=5e-7, e1=400, m2=5e-7, e2=400, d=3e-6)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Plusieurs points:\n",
    "- Dans ces exemples, le else n'est en rien obligatoire.\n",
    "\n",
    "## if / elif / else\n",
    "\n",
    "On souhaite parfois faire plusieurs tests imbriqués, on utilise pour cela l'instruction elif (else if)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Elément de numéro atomique Z =  7\n",
      "  fait partie de la deuxième ligne de la classification\n",
      "Elément de numéro atomique Z =  1\n",
      "  fait partie de la première ligne de la classification\n",
      "Elément de numéro atomique Z =  16\n",
      "  fait partie de la troisième ligne de la classification\n",
      "Elément de numéro atomique Z =  33\n",
      "   ne fait pas partie des trois premières lignes de la classification\n"
     ]
    }
   ],
   "source": [
    "# test imbriqué\n",
    "def ligne(Z):\n",
    "    \"\"\"\n",
    "    Indique la ligne dont fait partie l'élément\n",
    "    \n",
    "    :param Z: numéro atomique\n",
    "    \"\"\"\n",
    "    print(\"Elément de numéro atomique Z = \",Z)\n",
    "    # test vérifiant si l'élément fait partie des trois premières lignes\n",
    "    if Z<= 2:\n",
    "        print(\"  fait partie de la première ligne de la classification\")\n",
    "    elif Z <=10:\n",
    "        print(\"  fait partie de la deuxième ligne de la classification\")\n",
    "    elif Z <=18:\n",
    "        print(\"  fait partie de la troisième ligne de la classification\")\n",
    "    else:\n",
    "        print(\"   ne fait pas partie des trois premières lignes de la classification\")\n",
    "        \n",
    "# Utilisation\n",
    "ligne(7)\n",
    "ligne(1)\n",
    "ligne(16)\n",
    "ligne(33)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Attention, erreur fréquente : le test égal se note `==`, et pas `=` (assignation de variable)\n"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Format de la Cellule Texte Brut",
  "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.6.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
