Непоследовательное поведение в модульных тестах при исправлении QFileDialog в PySide2 - PullRequest
0 голосов
/ 24 апреля 2020

Я пытаюсь провести модульное тестирование GUI, написанного на Pyside2. Поскольку я не хочу, чтобы во время тестов отображались окна сообщений (что могло бы привести к остановке тестов при ожидании ввода данных пользователем), я подумал о исправлении QFileDialog. Однако это приводит к тому, что тесты противоречивы. Я не смог найти какой-либо ресурс о том, как правильно смоделировать / исправить патч QFileDialog, поэтому я не уверен, правильно ли я поступаю.

Поведение, которое я описал, воспроизводимо с двумя Сценарии ниже:

myapp.py - простой интерфейс с кнопкой, при нажатии на которую открывается диалоговое окно файла и записывается выбранное имя файла в метку.

import sys

from PySide2.QtWidgets import (QApplication, QFileDialog, QLabel, QMainWindow, 
                               QPushButton, QWidget, QVBoxLayout)


class MyApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.frame = QWidget(self)
        self.setCentralWidget(self.frame)
        main_layout = QVBoxLayout()
        self.frame.setLayout(main_layout)

        self.btn = QPushButton(self, text='Load file')
        self.btn.clicked.connect(self.load_file)
        main_layout.addWidget(self.btn)

        self.label = QLabel(self, text='')
        main_layout.addWidget(self.label)

    def load_file(self):
        query, _ = QFileDialog.getOpenFileName(self, 'Select input file')
        if query:
            self.label.setText('File loaded: ' + query)
        else:
            self.label.setText('File loaded: None')


if __name__ == '__main__':
    app = QApplication()
    ui = MyApp()
    ui.show()
    sys.exit(app.exec_())

test_myapp.py - два модульных теста, которые проверяют, правильно ли обновлена ​​метка (в зависимости от того, вернул ли QFileDialog пустую строку или нет).

import unittest
from unittest.mock import patch

from PySide2.QtWidgets import QApplication

from myapp import MyApp


class TestMyApp(unittest.TestCase):
    @classmethod
    def setUpClass(self):
        self.app = QApplication()

    def setUp(self):
        self.ui = MyApp()

    def tearDown(self):
        self.ui.destroy()

    def test_dialog_box_user_selected_a_file(self):
        with patch('myapp.QFileDialog.getOpenFileName', 
                return_value=('somefile', None)) as dialog_mock:
            self.ui.load_file()
            self.assertEqual(self.ui.label.text(), 'File loaded: somefile')

    def test_dialog_box_user_closed_dialog_without_selecting_a_file(self):
        with patch('myapp.QFileDialog.getOpenFileName', 
                return_value=('', None)) as dialog_mock:
            self.ui.load_file()
            self.assertEqual(self.ui.label.text(), 'File loaded: None')


if __name__ == '__main__':
    unittest.main()

Запуск тестов с python -m unittest test_myapp.py приводит к (большей части времени):

AssertionError: 'File loaded: None' != 'File loaded: somefile'
- File loaded: None
?              ^ ^
+ File loaded: somefile
?              ^ ^^^^^


----------------------------------------------------------------------
Ran 2 tests in 0.013s

FAILED (failures=1)

И все же иногда тесты приводят к:

..
----------------------------------------------------------------------
Ran 2 tests in 0.013s

OK

Поскольку первый тест всегда проходит, мне кажется, что QFileDialog исправляется успешно. Почему второй тест не может исправить это (по крайней мере, большую часть времени)? Если такого рода юнит-тестирование невозможно, есть ли другой способ проверить метод load_file?

...