IdentifiantMot de passe
Loading...
Mot de passe oubli� ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les r�ponses en temps r�el, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

RESOLU : Tester qu'une exception est bien lev�e


Sujet :

Python

  1. #1
    Membre Expert
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    F�vrier 2003
    Messages
    1 605
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : D�veloppeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : F�vrier 2003
    Messages : 1 605
    Par d�faut RESOLU : Tester qu'une exception est bien lev�e
    Bonjour,

    dans le cadre d'un projet professionnel, je dois ici d�placer un fichier d'un endroit vers un autre.

    J'utilise pytest pour les assert et pytest-mock si besoin dans mes tests.

    Voici le code de la m�thode de la classe traitant de ce d�placement de fichier :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    from pathlib import Path
    from shutil import move
     
    class FileManagerError(Exception):
        """File error class."""
     
     
    class FileManager:
        def rename_PDF_file(self, sourcefile: Path, destfile: Path) -> None:
     
            try:
                move(sourcefile, destfile)
            except (FileNotFoundError, PermissionError) as err:
                raise FileManagerError(
                    f"ERREUR de renommage du fichier {sourcefile.name} "
                    + f"en {destfile.name} : {err}"
                ) from err
    Le test s'assurant que le d�placement du fichier est ok fonctionne et passe au vert dans Pytest.

    En revanche, celui levant l'exception FileManagerError ne fonctionne pas et ne l�ve pas l'exception.

    Voici le code du test concern� :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    from pathlib import Path
    import pytest
    from pytest_mock import MockerFixture
    import shutil
    from file_manager import FileManager, FileManagerError
     
    def test_rename_PDF_file_is_not_ok(
            self, tmp_path: Path, mocker: MockerFixture
        ) -> None:
            sourcefile: Path = tmp_path / "in.pdf"
            sourcefile.write_bytes(b"foo bar")
            destfile: Path = tmp_path / "out.pdf"
            mocker.patch.object(shutil, "move", side_effect=PermissionError)
            manager: FileManager = FileManager(tmp_path, tmp_path)
            with pytest.raises(FileManagerError):
                manager.rename_PDF_file(sourcefile=sourcefile, destfile=destfile)
    L'erreur est :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    Failed: DID NOT RAISE <class 'file_manager.FileManagerError'>
    J'ai patch� shutil.move avec diff�rents effets de bord, comme IOError, FileNotFoundError et ici PermissionError, m�me constat.
    J'ai essay� mocker.patch('shutil.move', ...) � la place de mocker.patch.object(shutil, 'move', ...), m�me r�sultat.

    J'ai aussi essay� ceci :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def test_rename_PDF_file_is_not_ok(
            self, tmp_path: Path, mocker: MockerFixture
        ) -> None:
            def shutil_patch(*args: Any, **kwargs: Any) -> None:
                raise PermissionError
            sourcefile: Path = tmp_path / "in.pdf"
            sourcefile.write_bytes(b"foo bar")
            destfile: Path = tmp_path / "out.pdf"
            mocker.patch.object(shutil, "move", shutil_patch)
            manager: FileManager = FileManager(tmp_path, tmp_path)
            with pytest.raises(FileManagerError):
                manager.rename_PDF_file(sourcefile=sourcefile, destfile=destfile)
    Et pareil.

    Je sais que je peux inventer un r�pertoire bidon pour la destination du fichier afin que l'exception FileNotFoundError soit lev�e et que mon test passe au vert.

    Mais bof quoi. Je pr�f�re mocker shutil.move.

    Auriez-vous une id�e ?

  2. #2
    Expert �minent
    Homme Profil pro
    Architecte technique retrait�
    Inscrit en
    Juin 2008
    Messages
    21 771
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activit� : Architecte technique retrait�
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 771
    Par d�faut
    Salut,

    Ce que vous racontez semble dire que le mock ne marche pas.

    Je ne serais pas surpris que �a tombe en marche en rempla�ant le "from shutil import move" par un "import shutil" et l'utilisation explicite de shutil.move.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Expert confirm� Avatar de papajoker
    Homme Profil pro
    D�veloppeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 324
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ni�vre (Bourgogne)

    Informations professionnelles :
    Activit� : D�veloppeur Web
    Secteur : High Tech - Multim�dia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 324
    Par d�faut
    bonjour

    petit cas particulier
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    rename_PDF_file(Path("/tmp/1.pdf"), Path("/tmp/"))
    ici, j'intercepterais OSError dans cette fonction pour couvrir plus que les 2 exceptions classiques

    EDIT: de m�me , juste un probl�me d'importation de shutil

  4. #4
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyr�n�es)

    Informations professionnelles :
    Activit� : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par d�faut
    Bonjour,

    Dans file_manager.py, apr�s avoir fait from shutil import move, la variable file_manager.move pointe vers le m�me objet que shutil.move. Appelons "obj1" cet objet. Rq : dans le cas pr�sent, cet objet est une fonction.

    Dans le fichier de test, je pense que l'expression mocker.patch.object(shutil, "move", side_effect=PermissionError) modifie shutil pour que sa propri�t� move ne pointe plus vers "obj1", mais vers un nouvel objet "obj2" qui, quand on l'appelle comme une fonction, lance une exception.

    Mais file_manager.FileManager.rename_PDF_file continue d'appeler file_manager.move qui pointe toujours vers l'objet "obj1" de d�part.

    Je fais le m�me pari que wiztricks :

    Citation Envoy� par wiztricks Voir le message
    Je ne serais pas surpris que �a tombe en marche en rempla�ant le "from shutil import move" par un "import shutil" et l'utilisation explicite de shutil.move.
    Dans file_manager.py, apr�s avoir fait import shutil, la variable file_manager.shutil pointera vers le m�me objet que shutil. Appelons "obj3" cet objet. Rq : dans le cas pr�sent, cet objet est un module.

    Dans le fichier de test, l'expression mocker.patch.object(shutil, "move", side_effect=PermissionError) modifiera alors l'objet point� par shutil, qui est bien "obj3". La propri�t� move de cet objet "obj3" ne pointera plus vers "obj1", mais vers "obj2".

    � part �a, personnellement, pour faire des tests unitaires par dessus du code qui manipulait le syst�me de fichiers, j'utilisais pyfakefs. C'�tait tr�s pratique.

    Documentation : http://jmcgeheeiv.github.io/pyfakefs/master/usage.html

  5. #5
    Membre Expert
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    F�vrier 2003
    Messages
    1 605
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : D�veloppeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : F�vrier 2003
    Messages : 1 605
    Par d�faut
    Merci � tous pour vos interventions et pour m'aider � r�soudre mon (petit) soucis.

    C'est effectivement bien l'emploi de en lieu et place de dans ma classe qui a r�solu mon probl�me.

    Python regorge de petites subtilit�s comme celle-ci et je me fais r�guli�rement berner

    Merci � vous !

  6. #6
    Membre Expert
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    F�vrier 2003
    Messages
    1 605
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : D�veloppeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : F�vrier 2003
    Messages : 1 605
    Par d�faut
    Citation Envoy� par Pyramidev Voir le message
    Bonjour,

    Dans file_manager.py, apr�s avoir fait from shutil import move, la variable file_manager.move pointe vers le m�me objet que shutil.move. Appelons "obj1" cet objet. Rq : dans le cas pr�sent, cet objet est une fonction.

    Dans le fichier de test, je pense que l'expression mocker.patch.object(shutil, "move", side_effect=PermissionError) modifie shutil pour que sa propri�t� move ne pointe plus vers "obj1", mais vers un nouvel objet "obj2" qui, quand on l'appelle comme une fonction, lance une exception.

    Mais file_manager.FileManager.rename_PDF_file continue d'appeler file_manager.move qui pointe toujours vers l'objet "obj1" de d�part.
    Merci pour l'explication qui clarifie bien pourquoi mon test plantait !

    J'ai tendance � n'importer des libs que j'utilise que les m�thodes qui m'int�ressent mais je vois bien l'effet de bord que cela peut engendrer.

    Citation Envoy� par Pyramidev Voir le message
    � part �a, personnellement, pour faire des tests unitaires par dessus du code qui manipulait le syst�me de fichiers, j'utilisais pyfakefs. C'�tait tr�s pratique.
    Merci pour l'id�e mais au taf, nous r�pondons � des r�gles d'usage strictes : respect au maximum de la PEP8, usage de linters, emploi de pathlib pour toutes les manipulations de chemins/fichiers... Et pytest + pytest-django (si besoin) + pytest-mock pour couvrir nos tests

  7. #7
    Expert �minent
    Homme Profil pro
    Architecte technique retrait�
    Inscrit en
    Juin 2008
    Messages
    21 771
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activit� : Architecte technique retrait�
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 771
    Par d�faut
    Salut,

    Citation Envoy� par Arioch Voir le message
    Python regorge de petites subtilit�s comme celle-ci et je me fais r�guli�rement berner
    Ce qui est "subtil" ici est que �a se ram�ne � assigner 2 r�f�rences � un m�me objet comme:
    pour se demander pourquoi lorsqu'on assigne un autre objet � B, on acc�de toujours � l'ancien objet via A.

    Bien sur, ce "d�tail" enfoui dans la complexit� des imports, la notion de module, la magie des mocks,... se fait oublier... mais from shutil move (le A) cr�e une r�f�rence � un objet alors que shutil.move en sera une autre et l'assignation faite � l'un casse la coh�rence: c'est le m�me Python et la m�me punition.

    Une "solution" pourrait �tre de laisser le module file_manager tel qu'il est �crit.... et de faire un import file_manager dans le script de test pour "mocker" file_manager.move.

    Personnellement, je pr�f�re �viter les from module import X, Y, Z car �a n'aide pas � savoir d'o� sort la fonction appel�e (� la relecture). Quand je le fais, c'est pour "optimiser" une fonction qui appellera N fois module.X. Dans ce cas, j'inclus un from module import X au d�but de la fonction - ce qui me permet de me rappeler de l'intention initiale -.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  8. #8
    Membre Expert
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    F�vrier 2003
    Messages
    1 605
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : D�veloppeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : F�vrier 2003
    Messages : 1 605
    Par d�faut
    Citation Envoy� par wiztricks Voir le message
    Personnellement, je pr�f�re �viter les from module import X, Y, Z car �a n'aide pas � savoir d'o� sort la fonction appel�e (� la relecture). Quand je le fais, c'est pour "optimiser" une fonction qui appellera N fois module.X. Dans ce cas, j'inclus un from module import X au d�but de la fonction - ce qui me permet de me rappeler de l'intention initiale -.

    - W
    Je vais opter pour cette mani�re de faire d�sormais. Ca m'�vitera de me faire des n�uds au cerveau inutilement

Discussions similaires

  1. R�ponses: 0
    Dernier message: 16/10/2012, 13h39
  2. R�ponses: 3
    Dernier message: 29/03/2010, 12h35
  3. [VS2005] S'arreter quand une exception est lev�e
    Par ZePostman dans le forum Visual Studio
    R�ponses: 8
    Dernier message: 28/08/2008, 15h24
  4. R�ponses: 2
    Dernier message: 26/04/2008, 17h31
  5. Comment tester qu'une base est bien pr�sente?
    Par xilay dans le forum MS SQL Server
    R�ponses: 2
    Dernier message: 20/10/2005, 16h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo