Maison >développement back-end >Tutoriel Python >Outils de développement que les programmeurs Python doivent connaître

Outils de développement que les programmeurs Python doivent connaître

巴扎黑
巴扎黑original
2017-04-08 10:34:561826parcourir

Python a développé un vaste écosystème qui peut faciliter la vie des programmeurs Python et réduire leur travail de réinvention de la roue. Le même concept s'applique au travail des développeurs d'outils, même si les outils qu'ils développent n'apparaissent pas dans le programme final. Cet article présentera les outils de développement que les programmeurs Python doivent connaître.

Pour les développeurs, l’aide la plus pratique consiste à les aider à rédiger des documents de code. Le module pydoc peut générer une documentation bien formatée pour tout module importable basé sur des docstrings dans le code source. Python comprend deux frameworks de test pour tester automatiquement le code et vérifier l'exactitude du code : 1) Le module doctest, qui peut extraire des tests du code source ou des exemples de fichiers autonomes. Cas d'utilisation. 2) Module unittest, ce module est un cadre de test automatisé complet qui fournit des appareils de test, des suites de tests prédéfinies et une prise en charge de la découverte de tests.

Le module trace peut surveiller la façon dont Python exécute le programme et générer un rapport pour afficher le nombre de fois que chaque ligne du programme est exécutée. Ces informations peuvent être utilisées pour découvrir les chemins d'exécution du programme non couverts par les ensembles de tests automatisés, et peuvent également être utilisées pour étudier les graphiques d'appels de programme afin de découvrir les dépendances entre les modules. L'écriture et l'exécution de tests peuvent détecter des problèmes dans la plupart des programmes. Python facilite le débogage car dans la plupart des cas, Python peut imprimer des erreurs non gérées sur la console. Nous appelons ces erreurs les informations de traçabilité. Si le programme n'est pas exécuté dans une console texte, le traçage peut également générer des informations d'erreur dans un fichier journal ou une boîte de dialogue de message. Lorsque le traçage standard ne peut pas fournir suffisamment d'informations, vous pouvez utiliser le module cgitb pour afficher des informations détaillées dans le contexte de la pile et du code source à tous les niveaux, tels que les variables locales. Le module cgitb peut également générer ces informations de suivi sous forme de HTML pour signaler les erreurs dans les applications Web.

Une fois que vous avez découvert où se situe le problème, vous devez utiliser le débogueur interactif pour saisir le code à déboguer. Le module pdb peut bien faire ce travail. Ce module peut afficher le chemin d'exécution du programme lorsqu'une erreur se produit et peut ajuster dynamiquement les objets et le code pour le débogage. Une fois le programme testé et débogué, l’étape suivante consiste à porter votre attention sur les performances. Les développeurs peuvent utiliser les modules profile et timit pour tester la vitesse du programme, découvrir ce qui est lent dans le programme et puis corrigez le problème. Cette partie du code est réglée indépendamment pour le réglage. Les programmes Python sont exécutés via un interpréteur et l'entrée de l'interpréteur est une version compilée du bytecode du programme d'origine. Cette version compilée du bytecode peut être générée dynamiquement lorsque le programme est exécuté, ou elle peut être générée lorsque le programme est empaqueté. Le module compileall peut gérer l'empaquetage de programmes. Il expose les interfaces liées à l'empaquetage, qui peuvent être utilisées par les installateurs et les outils d'empaquetage pour générer des fichiers contenant les bytecodes de module. Parallèlement, dans l'environnement de développement, le module compileall peut également être utilisé pour vérifier si le fichier source contient des erreurs de syntaxe.

Au niveau du code source, le module pyclbr fournit un visualiseur de classes pour permettre aux éditeurs de texte ou à d'autres programmes d'analyser les caractères intéressants dans les programmes Python, tels que les fonctions ou les classes. Après avoir fourni un visualiseur de classes, il n'est pas nécessaire d'introduire du code, évitant ainsi les effets secondaires potentiels.

Chaînes de documents et module doctest

Si la première ligne d'une fonction, d'une classe ou d'un module est une chaîne, alors la chaîne est une docstring. L'inclusion de docstrings peut être considérée comme une bonne pratique de programmation, car ces chaînes peuvent fournir des informations aux outils de développement de programmes Python. Par exemple, la commande help() peut détecter les docstrings, et les IDE liés à Python peuvent également détecter les docstrings. Étant donné que les programmeurs ont tendance à afficher les docstrings dans un shell interactif, il est préférable de garder ces chaînes courtes. Par exemple

# mult.py
class Test:
    """
    >>> a=Test(5)
    >>> a.multiply_by_2()
    10
    """
    def __init__(self, number):
        self._number=number

    def multiply_by_2(self):
        return self._number*2

Lors de la rédaction de la documentation, un problème courant est de savoir comment synchroniser la documentation et le code réel. Par exemple, un programmeur peut modifier l'implémentation d'une fonction mais oublier de mettre à jour la documentation. Pour résoudre ce problème, nous pouvons utiliser le module doctest. Le module doctest collecte les docstrings, les analyse et les exécute sous forme de tests. Afin d'utiliser le module doctest, nous créons généralement un nouveau module indépendant pour les tests. Par exemple, si l'exemple précédent Classe de test est inclus dans le fichier mult.py, alors vous devez créer un nouveau fichier testmult.py pour tester, comme suit Affichage :

# testmult.py

import mult, doctest

doctest.testmod(mult, verbose=True)

# Trying:
#     a=Test(5)
# Expecting nothing
# ok
# Trying:
#     a.multiply_by_2()
# Expecting:
#     10
# ok
# 3 items had no tests:
#     mult
#     mult.Test.__init__
#     mult.Test.multiply_by_2
# 1 items passed all tests:
#    2 tests in mult.Test
# 2 tests in 4 items.
# 2 passed and 0 failed.
# Test passed.

Dans ce code, doctest.testmod(module) exécutera le test d'un module spécifique et renverra le nombre de tests ayant échoué et le nombre total de tests. Si tous les tests réussissent, aucune sortie n’est produite. Sinon, vous verrez un rapport d'échec montrant la différence entre les valeurs attendues et réelles. Si vous souhaitez voir le résultat détaillé du test, vous pouvez utiliser testmod(module, verbose=True).

Si vous ne souhaitez pas créer un fichier de test séparé, une autre option consiste à inclure le code de test correspondant à la fin du fichier :

if __name__ == '__main__':
    import doctest
    doctest.testmod()

Si nous voulons effectuer ce type de test, nous pouvons appeler le module doctest avec l'option -m. Normalement, il n'y a aucune sortie lors de l'exécution de tests. Si vous souhaitez voir des informations détaillées, vous pouvez ajouter l'option -v.

$ python -m doctest -v mult.py

Tests unitaires et module unittest

Si nous voulons tester le programme de manière plus approfondie, nous pouvons utiliser le module unittest. Grâce aux tests unitaires, les développeurs peuvent écrire une série de cas de test indépendants pour chaque élément qui constitue le programme (par exemple, des fonctions, méthodes, classes et modules indépendants). Lors du test de programmes plus volumineux, ces tests peuvent servir d’éléments de base pour vérifier l’exactitude du programme. À mesure que nos programmes grandissent, les tests unitaires pour différents composants peuvent être combinés dans des cadres de test et des outils de test plus vastes. Cela peut grandement simplifier le travail de test de logiciels et faciliter la recherche et la résolution des problèmes logiciels.

# splitter.py
import unittest

def split(line, types=None, delimiter=None):
    """Splits a line of text and optionally performs type conversion.
    ...
    """
    fields = line.split(delimiter)
    if types:
        fields = [ ty(val) for ty,val in zip(types,fields) ]
    return fields

class TestSplitFunction(unittest.TestCase):
    def setUp(self):
        # Perform set up actions (if any)
        pass
    def tearDown(self):
        # Perform clean-up actions (if any)
        pass
    def testsimplestring(self):
        r = split('GOOG 100 490.50')
        self.assertEqual(r,['GOOG','100','490.50'])
    def testtypeconvert(self):
        r = split('GOOG 100 490.50',[str, int, float])
        self.assertEqual(r,['GOOG', 100, 490.5])
    def testdelimiter(self):
        r = split('GOOG,100,490.50',delimiter=',')
        self.assertEqual(r,['GOOG','100','490.50'])

# Run the unittests
if __name__ == '__main__':
    unittest.main()

#...
#----------------------------------------------------------------------
#Ran 3 tests in 0.001s

#OK

Lors de l'utilisation de tests unitaires, nous devons définir une classe qui hérite de unittest.TestCase. Dans cette classe, chaque test est défini sous la forme d'une méthode et nommé commençant par test - par exemple, 'testsimplestring', 'testtypeconvert' et similaire nommer les méthodes (il est nécessaire de souligner que tant que le nom de la méthode commence par test, peu importe comment vous le nommez, c'est OK). Dans chaque test, des assertions peuvent être utilisées pour vérifier différentes conditions.

Exemple pratique :

Supposons que vous ayez une méthode dans votre programme et que la sortie de cette méthode pointe vers la sortie standard (sys.stdout). Cela signifie généralement afficher des informations textuelles à l'écran. Si vous souhaitez tester votre code pour le prouver, donnez simplement l'entrée correspondante et la sortie correspondante sera affichée.

# url.py

def urlprint(protocol, host, domain):
    url = '{}://{}.{}'.format(protocol, host, domain)
    print(url)

La fonction d'impression intégrée envoie la sortie à sys.stdout par défaut. Pour tester que la sortie est réellement arrivée, vous pouvez la simuler à l'aide d'un objet remplaçant et faire des affirmations sur les valeurs attendues du programme. La méthode patch() du module unittest.mock ne peut remplacer l'objet que dans le contexte de l'exécution du test et renvoyer l'état d'origine de l'objet immédiatement une fois le test terminé . Voici le code de test pour la méthode urlprint() :

#urltest.py

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

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

        with patch('sys.stdout', new=StringIO()) as fake_out:
            url.urlprint(protocol, host, domain)
            self.assertEqual(fake_out.getvalue(), expected_url)

  urlprint()函数有三个参数,测试代码首先给每个参数赋了一个假值。变量expected_url包含了期望的输出字符串。为了能够执行测试,我们使用了unittest.mock.patch()方法作为上下文管理器,把标准输出sys.stdout替换为了StringIO对象,这样发送的标准输出的内容就会被StringIO对象所接收。变量fake_out就是在这一过程中所创建出的模拟对象,该对象能够在with所处的代码块中所使用,来进行一系列的测试检查。当with语句完成时,patch方法能够将所有的东西都复原到测试执行之前的状态,就好像测试没有执行一样,而这无需任何额外的工作。但对于某些Python的C扩展来讲,这个例子却显得毫无意义,这是因为这些C扩展程序绕过了sys.stdout的设置,直接将输出发送到了标准输出上。这个例子仅适用于纯Python代码的程序(如果你想捕获到类似C扩展的输入输出,那么你可以通过打开一个临时文件然后将标准输出重定向到该文件的技巧来进行实现)。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn