[PYTHON] Démarrage du développement piloté par les tests avec PySide & Pytest

introduction

Article supplémentaire sur "Démarrage du développement piloté par les tests avec PySide & Pytest" lors de la session d'étude PySide. Et une note pour le développement piloté par les tests avec PySide et Pytest.

image.png

Environnement de développement

Windows 10 Python 3.7.7 Pytest

Exemple de fichier

GitHub

Entretien initial

Préparation des répertoires et des fichiers

annuaire


root
  |- sample
  |    |- __init__.py
  |    |- gui.py
  |- tests
  |    |- __init__.py
  |    |- conftest.py
  |    |- unit
  |        |- test_gui.py
  |- requirments.txt

La source de l'outil ici, gui.py, est la suivante.

sample/gui.py


import sys
from PySide2 import QtCore
from PySide2 import QtWidgets


class SampleDialog(QtWidgets.QDialog):

    def __init__(self, *args):
        super(SampleDialog, self).__init__(*args)
        
        self.number = 0

        self.setWindowTitle('Hello, World!')
        self.resize(300, 200)

        layout = QtWidgets.QVBoxLayout()

        self.label = QtWidgets.QLabel(str(self.number))

        layout.addWidget(self.label)

        self.button = QtWidgets.QPushButton('Add Count')
        self.button.clicked.connect(self.add_count)
        self.button.setMinimumSize(200, 100)

        layout.addWidget(self.button)

        self.setLayout(layout)
        self.resize(200, 100)


    def add_count(self):
        self.number += 2
        self.label.setText(str(self.number))


def main():
    app = QtWidgets.QApplication.instance()
    if app is None:
        app = QtWidgets.QApplication(sys.argv)
    gui = SampleDialog()
    gui.show()
    
    app.exec_()
    

if __name__ == '__main__':
    main()
    

L'apparence lors de l'exécution est la suivante. image.png

Écrivez les modules requis dans requirements.txt

PySide2
Pytest

Créer un environnement venv

  1. Allez dans le répertoire racine
  2. python -m venv .venv
  3. Activez l'environnement venv: .venv \ Script \ Activate.bat
  4. pip install -r requirements.txt

Connectez le chemin d'accès au module avec conftest.py

tests/conftest.py


import os
import sys

sys.path.append(os.path.dirname(os.path.abspath(__file__)))

Selon le responsable de Pytest, il est [recommandé] d'installer en utilisant pip install -e . en utilisant setup.py (https://docs.pytest.org/en/latest/goodpractices.html Cependant, en fonction de chaque environnement (dans mon cas, l'environnement de publication de l'outil (y compris les outils DCC) de l'équipe Techcnial Artist), il n'est pas toujours possible de fournir un environnement pip.

Dans un tel cas, vous ne voudrez peut-être pas prendre une structure de répertoire supplémentaire, utilisez donc conftest.py et mettez le chemin vers root lors de l'exécution de Pytest.

Bien sûr, dans le cas d'un environnement de distribution qui suppose pip install, il est préférable de placer setup.py sous root afin que pip intall -e . puisse être exécuté afin que pip install puisse être exécuté.

De même, si vous avez un module dont vous avez besoin pour un outil externe tel que Maya ou une bibliothèque interne, vous devez suivre le chemin ici.

Implémentation du code de test

Fichier de test dans Pytest

Pour le moment, voici les comportements de base à retenir. (En fait, il y en a plus, donc veuillez vous référer au document)

Ecrire un test

tests/unit/test_gui.py


import sys

from PySide2 import QtCore
from PySide2 import QtWidgets
from PySide2 import QtTest


def test_add_count():
    from sample import gui

    app = QtWidgets.QApplication.instance()
    if app is None:
        app = QtWidgets.QApplication(sys.argv)
    gui = gui.SampleDialog()
    gui.show()

    QtTest.QTest.mouseClick(gui.button, QtCore.Qt.LeftButton)
    n1 = gui.number

    QtTest.QTest.mouseClick(gui.button, QtCore.Qt.LeftButton)
    n2 = gui.number
    assert abs(n2 - n1) == 1

Utiliser QtTest

Voici QtTest, que PySide fournit un module de test.

L'utilisateur reconnaît que "en cliquant sur le bouton", le nombre sur l'étiquette augmente de 1, donc pour corriger ce comportement, "en cliquant sur le bouton" est simulé sur le test. Besoin d'être fait. Ici, QtTest fournit une fonction pour simuler son fonctionnement en utilisant QtTest.QTest.mouseClick ().

En d'autres termes, dans le test_add_count ci-dessus, QtTest effectue les opérations suivantes:

  1. Dans le premier QtTest.QTest.mousClicke (), "Cliquez avec le bouton gauche de la souris sur le bouton de l'interface graphique"
  2. Stockez la valeur de la variable de classe numérique à ce moment-là sous la forme n1
  3. Dans le QtTest.QTest.mousClicke () suivant, "Cliquez avec le bouton gauche de la souris sur le bouton de l'interface graphique"
  4. Enregistrez la valeur de la variable de classe numérique sous la forme n2 lorsque vous cliquez la deuxième fois.
  5. Utilisez assert pour comparer les deux valeurs stockées et assurez-vous que la différence est de 1.

Cela vous permet de vous assurer que les modifications que vous effectuez lorsque vous cliquez sur le bouton ** sont correctes, avec un seul incrément du nombre **.

Exécutez la commande de test

Exécutez simplement la commande pour exécuter le test dans le répertoire racine pour le moment.

pytest .

Ensuite, le résultat suivant est obtenu.

======================================= test session starts ========================================
platform win32 -- Python 3.7.7, pytest-5.4.1, py-1.8.1, pluggy-0.13.1
rootdir: D:\Develop\Python\_learn\test_pytest_pyside
collected 1 item

tests\unit\test_gui.py F                                                                      [100%]

============================================= FAILURES =============================================
__________________________________________ test_add_count __________________________________________

    def test_add_count():
        from sample import gui

        app = QtWidgets.QApplication.instance()
        if app is None:
            app = QtWidgets.QApplication(sys.argv)
        gui = gui.SampleDialog()
        gui.show()

        QtTest.QTest.mouseClick(gui.button, QtCore.Qt.LeftButton)
        n1 = gui.number

        QtTest.QTest.mouseClick(gui.button, QtCore.Qt.LeftButton)
        n2 = gui.number
>       assert abs(n2 - n1) == 1
E       assert 2 == 1
E        +  where 2 = abs((4 - 2))

tests\unit\test_gui.py:22: AssertionError
===================================== short test summary info ======================================
FAILED tests/unit/test_gui.py::test_add_count - assert 2 == 1
======================================== 1 failed in 0.67s =========================================

Pour expliquer cela, Comme vous pouvez le voir à partir du code du test, nous pouvons voir que add_count a l'intention du développeur ** que la différence entre les valeurs de la première exécution et de la prochaine exécution soit de 1. Cependant, si vous regardez le code source, il dit self.number + = 2, ** contrairement à l'intention du développeur **, la différence dans le résultat du traitement exécuté" en cliquant sur le bouton " On voit que le résultat de 2 a été obtenu.

Maintenant, si vous changez ceci en self.number + = 1 et le définissez sur" augmenter de 1 (c'est-à-dire que la différence qui augmente toujours est de 1) ", vous obtiendrez le résultat suivant lorsque vous exécuterez pytest..

======================================= test session starts ========================================
platform win32 -- Python 3.7.7, pytest-5.4.1, py-1.8.1, pluggy-0.13.1
rootdir: D:\Develop\Python\_learn\test_pytest_pyside
collected 1 item

tests\unit\test_gui.py .                                                                      [100%]

======================================== 1 passed in 0.70s =========================================

De cette manière, le résultat du test réussi a été obtenu.

Résumé

Comme mentionné ci-dessus, Pytest peut automatiquement récupérer le code de test ou utiliser conftest.py pour préparer les paramètres d'environnement que vous souhaitez assumer à l'avance, de sorte que divers environnements exclusifs peuvent être automatiquement créés avec moins de code. Vous pourrez construire avec. PySide a une fonction appelée QtTest à l'avance, et vous pouvez voir que vous pouvez simuler le comportement de Gui en utilisant cette fonction.

Si vous regardez de plus près, Pytest a beaucoup plus de fonctionnalités, et QtTest a également beaucoup de fonctionnalités, donc j'espère être en mesure de mettre en œuvre divers tests grâce à ce démarrage.

Recommended Posts

Démarrage du développement piloté par les tests avec PySide & Pytest
Développement piloté par les tests avec Django Partie 3
Développement piloté par les tests avec Django Partie 6
Développement piloté par les tests avec Django Partie 2
Développement piloté par les tests avec Django Partie 1
Développement piloté par les tests avec Django Partie 5
Test unitaire du flacon avec pytest
Tester la sortie standard avec Pytest
[Test Driven Development (TDD)] Chapitre 21 Résumé
Contrôle des relances de test avec Luigi + pytest
Jugement des nombres premiers avec Python
Renforcez avec le test de code ⑦
Renforcez avec le test de code ⑨
Utilisez Mock avec pytest
Renforcez avec le test de code ③
Renforcez avec le test de code ⑤
Renforcez avec le test de code ④
Jugement des nombres premiers avec python
Renforcez avec le test de code ②
Renforcez avec le test de code ①
Renforcez avec le test de code ⑧
Renforcez avec le test de code ⑨
Tutoriel pour faire du développement piloté par les tests (TDD) avec Flask-2 Decorators
Tutoriel pour faire du développement piloté par les tests (TDD) avec Flask-1 Test Client Edition