QTest - 为基于 Qt 的库编写测试并公开 类
QTest - writing tests for Qt-based library and exposing classes
我有一个库(我们称之为 MyLib
),它具有以下结构:
mylib_global.h - 确定 Q_DECL_IMPORT
或 Q_DECL_EXPORT
是否在 MYLIBSHARED_EXPORT
前缀后面用于在编写使用库的应用程序时公开库的特定符号:
#ifndef MYLIB_GLOBAL_H
#define MYLIB_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(MYLIB_LIBRARY) // Set using DEFINES inside MyLib.pro
# define MYLIBSHARED_EXPORT Q_DECL_EXPORT
#else
# define MYLIBSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // MYLIB_GLOBAL_H
MyLib.h - 包含主要的 class,其中还包括各种其他 classes:
#include "mylib_global.h"
#include "MyLibOtherClass1.h"
#include "MyLibOtherClass2.h"
// Symbol will be exposed to the application that links against MyLib
// and can be directly interacted with from the application's code
class MYLIBSHARED_EXPORT MyLibMainClass {
public:
...
private:
MyLibOtherClassA ocA;
MyLibOtherClass1 oc1;
MyLibOtherClass2 oc2;
...
}
// Symbol will not be exposed to the application that links against MyLib
// however it is indirectly used through the `MyLibMainClass`
class MyLibOtherClassA {
...
}
源文件和其他classes (header+source) - 包含[=13=的底层逻辑的声明和定义].
如您所见,我混合使用了 classes - 有些是在与库的主 class 相同的头文件中定义的(它控制所有其他 class 实例) ,其他的在不同的头文件中。只有很少的 classes 带有 MYLIBSHARED_EXPORT
我需要公开它们以便在链接时能够访问库的功能。
这在编写普通应用程序时完全没问题。但是我决定编写一些测试(使用 Qt 测试框架),因为我经常更改代码(现在 :)),其中有许多复杂的依赖关系,我想确保在每次更改所有测试后我涵盖了所写的内容,并且功能与预期的一样。
在编写测试时,我需要访问所有 classes 以确保每个齿轮都朝着正确的方向转动(即使它没有暴露在外面)。我该如何处理?我可以在所有 class 之前添加 MYLIBSHARED_EXPORT
但这也将允许普通用户看到仅用于间接使用的内容。这可以使用另一个 #define
来更精确地调节,它可以通过项目的设置进行设置,并且只有在定义时所有没有前缀的 class 才会得到一个,否则它们将不会被公开。虽然此解决方案很可能会解决问题,但它会造成代码混乱,我希望尽可能避免这种情况。
因为许多功能未导出,您已经决定不测试最终交付物:您不能只获取最终产品和 运行 上面的测试工具。
然后,最简单的解决方案是将所有 headers/sources 包含到测试工具本身中。
您可以将源列表和 headers 分解到一个单独的文件中,该文件将包含在可交付成果和测试工具的项目文件中。这在 cmake 和 qmake 中都很容易做到。
我有一个库(我们称之为 MyLib
),它具有以下结构:
mylib_global.h - 确定
Q_DECL_IMPORT
或Q_DECL_EXPORT
是否在MYLIBSHARED_EXPORT
前缀后面用于在编写使用库的应用程序时公开库的特定符号:#ifndef MYLIB_GLOBAL_H #define MYLIB_GLOBAL_H #include <QtCore/qglobal.h> #if defined(MYLIB_LIBRARY) // Set using DEFINES inside MyLib.pro # define MYLIBSHARED_EXPORT Q_DECL_EXPORT #else # define MYLIBSHARED_EXPORT Q_DECL_IMPORT #endif #endif // MYLIB_GLOBAL_H
MyLib.h - 包含主要的 class,其中还包括各种其他 classes:
#include "mylib_global.h" #include "MyLibOtherClass1.h" #include "MyLibOtherClass2.h" // Symbol will be exposed to the application that links against MyLib // and can be directly interacted with from the application's code class MYLIBSHARED_EXPORT MyLibMainClass { public: ... private: MyLibOtherClassA ocA; MyLibOtherClass1 oc1; MyLibOtherClass2 oc2; ... } // Symbol will not be exposed to the application that links against MyLib // however it is indirectly used through the `MyLibMainClass` class MyLibOtherClassA { ... }
源文件和其他classes (header+source) - 包含[=13=的底层逻辑的声明和定义].
如您所见,我混合使用了 classes - 有些是在与库的主 class 相同的头文件中定义的(它控制所有其他 class 实例) ,其他的在不同的头文件中。只有很少的 classes 带有 MYLIBSHARED_EXPORT
我需要公开它们以便在链接时能够访问库的功能。
这在编写普通应用程序时完全没问题。但是我决定编写一些测试(使用 Qt 测试框架),因为我经常更改代码(现在 :)),其中有许多复杂的依赖关系,我想确保在每次更改所有测试后我涵盖了所写的内容,并且功能与预期的一样。
在编写测试时,我需要访问所有 classes 以确保每个齿轮都朝着正确的方向转动(即使它没有暴露在外面)。我该如何处理?我可以在所有 class 之前添加 MYLIBSHARED_EXPORT
但这也将允许普通用户看到仅用于间接使用的内容。这可以使用另一个 #define
来更精确地调节,它可以通过项目的设置进行设置,并且只有在定义时所有没有前缀的 class 才会得到一个,否则它们将不会被公开。虽然此解决方案很可能会解决问题,但它会造成代码混乱,我希望尽可能避免这种情况。
因为许多功能未导出,您已经决定不测试最终交付物:您不能只获取最终产品和 运行 上面的测试工具。
然后,最简单的解决方案是将所有 headers/sources 包含到测试工具本身中。
您可以将源列表和 headers 分解到一个单独的文件中,该文件将包含在可交付成果和测试工具的项目文件中。这在 cmake 和 qmake 中都很容易做到。