2017-03-27 5 views
0

私はPyQt5 MainWindow GUIの機能テストを書いています。現在、正しいウィジェットがグリッドレイアウトの正しい座標にあるかどうかを確認しています。私はobjectNameでウィジェットを見つける方法を決め、GUIの(グリッド)レイアウトでウィジェットに "掘り下げる"ために必要なモジュールの階層を見つけましたが、私はこれを難しい方法でやらなければならないと感じています。私はPyQt4/5のドキュメントを読んで、それに関する同様の質問を探していましたが、私の仕事を簡略化するツールは明らかにしていませんでした。ウィジェットとそのレイアウトの場所を名前で見つけるよりも簡潔な方法ですか?

理想的には、私は、次の擬似コードと同様のコマンドを希望:

Bob_widget = widget['Bob'] # lookup widget by objectName 
assert Bob_widget.layout.coordinates == (0, 0) 

擬似コードの最初の行の機能は、次にfindChildメソッドに各ウィジェットの名前とタイプを渡すによって行うことができます辞書を作っていますが、それに相当するものがあるのだろうかと思います。

擬似コードの2行目は痛みが増します。ウィジェットを見つけるためにGUIをどのようにトンネルするかについて、いくつかの調査が行われました。以下私のGUIのコードのために:

import sys 
from collections import namedtuple 

from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QGridLayout, 
          QLabel, QDoubleSpinBox) 

gui_userinput = namedtuple('gui_userinput', ['key', 'string', 'value', 'range']) 

variable_a = gui_userinput(key='variable_a', string='Variable A', value=165.00, 
          range=(0.00, 10000.00)) 
variable_b = gui_userinput(key='variable_b', string='Variable B', value=135.00, 
          range=(0.00, 10000.00)) 

gui_userinput_order = (variable_a, variable_b) 


class Gui(QMainWindow): 
    def __init__(self, parent=None): 

     super(Gui, self).__init__(parent) 

     self.setObjectName('toplevel') 
     self.setupUi() 

    def setupUi(self): 

     centralWidget = QWidget() 
     centralWidget.setObjectName('centralwidget') 
     self.setCentralWidget(centralWidget) 

     centralLayout = QGridLayout() 
     self.setObjectName('centrallayout') 

     for i, widget in enumerate(gui_userinput_order): 

      wlabel = QLabel(widget.string) 
      wlabel.setObjectName(widget.key + '_label') 

      wbox = QDoubleSpinBox() 
      wbox.setObjectName(widget.key) 
      wbox.setRange(*widget.range) 
      wbox.setValue(widget.value) 

      centralLayout.addWidget(wlabel, 0, i) 
      centralLayout.addWidget(wbox, 1, i) 

     centralWidget.setLayout(centralLayout) 


if __name__ == '__main__': 

    app = QApplication(sys.argv) 
    ui = Gui() 
    ui.show() 
    sys.exit(app.exec_()) 

メインウィンドウからウィジェットをフェッチするようなステートメントを使用する必要があります。

widget_0_0 = self.ui.centralWidget().layout()\ 
      .itemAtPosition(0, 0).widget() 

「GUIウィジェット容器を有する(グリッド)レイアウトを有する中央のウィジェットを有します私が望むウィジェットを保持するグリッド座標(0、0)で。

import sys 
from PyQt5.QtWidgets import QApplication, QDoubleSpinBox, QLabel 

import mini_ui 

app = QApplication(sys.argv) 


class TestMainGUi: 

    def setup(self): 
     self.ui = mini_ui.Gui() 

    def test_all_widgets_exist(self): 
     """The user finds the expected labels and doublespinboxes.""" 
     for widget in mini_ui.gui_userinput_order: 
      found_box = self.ui.findChild(QDoubleSpinBox, widget.key) 
      assert found_box.value() == widget.value 
      found_label = self.ui.findChild(QLabel, widget.key + '_label') 
      assert found_label.text() == widget.string 

    def test_label_0_0(self): 
     """The user sees a label for 'Variable A' in the top left corner.""" 
     label_a = self.ui.findChild(QLabel, 'variable_a_label') 
     print('Found', label_a, 'named', label_a.objectName(), 'in GUI.') 
     widget_0_0 = self.ui.centralWidget().layout()\ 
      .itemAtPosition(0, 0).widget() 
     print('Found widget type', type(widget_0_0), 'at grid 0, 0') 
     print('It is named: ', widget_0_0.objectName()) 

     assert widget_0_0.text() == 'Variable A' 
     assert widget_0_0 is label_a 

    def test_alternate_widget_acces(self): 
     """Just hacking away trying to find a more terse widget reference""" 
     label_a = self.ui.findChild(QLabel, 'variable_a_label') 

     assert 1 == 1 

    def teardown(self): 
     pass 

および反復ウィジェット座標グリッドにコンポーネントウィジェットに一致するように第二の試験を変更し、それは間違っている感じ:

だから、以下最小例のオフリフテストをコードすることができます。 GUIが変更されて階層が変更された場合、テストは機能しません。テストコードは、GUIの細かい構造を認識している必要があります。

GUIレイアウトの内容をテストするための、より簡潔で堅牢な方法がありますか?私が紛失しているビルトインツールはありますか?

ありがとうございました。

答えて

0

名前でレイアウトを見つけるための部分的な解決策があります。つまり、テストでは正確なGUI構造を認識できなくなります。

レイアウトの名前はで、centralWidget.setLayout()でcentralWidgetに適用する前にレイアウトに割り当てた場合、が失われます。 centralWidgetのレイアウトを設定し、を指定した場合、の名前はcentralWidget.layout()になります。レイアウトは名前で検索できます。

したがって、としてmini_uiを修正:

centralWidget.setLayout(centralLayout) 
centralWidget.layout().setObjectName('centrallayout') 

、次いで、機能テストレイアウトを見つけ、それを変数に割り当てることができます。

def test_alternate_widget_access(self): 
    """Just hacking away trying to find a more terse widget reference""" 
    main_layout = self.ui.findChild(QGridLayout, 'centrallayout') 
    found_widget = main_layout.itemAtPosition(0, 0).widget() 
関連する問題