Tests unitaires et pile d'appels
=================================

Les tests automatiques sont un complément à la déclaration des types.

que tester, quoi tester ?

- que les composants interagissent bien entre eux
- que les unités (fonctions, objets...) réagissent bien à une entrée spécifique
- que le code se comporte de la manière attendue dans des environnements différents
  (systèmes d'exploitation, etc...)

les types de tests :

- tests unitaires
- tests fonctionnels
- tests d'acceptation
- tests d'intégration

Quel outil utiliser ?

- la :doc:`stdlib` propose le module :mod:`unittest`

.. module:: py.test
    :synopsis: outil de test unitaires de la pylib

- :mod:`py.test` est **le plus simple** (plus simple que unittest)

http://pytest.org/latest/

::

    def test_simple():
        "test si ma_fontion renvoie bien 3"
        assert ma_fontion(2) == 3

- `py.test` utilise `assert` et `raises`
- `unittest` necessite de faire sytématiquement une classe, puis `assertEqual()`
- :mod:`doctest` est plus simple mais charge trop les docstrings


.. todo:: écrire un test unitaire avec `py.test` pour la fonction suivante

- installer le paquet `python-pytest`

- écrire un fichier avec une fonction dedans

::

    def double(x):
        return x*2

- écrire un fichier commençant par `test_` qui teste les fonctions du fichier

options utiles dans `py.test`
------------------------------

::

    py.test --tb=no
    py.test --tb=short
    py.test -x (dernière erreur)
    py.test -s  (c'est comme nocapture en fait)
    py.test -x --nocapture --pdb
    py.test -xl --pdb

    py.test -k test_simple


utiliser la pile d'appel pour débugger
---------------------------------------

utiliser la pile d'appels, elle se lit de bas en haut. Il est possible de
provoquer cette pile d'appels.

::

    import traceback
    traceback.print_exc()


traiter une exception avec

::

    try:
        ...
    except:
        import traceback
        traceback.print_exc()

    else:
        bla bla
    finally:
        bla bla


créer le plus possible ses propres exceptions spécifiques au programme

utiliser le module :mod:`pdb`

.. module:: pdb
    :synopsis: debugger de la lib standard

::

    import pdb
    pdb.set_trace()

depuis py.test :

::

    import pytest
    def test_function():
        ...
            pytest.set_trace()    # invoke PDB debugger and tracing



Remarquons que :mod:`pdb` utilise le module :mod:`cmd`, voir :ref:`cmdlabel` qu'on a déjà vu précedemment

::

    (Pdb) h

    Documented commands (type help <topic>):
    ========================================
    EOF    bt         cont      enable  jump  pp       run      unt
    a      c          continue  exit    l     q        s        until
    alias  cl         d         h       list  quit     step     up
    args   clear      debug     help    n     r        tbreak   w
    b      commands   disable   ignore  next  restart  u        whatis
    break  condition  down      j       p     return   unalias  where

    Miscellaneous help topics:
    ==========================
    exec  pdb

    Undocumented commands:
    ======================
    retval  rv

    (Pdb)


last but not least :

utiliser pylint ou pychecker

::

    apt-get install pylint