Qt:如何将参数传递给Qt GUI测试?

huangapple go评论109阅读模式
英文:

Qt: how to pass arguments to a Qt GUI test?

问题

以下是代码部分的翻译:

Qt:如何将参数传递给Qt GUI测试
基本上,如何像普通的`main`一样传递参数给`QTEST_MAIN`?

要运行测试Qt GUI的测试,可以执行以下操作:

cat CMakeLists.txt 
cmake_minimum_required(VERSION 3.0)
project(foo)
enable_testing()
# 告诉CMake在需要时运行moc:
set(CMAKE_AUTOMOC ON)
# 由于moc文件在二进制目录中生成,告诉CMake始终在那里查找包含文件:
set(CMAKE_INCLUDE_CURRENT_DIR ON)
find_package(Qt5Test REQUIRED)
add_executable(foo foo.cpp)
add_test(foo foo)
target_link_libraries(foo Qt5::Test)

cat foo.cpp 
#include <QTest>
class Foo : public QObject {
    Q_OBJECT
private slots:
    void t1() { QVERIFY(true); }
};
QTEST_MAIN(Foo)
#include "foo.moc"

mkdir build; cd build; cmake ..; make all test
[ 25%] Automatic MOC for target foo
[ 25%] Built target foo_autogen
[100%] Built target foo
Running tests...
Test project /tmp/test/build
    Start 1: foo
1/1 Test #1: foo ..............................   Passed    0.01 sec

100% tests passed, 0 tests failed out of 1

Total Test time (real) =   0.02 sec

现在,如果我需要传递参数给QTEST_MAIN以配置Foot1中进行的测试,应该如何做?

基本上,没有Qt,可以执行以下操作:

set(TEST_MSG "hello" CACHE STRING "Message to print from Foo.")
add_test(NAME test COMMAND my_exe "${TEST_MSG}")

然后,在测试的主函数中:

int main(int argc, char **argv) {
  std::string msg = argv[1];
  Foo f(msg);

理想情况下,我希望像这样运行cmake:cmake -D TEST_MSG=world ..,然后稍后能够在Foo中检索TEST_MSG的内容(作为std::string)以进行配置。这是否可能?如果是,如何做?

我的理解是,这归结为"传递参数给QTEST_MAIN":这是否可能?如果是,如何在代码中检索这些参数(Foo)?

解决方案:

根据@jdfa的建议,这样可以解决问题:

git diff
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5c3c430..457ad7e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,5 +7,7 @@ set(CMAKE_AUTOMOC ON)
 set(CMAKE_INCLUDE_CURRENT_DIR ON)
 find_package(Qt5Test REQUIRED)
 add_executable(foo foo.cpp)
-add_test(foo foo)
 target_link_libraries(foo Qt5::Test)
+set(TEST_MSG "hello" CACHE STRING "Message to print from Foo.")
+add_test(NAME foo_tst COMMAND foo)
+set_property(TEST foo_tst PROPERTY ENVIRONMENT_MODIFICATION "TEST_MSG=set:${TEST_MSG}")

diff --git a/foo.cpp b/foo.cpp
index 844fca0..1d7e3da 100644
--- a/foo.cpp
+++ b/foo.cpp
@@ -1,8 +1,15 @@
 #include <QTest>
+#include <QtGlobal> // qgetenv
+#include <QString>
+#include <iostream> // cout
 class Foo : public QObject {
     Q_OBJECT
 private slots:
-    void t1() { QVERIFY(true); }
+    void t1() {
+      QString arg = qgetenv("TEST_MSG");
+      std::cout << "Foo arg: " << arg.toStdString() << std::endl;
+      QVERIFY(true);
+    }
 };
 QTEST_MAIN(Foo)
 #include "foo.moc"

这就是翻译好的部分。如果您需要进一步的信息或有其他问题,请随时告诉我。

英文:

Qt: how to pass arguments to a Qt GUI test?
Basically, how to pass arguments to QTEST_MAIN as you could have done with regular main?

To run a test for testing a Qt GUI, one can do the following:

>> cat CMakeLists.txt 
cmake_minimum_required(VERSION 3.0)
project(foo)
enable_testing()
# Tell CMake to run moc when necessary:
set(CMAKE_AUTOMOC ON)
# As moc files are generated in the binary dir, tell CMake to always look for includes there:
set(CMAKE_INCLUDE_CURRENT_DIR ON)
find_package(Qt5Test REQUIRED)
add_executable(foo foo.cpp)
add_test(foo foo)
target_link_libraries(foo Qt5::Test)

>> cat foo.cpp 
#include <QTest>
class Foo : public QObject {
    Q_OBJECT
private slots:
    void t1() { QVERIFY(true); }
};
QTEST_MAIN(Foo)
#include "foo.moc"

>> mkdir build; cd build; cmake ..; make all test
[ 25%] Automatic MOC for target foo
[ 25%] Built target foo_autogen
[100%] Built target foo
Running tests...
Test project /tmp/test/build
    Start 1: foo
1/1 Test #1: foo ..............................   Passed    0.01 sec

100% tests passed, 0 tests failed out of 1

Total Test time (real) =   0.02 sec

Ok, so far, so good.

Now say I have to pass arguments to QTEST_MAIN in order to configure Foo and what's tested in t1: how to do this?

Basically, without Qt, one could have done:

set(TEST_MSG "hello" CACHE STRING "Message to print from Foo.")
add_test(NAME test COMMAND my_exe "${TEST_MSG}")

And then in the main of the test:

int main(int argc, char **argv) {
  std::string msg = argv[1];
  Foo f(msg);

Ideally, I'd like to run cmake like so cmake -D TEST_MSG=world .. and later on be able to retrieve the content of TEST_MSG (as a std::string) in Foo (to configure it): is it possible? If yes, how?

My understanding it that this reduces to "pass arguments to QTEST_MAIN": is this possible? And if yes, how to retrieve these arguments in the code (Foo)?

SOLUTION

Following @jdfa, this works:

>> git diff
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5c3c430..457ad7e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,5 +7,7 @@ set(CMAKE_AUTOMOC ON)
 set(CMAKE_INCLUDE_CURRENT_DIR ON)
 find_package(Qt5Test REQUIRED)
 add_executable(foo foo.cpp)
-add_test(foo foo)
 target_link_libraries(foo Qt5::Test)
+set(TEST_MSG "hello" CACHE STRING "Message to print from Foo.")
+add_test(NAME foo_tst COMMAND foo)
+set_property(TEST foo_tst PROPERTY ENVIRONMENT_MODIFICATION "TEST_MSG=set:${TEST_MSG}")
diff --git a/foo.cpp b/foo.cpp
index 844fca0..1d7e3da 100644
--- a/foo.cpp
+++ b/foo.cpp
@@ -1,8 +1,15 @@
 #include <QTest>
+#include <QtGlobal> // qgetenv
+#include <QString>
+#include <iostream> // cout
 class Foo : public QObject {
     Q_OBJECT
 private slots:
-    void t1() { QVERIFY(true); }
+    void t1() {
+      QString arg = qgetenv("TEST_MSG");
+      std::cout << "Foo arg: " << arg.toStdString() << std::endl;
+      QVERIFY(true);
+    }
 };
 QTEST_MAIN(Foo)
 #include "foo.moc"

答案1

得分: 0

以下是您要翻译的内容:

"First of all, QTEST_MAIN creates tested object using default ctor. So even if you will create your own main function and will use QTEST_MAIN_IMPL instead of QTEST_MAIN - that will not help you to pass arguments to tested object."

"Second issue is that QTest executable will interpret your additional arguments as test filter (QTest cli reference)."

"But there is another way to configure your test objects. You can use environment variables for that:

set(TEST_MSG "hello" CACHE STRING "Message to print from Foo.")
add_test(NAME test COMMAND my_exe "${TEST_MSG}")
set_property(TEST test PROPERTY ENVIRONMENT_MODIFICATION "CUSTOM_ENV=set:${TEST_MSG}")"

"It will set CUSTOM_ENV variable with value ${TEST_MSG} for you test when it is started from ctest command. In tested object you can retrieve that value using qgetenv("CUSTOM_ENV"). So it will be possible to define default ctor and use it for any configuration."

英文:

There are few problems with your approach.

First of all, QTEST_MAIN creates tested object using default ctor. So even if you will create your own main function and will use QTEST_MAIN_IMPL instead of QTEST_MAIN - that will not help you to pass arguments to tested object.

Second issue is that QTest executable will interpret your additional arguments as test filter (QTest cli reference).

But there is another way to configure your test objects. You can use environment variables for that:

set(TEST_MSG "hello" CACHE STRING "Message to print from Foo.")
add_test(NAME test COMMAND my_exe "${TEST_MSG}")
set_property(TEST test  PROPERTY ENVIRONMENT_MODIFICATION "CUSTOM_ENV=set:${TEST_MSG}")

It will set CUSTOM_ENV variable with value ${TEST_MSG} for you test when it is started from ctest command. In tested object you can retrieve that value using qgetenv("CUSTOM_ENV"). So it will be possible to define default ctor and use it for any configuration.

huangapple
  • 本文由 发表于 2023年2月27日 02:52:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/75574293.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定