A supplementary article on "Test Driven Development Startups with PySide & Pytest" at the PySide Study Group. And a note for test-driven development with PySide and Pytest.
Windows 10 Python 3.7.7 Pytest
directory
root
|- sample
| |- __init__.py
| |- gui.py
|- tests
| |- __init__.py
| |- conftest.py
| |- unit
| |- test_gui.py
|- requirments.txt
The gui.py that is the source of the tool here is as follows.
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()
The appearance when executed is as follows.
PySide2
Pytest
python -m venv .venv
.venv \ Script \ Activate.bat
pip install -r requirements.txt
tests/conftest.py
import os
import sys
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
The Pytest official [recommended] to install using pip install -e .
with setup.py (https://docs.pytest.org/en/latest/goodpractices.html" However, depending on the environment (in my case, the tool release environment of the Techcnial Artist team (including DCC tools)), it may not always be possible to provide a pip environment.
In such a case, you may not want to take an extra directory structure, so use conftest.py and put the path to root when executing Pytest.
Of course, in the case of a distribution environment that assumes pip install
, it is better to place setup.py under root so that pip intall -e .
can be done so that pip install
can be done.
Similarly, if you have modules that you need for external tools such as Maya or in-house libraries, you should go through the path here.
For the time being, the following are the basic behaviors to remember. (Actually, there are more, so please refer to the document)
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
Here's QtTest, which PySide provides a module for testing.
The user recognizes that "by clicking the button", the number on the label goes up by 1, so to make this behavior correct, "by clicking the button" is simulated on the test. Need to be done.
Here, QtTest provides a function to simulate its operation by using QtTest.QTest.mouseClick ()
.
In other words, in the above test_add_count, QtTest does the following:
This allows you to ensure that the changes you make when you click the ** button are correct, with a single increment of the count **.
Just run the command to run the test in the root directory for now.
pytest .
Then, the following result is obtained.
======================================= 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 =========================================
To explain this,
As you can see in the code on the test, add_count has ** the developer's intention to want the difference between the values on the first run and the next run to be 1.
However, if you look at the source code, it says self.number + = 2
, ** contrary to the developer's intention **, the difference in the result of the processing executed" by clicking the button " It can be seen that the result of 2 has been obtained.
Now, if you change this to self.number + = 1
and set it to" increase by 1 (that is, the difference that always increases is 1) ", you will get the following result when you executepytest.
======================================= 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 =========================================
In this way, the result of the successful test was obtained.
As mentioned above, Pytest automatically picks up the test code, and by using conftest.py, you can prepare the environment settings you want to assume in advance, so various exclusive environments can be automatically created with less code. You will be able to build with. PySide has a function called QtTest in advance, and you can see that you can simulate the behavior of Gui by using this function.
If you look closely, Pytest has a lot more features, and QtTest also has a lot of features, so I hope you can implement various tests through this startup.
Recommended Posts