最近有一个需求是对QT UI 程序进行黑盒自动化测试.
目标程序
qt 3.X windows 平台
挑战
使用现有的市面上的测试框架无法捕获到 控件的数据. eg:
- 文本框、按钮 拿不到数据 无法定位点击.
- 各组件使用spy++ 显示 unname
解决
经过排查后 发现 原因是 QT 自绘组件导致的。 QT 自己渲染出了显示结果在屏幕上。 这种情况似乎在QT上还是挺常见的。
说复杂不复杂,说简单还是需要一点工作量:
现在我们的问题是 句柄拿不到数据.
句柄 <=> 我们的代码 <=> QT的数据
QT的控件基本都是Widget作为父类 . 所以我们要获取 需要操作的控件 的 Widget指针.
句柄 => Widget* => 转特定控件指针 => 操作数据 或者 触发动作
先看一下句柄怎么转Widget ,大致步骤如下:
Widget* wg = Widget.find(HANDLE hd);
QLabel* ql = (QLabel*)wg;
getText = ((*ql)+3)
getText();
之所以用 find 是因为 人家管理了所有的子类的HANDLE。
得到 Widget* 后如何知道它属于哪个控件子类的指针? Widget* 指针可以获取到当前控件的名字.eg: QLabel,然后我们 IDA 等分析 QLabel的各种方法在虚表中的偏移.
Widget::find 在哪里? 如果是使用的qt-mt.dll 则就是在其中的导出函数. 如果使用的是qtXwidgets.dll 则在其中:
最终我们将该程序编为一个 dll,在需要的时机 由外部测试 程序传入(RPC等等方式) 需要操作的句柄 和 动作. dll 通过一系列上面的函数 实现了 黑盒 调用QT.
总结
- QT 是自绘的
- 要想获取 文本框、标签 里的数据 ,或者设置数据 最佳的方式就是 注入 dll 调用 QT 自己的API来代理我们 获取数据 或者 操纵控件。
后记
在写这篇文章的时候 我在工作中操作的是 qt-mt.dll 而我本机环境 只有 qt5widgets.dll 。。。所以对于高版本的API也不能顺利的截图了。只能这样了。
|