Search code examples
qtqwidgetqtestlibqttest

QTest : testing dialogs with sub dialogs


I am trying to create a test for a use case like this:

  • A Dialog is opened
  • Clicking on a button in this dialog opens a sub dialog
  • Clicking on a button in the sub dialog closes it
  • Some action is done in dialog after sub dialog has been closed

I was able to write a test that does all that and organize the dialogs to make such test possible. However, there is a strange issue that occurs : if these steps are repeated multiple times, then the final action is repeated more times than it should. To simplify, let's suppose the action is outputting input data. Here is the repeat pattern :

  • Execute test with data "1" -> output is "1"
  • Execute test with data "1 2" -> output is "1 2 2"
  • Execute test with data "1 2 3" -> output is "1 2 2 3 3 3"
  • Execute test with data "1 2 3 4" -> output is "1 2 2 3 3 3 4 4 4 4"

It seems that somehow the final action signal is repeated, but I haven't been able to find what is wrong with the code. Here is a simplified code sample that reproduces the issue :

Test case

void QtBugIsolationTest::testCase1()
{
  auto dialog = new MyDialog();

  QTest::mouseClick(dialog->showSubDialogButton, Qt::LeftButton);
  QTest::mouseClick(dialog->subDialog->button, Qt::LeftButton);

  QTest::mouseClick(dialog->showSubDialogButton, Qt::LeftButton);
  QTest::mouseClick(dialog->subDialog->button, Qt::LeftButton);

  QTest::mouseClick(dialog->showSubDialogButton, Qt::LeftButton);
  QTest::mouseClick(dialog->subDialog->button, Qt::LeftButton);

  QVERIFY(true);
}

Main dialog

MyDialog::MyDialog()
{
  setGeometry(0, 0, 100, 100);

  subDialog = new MySubDialog(this);
  showSubDialogButton = new QPushButton(this);
  connect(showSubDialogButton, SIGNAL(clicked()), this, SLOT(OnShowSub()));
}

MyDialog::~MyDialog()
{
  delete showSubDialogButton;
}

void MyDialog::OnShowSub()
{
  connect(subDialog, SIGNAL(accepted()), this, SLOT(OnCloseSub()));
  subDialog->show();
}

void MyDialog::OnCloseSub()
{
  std::cout << "Closed sub dialog" << std::endl;
  subDialog->hide();
  disconnect(subDialog);//, SIGNAL(accepted()));
}

Sub dialog

MySubDialog::MySubDialog(QWidget* parent) : QDialog(parent)
{
  setGeometry(0, 0, 100, 100);

  button = new QPushButton(this);
  connect(button, SIGNAL(clicked()), this, SLOT(OnPush()));

  auto layout = new QHBoxLayout();
  layout->addWidget(button);
  setLayout(layout);
}

MySubDialog::~MySubDialog()
{
  delete button;
}

void MySubDialog::OnPush()
{
  std::cout << "Button Pushed" << std::endl;
  accepted();
}

If requested (and possible in StackOverflow), I can post the whole QtCreator project or header files for those classes.


Solution

  • I finally found out the issue. It was with the disconnect() statement that was not working. Changing it from

    disconnect(subDialog);
    

    to

    subDialog->disconnect();
    

    resolved the issue.