除了 BDD,您将如何自动化预期用户交互的测试?
- 您可以对输入(或其效果)进行动画处理,
- 要么您必须等待人工干预并完成任务。
我已经为 Python 中的 GUI 应用程序实现了 BDD 测试套件。 BDD 部分与通常的自动化测试套件没有什么不同。
如果您想测试一个简单的终端应用程序,您可以在包含输入的文件中使用管道。
但是,如果您打算测试一个富终端或图形应用程序,您应该为这个特定框架寻找一个测试驱动程序。例如,对于 Qt,QTest 提供 mouseClick、keyPress、qWaitForWindowActive、...
BDD 仅更改测试的结构,而不是:
def test__add_one_int_with_another__gets_the_result():
driver = initiate_test_driver()
driver.click_number(1)
driver.click_operator("+")
driver.click_number(1)
driver.click_enter()
assert driver.get_displayed_result() == "2"
你将拥有
Feature: simple calculator
Scenario: adding two positive integers
Given: the application is started
When: I press <x>
And: I press +
And: I press <y>
And: I press Enter
Then: I get the result <result>
Examples: Computations
| x | y | result |
| 1 | 1 | 2 |
def the_application_is_started(ctxt):
ctxt.driver = initiate_test_driver()
def i_press(ctxt, something):
if something in (0,1,2,3,4,5,6,7,8,9):
ctxt.driver.click_number(something)
elif something in ("+", "-", "*", "/"):
ctxt.driver.click_operator(something)
def i_get_the_result(ctxt, result):
assert ctxt.driver.get_displayed_result() == result
编辑:正如这个答案的 cmets 中所问的,这是一个自动化测试期间用户交互的示例。
from PyQt5 import QtWidgets, QtCore, Qt, QtGui
class DiodeSwitchWindow(QtWidgets.QMainWindow):
def __init__(self) -> None:
super().__init__(None) # a top window has no parent
self.setWindowTitle("Diode Switcher")
self.diode_switch_panel = QtWidgets.QWidget(self)
self.diode_switch_panel.switch_diode_button = QtWidgets.QPushButton(self.diode_switch_panel)
self.diode_switch_panel.switch_diode_button.setText("Switch")
self.diode_switch_panel.diode_label = QtWidgets.QLabel(self.diode_switch_panel)
self.diode_switch_panel.diode_icon_on = QtGui.QPixmap(16, 16)
self.diode_switch_panel.diode_icon_on.fill(QtGui.QColor("#0F0")) # green
self.diode_switch_panel.diode_icon_off = QtGui.QPixmap(16, 16)
self.diode_switch_panel.diode_icon_off.fill(QtGui.QColor("#F00")) # red
self.diode_switch_panel.diode_label.setPixmap(self.diode_switch_panel.diode_icon_off)
self.diode_switch_panel.switch_state = False # off
self.diode_switch_panel.switch_diode_button.clicked.connect(lambda _: self.switch())
layout = QtWidgets.QHBoxLayout()
layout.addWidget(self.diode_switch_panel.switch_diode_button)
layout.addWidget(self.diode_switch_panel.diode_label)
self.diode_switch_panel.setLayout(layout)
self.setCentralWidget(self.diode_switch_panel)
def switch(self) -> None:
if self.diode_switch_panel.switch_state is True:
self.diode_switch_panel.diode_label.setPixmap(self.diode_switch_panel.diode_icon_off)
else:
self.diode_switch_panel.diode_label.setPixmap(self.diode_switch_panel.diode_icon_on)
self.diode_switch_panel.switch_state = not self.diode_switch_panel.switch_state
def test_switch() -> None:
from PyQt5.QtTest import QTest
# setup the application under test
app = QtWidgets.QApplication([])
main_window = DiodeSwitchWindow()
main_window.setVisible(True)
# no exec !!!
assert main_window.diode_switch_panel.switch_state is False
# simulate user interaction
QTest.mouseClick(main_window.diode_switch_panel.switch_diode_button, QtCore.Qt.LeftButton)
# ask the user to check visually that the diode has switched from off to on
answer = QtWidgets.QMessageBox(
QtWidgets.QMessageBox.Question, # icon
"Manual validation required", # title
"Is the diode green (ON) ?", # question
QtWidgets.QMessageBox.No | QtWidgets.QMessageBox.Yes, # buttons
None, # no parent
).exec()
assert answer == QtWidgets.QMessageBox.Yes
# simulate user interaction again
QTest.mouseClick(main_window.diode_switch_panel.switch_diode_button, QtCore.Qt.LeftButton)
# ask the user to check visually that the diode has switched from on to off
answer = QtWidgets.QMessageBox(
QtWidgets.QMessageBox.Question, # icon
"Manual validation required", # title
"Is the diode red (OFF) ?", # question
QtWidgets.QMessageBox.No | QtWidgets.QMessageBox.Yes, # buttons
None, # no parent
).exec()
assert answer == QtWidgets.QMessageBox.Yes
if __name__ == "__main__":
app = QtWidgets.QApplication([])
main_window = DiodeSwitchWindow()
main_window.setVisible(True)
app.exec()
如果您运行此文件 ($ python so69103776.py),它将显示应用程序并让您使用它,直到您退出它(关闭窗口)。
如果您在此文件上运行测试运行程序(例如$ pytest so69103776.py),它将打开一个弹出窗口供您回答,两次。