2017-06-26 5 views
1

Meine Aufgabe ist es, einen automatisierten UI-Test für eine in Entwicklung befindliche Software zu schreiben. Es passiert so, dass Radiobuttons eine Messagebox auslösen, die meinen automatisierten Test stoppt, bis ich ihn manuell bestätige (durch Drücken von ENTER). Das Problem ist, dass ich nicht weiß, wie ich diese neu beschworene Nachrichtenbox anrufen kann, und lasse sie dann von QTest::keyClick(<object>, QtKey::Key_Enter); bestätigen und lasse meinen automatisierten Test den Lauf fortsetzen.Qt Auto-UI-Test wird wegen MessageBox gestoppt. Wie simuliere ich in eine Messagebox?

Ich verwende QWidgets, QApplication, Q_OBJECT und QtTest. Ich werde einen Code ähnlich dem, was ich arbeite mit:

void testui1(){ 
Form1* myform = new Form1(); 
myform->show(); 
QTest::mouseClick(myform->radioButton01, Qt::LeftButton, Qt::NoModifier, QPoint(), 100); 
// Message box pops up and stops the operation until confirmed 
QTest::mouseClick(myform->radioButton02, Qt::LeftButton, Qt::NoModifier, QPoint(), 100); 
// again 
... 
} 

Wie genau kann ich Skript automatisch das Meldungsfeld zu bestätigen? Das Nachrichtenfeld ist nur ein [OK] -Typ, also brauche ich es nicht zurückzukehren, ob ich Ja oder Nein gedrückt habe. Eine QTest::keyClick(<target object>, Qt::Key_Enter) Methode muss wissen, auf welches Objekt sie drücken soll. Ich habe versucht, einschließlich myform in das Objekt und es hat nicht funktioniert. Googeln Ich habe die Antwort nicht gefunden. Ich fand funktioniert das folgende Ergebnis als nicht für das, was ich suche

QWidgetList allToplevelWidgets = QApplication::topLevelWidgets(); 
foreach (QWidget *w, allToplevelWidgets) { 
    if (w->inherits("QMessageBox")) { 
     QMessageBox *mb = qobject_cast<QMessageBox *>(w); 
     QTest::keyClick(mb, Qt::Key_Enter); 
    } 
} 
+0

Findet Ihr Code das Nachrichtenfeld? Bitte klären Sie. – vahancho

+0

Ich bezweifle es. Gibt es auf jeden Fall ein Stück Skript, um diese Nachrichtenbox zu finden? – Unit1

+0

Ihr Code sieht korrekt aus: Iterieren Sie über alle Fenster der obersten Ebene. Ich vermute, dass das modale Meldungsfeld die Ereignisschleife blockiert, so dass der Code nicht ausgeführt wird, während das Meldungsfeld geöffnet wird. – vahancho

Antwort

1

Das Problem ist, dass, sobald Sie haben „geklickt“ auf dem Radio-Button, der in QMessageBox::exec Ergebnissen genannt wird, der Code stoppt, bis den Lauf Benutzer klickt auf die Schaltflächen.

Sie können den Benutzer durch Klicken auf eine Schaltfläche simulieren, indem Sie einen Timer starten vor klicken Sie auf das Optionsfeld.

In der Callback-Funktion für den Timer können Sie QApplication::activeModalWidget() verwenden, um einen Zeiger auf das Meldungsfeld zu erhalten, und rufen Sie dann close darauf.

QTimer::singleShot(0, [=]() 
    { 
     QWidget* widget = QApplication::activeModalWidget(); 
     if (widget) 
      widget->close(); 
    }); 

Wenn Sie eine bestimmte Taste auf dem Meldungsfeld drücken möchten, können Sie QCoreApplication::postEvent verwenden, um ein Schlüsselereignis auf das Meldungsfeld zu schreiben

QTimer::singleShot(0, [=]() 
    { 
     int key = Qt::Key_Enter; // or whatever key you want 

     QWidget* widget = QApplication::activeModalWidget(); 
     if (widget) 
     { 
      QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier); 
      QCoreApplication::postEvent(widget, event); 
     } 
    }); 

So in Bezug darauf, wie diese Beziehungen in die Probe Code, den Sie haben:

void testui1() 
{ 
    Form1* myform = new Form1(); 
    myform->show(); 

    QTimer::singleShot(0, [=]() 
     { 
      QWidget* widget = QApplication::activeModalWidget(); 
      if (widget) 
       widget->close(); 
      else 
       QFAIL("no modal widget"); 
     }); 

    QTest::mouseClick(myform->radioButton01, Qt::LeftButton, Qt::NoModifier, QPoint(), 100); 
} 

Eine Beispielanwendung die alle oben zusammen setzen:

#include <QApplication> 
#include <QMainWindow> 
#include <QHBoxLayout> 
#include <QPushButton> 
#include <QTimer> 
#include <QMessageBox> 
#include <iostream> 

int main(int argc, char** argv) 
{ 
    QApplication app(argc, argv); 
    QMainWindow window; 

    QWidget widget; 
    window.setCentralWidget(&widget); 

    QHBoxLayout layout(&widget); 

    QPushButton btn("go"); 
    layout.addWidget(&btn); 

    QObject::connect(&btn, &QPushButton::clicked, [&]() 
     { 
      QTimer::singleShot(0, [=]() 
       { 
        QWidget* widget = QApplication::activeModalWidget(); 
        if (widget) 
        { 
         widget->close(); 
        } 
        else 
        { 
         std::cout << "no active modal\n"; 
        } 
       }); 

      QMessageBox(
       QMessageBox::Icon::Warning, 
       "Are you sure?", 
       "Are you sure?", 
       QMessageBox::Yes | QMessageBox::No, 
       &window).exec(); 
     }); 

    window.show(); 
    return app.exec(); 
} 

Klick auf Go wird wie nichts aussehen geschehen, da die QMessageBox sofort geschlossen.

Um zu beweisen, dass das Meldungsfeld angezeigt und dann geschlossen wird, können Sie die Zeit im Aufruf von QTimer::singleShot auf einen Wert wie 1000 erhöhen. Jetzt wird das Nachrichtenfeld für 1 Sekunde angezeigt und dann wird es vom Timer geschlossen.

+0

Vielen Dank Freund! Aber im Stück 'QTimer :: singleShot (0, [=]()' sollte die 0 durch einen Wert der Wartezeit ersetzt werden.In meinem Fall gebe ich 150 als Millisekunden Wert ein. Es klappt! – Unit1

+0

@ Unit1 Hinzufügen einer willkürlichen Verzögerung ist sehr spröde und fehleranfällig - 150ms funktioniert für Sie auf Ihrem Dev-Rechner, aber wird es auf * jeder * Maschine arbeiten? Ich würde mit einer Verzögerung von 0 bleiben, aber einen Aufruf an QCoreApplication :: processEvents(); hinzufügen, bevor Sie nach dem aktiven Modal suchen (ungetestet, nur eine Idee, wenn es funktioniert, ist es der Verwendung einer Verzögerung weit überlegen) –

+0

Verzögerung = 0 hat nicht für mich funktioniert. Das Debugging-Skript wurde gestoppt. Ich habe es getestet, bevor ich die Verzögerung auf 150 ms einstellte. | Wo schlage ich vor, sollte ich die 'QCoreApplication :: processEvents();'? Bevor der mouseClick die Messagebox ruft oder in diesem QTimer? – Unit1