2

I have 2 questions:

  1. How can I access a QFileDialog and write the path of a file in the "File name" field using the Qt Test module?

    I am asking that because I am developing some GUI tests in Qt and now I need to open a text file. The following code creates the QFileDialog and gets the file path:

    QString filePath = QFileDialog::getOpenFileName(
                                this,
                                "Open",
                                "",
                                tr("Text Files (*.txt)") );
    
  2. If I am using a thread (QThread) to load the content in this text file, how can I wait for this thread to finish in my GUI tests?

    I know I can use the QTest::qSleep( milliseconds ); command, but I don't think it is a good practice in this case.

If possible show me an example, please.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
KelvinS
  • 2,870
  • 8
  • 34
  • 67

1 Answers1

2
  1. Unfortunately, it's not possible using the Qt Test module. You have several choices:

    1. Add test hooks that bypass that dialog: you need to instrument your code to make it testable. You could e.g. set a testFile property on the object that asks for the file to a file path, if the property is set the object can skip asking for the file.

      const char k_testFile[] = "k_testFile";
      
      MyClass::foo() {
        ...
        auto testFile = property(k_testFile);
        auto filePath = testFile.isNull()
          ? QFileDialog::getOpenFilePath(...)
          : testFile.toString();
        ...
      }
      
    2. Use a non-native dialog and then it's a normal widget that you can test using Qt Test.

    3. Use platform-specific means of finding the native dialog and interacting with it. You'd need to implement it for every platform you intend to test on.

  2. You should be emitting a signal after the file has been loaded. The test can wait for that signal. You don't even need to use an explicit thread to load the file, an idiomatic way of asynchronously loading a file is:

    QString filePath = ...;
    QtConcurrent::run(ioPool, [this, filePath]{
      auto data = MyLoader::load(filePath);
      emit haveFileData(data);
    });
    

    The class where you invoke this code should have a haveFileData signal that some other code connects to and proceeds as desired. The ioPool is the thread pool used for I/O bound operations, it could be QThredPool::globalInstance() if you want the global pool to be the I/O pool. The CPU- and I/O-bound thread pools should be separate.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • Thanks, Kuba. 1. I don't know what is "test hooks", but I will search about it. 2. This is not an option for my project right now. :/ 3. I didn't quite understand this option. I am developing using Windows platform, but the application is multi-platform, then, I don't think this is a valid option for me. – KelvinS Aug 09 '16 at 21:12
  • Re 3. You'd need to add test hooks that manipulate the platform dialog on every platform you test on. It'll be relatively easy on Windows and OS X. It'll be harder on Linux, where the "native" dialog might be a Qt dialog, a KDE dialog, or a Gnome dialog. – Kuba hasn't forgotten Monica Aug 09 '16 at 21:20
  • Actually, I just need it for Windows and OS X, then, maybe this option is a possible solution. – KelvinS Aug 09 '16 at 22:27