Tester la sortie envoyée à stdout en Python

Vous avez un programme qui a une méthode dont la sortie est envoyée à la sortie standard (sys.stdout). Cela signifie presque toujours qu’il émet du texte à l’écran. Vous aimeriez écrire un test pour votre code afin de prouver que, si l’entrée est correcte, la sortie correcte est affichée.

En utilisant la fonction patch() du module unittest.mock, il est assez simple de simuler sys.stdout pour un seul test, et de le remettre en place, sans variables temporaires désordonnées ou état mocké fuyant entre les cas de test.

Considérer, comme exemple, la fonction suivante du module mymodule:

# mymodule.py

def urlprint(protocole, hote, domaine):
    url = '{}://{}.{}'.format(protocole, hote, domaine)
    print(url)

La fonction print intégrée, par défaut, envoie le texte à afficher à sys.stdout. Afin de tester que la sortie arrive à destination, vous pouvez la simuler à l’aide d’un objet de remplacement, puis faire des assertions sur ce qui s’est passé.

L’utilisation de la méthode patch() du module unittest.mock permet de remplacer les objets uniquement dans le contexte d’un test en cours d’exécution et de remettre les choses dans leur état d’origine immédiatement après le test. Voici le code de test pour mymodule:

from io import StringIO
from unittest import TestCase
from unittest.mock import patch
import mymodule

class TestURLPrint(TestCase):
    def test_url_gets_to_stdout(self):
        protocol = 'http'
        host = 'www'
        domain = 'example.com'
        expected_url = '{}://{}.{}\n'.format(protocole, hote, domaine)

        with patch('sys.stdout', new=StringIO()) as fake_out:
            mymodule.urlprint(protocole, hote, domaine)
            self.assertEqual(fake_out.getvalue(), expected_url)

La fonction urlprint() prend trois arguments, et le test commence par mettre en place des arguments pour chacun d’eux. La variable expected_url est définie sur une chaîne contenant la sortie attendue.

Pour exécuter le test, la fonction unittest.mock.patch() est utilisée comme gestionnaire de contexte pour remplacer la valeur de sys.stdout par un objet StringIO en remplacement. La variable fake_out est l’objet qui est créé dans ce processus.

Ceci peut être utilisé à l’intérieur du corps de l’instruction with pour effectuer divers contrôles. Lorsque l’instruction with est terminée, le patch remet tout en place comme avant le test.

Il est à noter que certaines extensions C de Python peuvent écrire directement en sortie standard, en contournant la configuration de sys.stdout.

Cette solution ne vous aidera pas dans ce scénario, mais elle devrait fonctionner correctement avec du code Python pur (si vous avez besoin de capturer des E/S à partir de telles extensions C, vous pouvez le faire en ouvrant un fichier temporaire et en exécutant diverses astuces impliquant des descripteurs de fichiers pour rediriger temporairement la sortie standard vers ce fichier).

Plus d’informations sur la capture d’E/S dans une chaîne de caractères et les objets StringIO sont disponibles dans l’article “Effectuer des opérations d’E/S sur une chaîne de caractères“.

LAISSER UN COMMENTAIRE

Please enter your comment!
Please enter your name here