GUI應(yīng)用程序自動測試一直是個難題,通常的做法是先把人工測試過程錄制下來,然后去重放這個測試過程。這種方法的主要缺點(diǎn)是很難自動檢測運(yùn)行結(jié)果的正確性,所以很多人都不屑去使用它。其實(shí)工具總是有它的局限性,它能不能發(fā)揮它應(yīng)有的作用,還依賴于人的靈活運(yùn)用。即不能過分依賴于工具,也不能盲目排斥工具。
在質(zhì)量保證的過程中,人無疑是重要的,沒有什么比一次性寫出高質(zhì)量代碼有效的了。但事實(shí)是即使有良好的架構(gòu)設(shè)計,輔之于單元測試和代碼評審等一些有效實(shí)踐,仍然有些BUG成為漏網(wǎng)之魚,更何況很多團(tuán)隊這些工作做得并到位。單一工具和方法很難包醫(yī)百病,但各種方法和工具綜合起來使用的效果大不一樣了。
前段時間一位同事開發(fā)了一個GUI自動測試工具,我們把它用于BUG重現(xiàn)和壓力測試中,取得了不錯的效果。這里介紹一下DirectFB里面事件錄制和重放的方法:
獲得鍵盤設(shè)備:
dfb_input_enumerate_devices ((InputDeviceCallback)device_callback,
&context->keyboard_device, DICAPS_KEYS);
獲得鼠標(biāo)或觸摸屏設(shè)備:
dfb_input_enumerate_devices ((InputDeviceCallback)device_callback,
&context->mouse_device, DICAPS_AXES | DICAPS_BUTTONS);
向設(shè)備注冊事件監(jiān)聽函數(shù):
dfb_input_attach (context->mouse_device,
input_device_listener, context, &context->mouse_reaction);
dfb_input_attach (context->keyboard_device,
input_device_listener, context, &context->keyboard_reaction);
事件監(jiān)聽函數(shù):
static ReactionResult input_device_listener (const void *msg_data, void *ctx)
{
DFBContext *context = (DFBContext*)ctx;
DFBInputEvent *event = (DFBInputEvent*)msg_data;
event->locks = 0;
event->flags &= ~DIEF_LOCKS;
if (fwrite (msg_data, sizeof (DFBInputEvent), 1, context->file) != 1)
{
printf ("[%s]: fwrite Error errno = %d ", __func__, errno);
g_main_loop_quit (context->loop);
}
fflush(context->file);
return RS_OK;
}
事件重放函數(shù):
static gboolean replay_one_event (gpointer user_data)
{
DFBContext *context = (DFBContext*)user_data;
off_t cur = 0;
DFBInputEvent event = context->event;
if(event.type == DIET_KEYPRESS || event.type == DIET_KEYRELEASE)
{
dfb_input_dispatch (context->keyboard_device, &event);
}
else
{
dfb_input_dispatch (context->mouse_device, &event);
}
if (fread (&context->event, sizeof (DFBInputEvent), 1, context->file) == 1)
{
guint ms = (context->event.timestamp.tv_sec - event.timestamp.tv_sec) * 1000
+ (context->event.timestamp.tv_usec - event.timestamp.tv_usec)/1000;
g_timeout_add (ms, replay_one_event, user_data);
}
else
{
g_main_loop_quit (context->loop);
}
return FALSE;
}
注意:DirectFB中的筆點(diǎn)事件是以相對坐標(biāo)方式表示的,所以要保證重放時光標(biāo)在同樣的初始位置。如果DirectFB以多進(jìn)程的方式運(yùn)行,這個程序可以是一個獨(dú)立的進(jìn)程,否則要放到應(yīng)用程序的進(jìn)程中才行。