千家信息网

如何用C语言对Gtk及应用进行功能测试

发表于:2024-11-15 作者:千家信息网编辑
千家信息网最后更新 2024年11月15日,本篇文章给大家分享的是有关如何用C语言对Gtk及应用进行功能测试,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。如何测试你应用的功能。自动
千家信息网最后更新 2024年11月15日如何用C语言对Gtk及应用进行功能测试

本篇文章给大家分享的是有关如何用C语言对Gtk及应用进行功能测试,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

如何测试你应用的功能。

自动化测试用来保证你程序的质量以及让它以预想的运行。单元测试只是检测你算法的某一部分,而并不注重各组件间的适应性。这就是为什么会有功能测试,它有时也称为集成测试。

功能测试简单地与你的用户界面进行交互,无论它是网站还是桌面应用。为了展示功能测试如何工作,我们以测试一个 Gtk+ 应用为例。为了简单起见,这个教程里,我们使用 Gtk+ 2.0 教程的示例。

基础设置

对于每一个功能测试,你通常需要定义一些全局变量,比如 "用户交互时延" 或者 "失败的超时时间"(也就是说,如果在指定的时间内一个事件没有发生,程序就要中断)。

#define TTT_FUNCTIONAL_TEST_UTIL_IDLE_CONDITION(f) ((TttFunctionalTestUtilIdleCondition)(f)) #define TTT_FUNCTIONAL_TEST_UTIL_REACTION_TIME (125000) #define TTT_FUNCTIONAL_TEST_UTIL_REACTION_TIME_LONG (500000) typedef gboolean (*TttFunctionalTestUtilIdleCondition)(gpointer data); struct timespec ttt_functional_test_util_default_timeout = {   20,   0, };

现在我们可以实现我们自己的超时函数。这里,为了能够得到期望的延迟,我们采用 usleep 函数。

void ttt_functional_test_util_reaction_time() {   usleep(TTT_FUNCTIONAL_TEST_UTIL_REACTION_TIME); } void ttt_functional_test_util_reaction_time_long() {   usleep(TTT_FUNCTIONAL_TEST_UTIL_REACTION_TIME_LONG); }

直到获得控制状态,超时函数才会推迟执行。这对于一个异步执行的动作很有帮助,这也是为什么采用这么长的时延。

void ttt_functional_test_util_idle_condition_and_timeout(      TttFunctionalTestUtilIdleCondition idle_condition,      struct timespec *timeout,      pointer data) {   struct timespec start_time, current_time;   clock_gettime(CLOCK_MONOTONIC,                 &start_time);   while(TTT_FUNCTIONAL_TEST_UTIL_IDLE_CONDITION(idle_condition)(data)){     ttt_functional_test_util_reaction_time();     clock_gettime(CLOCK_MONOTONIC,                   ¤t_time);     if(start_time.tv_sec + timeout->tv_sec < current_time.tv_sec){       break;     }   }   ttt_functional_test_util_reaction_time(); }

与图形化用户界面交互

为了模拟用户交互的操作, Gdk 库 为我们提供了一些需要的函数。要完成我们的工作,我们只需要如下 3 个函数:

  • gdk_display_warp_pointer()

  • gdk_test_simulate_button()

  • gdk_test_simulate_key()

举个例子,为了测试按钮点击,我们可以这么做:

gboolean ttt_functional_test_util_button_click(GtkButton *button) {   GtkWidget *widget;   GdkWindow *window;   gint x, y;   gint origin_x, origin_y;   if(button == NULL ||      !GTK_IS_BUTTON(button)){     return(FALSE);   }   widget = button;   if(!GTK_WIDGET_REALIZED(widget)){     ttt_functional_test_util_reaction_time_long();   }   /* retrieve window and pointer position */   gdk_threads_enter();   window = gtk_widget_get_window(widget);   x = widget->allocation.x + widget->allocation.width / 2.0;   y = widget->allocation.y + widget->allocation.height / 2.0;   gdk_window_get_origin(window, &origin_x, &origin_y);   gdk_display_warp_pointer(gtk_widget_get_display(widget),                            gtk_widget_get_screen(widget),                            origin_x + x, origin_y + y);   gdk_threads_leave();   /* click the button */   ttt_functional_test_util_reaction_time();   gdk_test_simulate_button(window,                            x,                            y,                            1,                            GDK_BUTTON1_MASK,                            GDK_BUTTON_PRESS);   ttt_functional_test_util_reaction_time();   gdk_test_simulate_button(window,                            x,                            y,                            1,                            GDK_BUTTON1_MASK,                            GDK_BUTTON_RELEASE);   ttt_functional_test_util_reaction_time();   ttt_functional_test_util_reaction_time_long();   return(TRUE); }

我们想要保证按钮处于激活状态,因此我们提供一个空闲条件函数:

gboolean ttt_functional_test_util_idle_test_toggle_active(      GtkToggleButton **toggle_button) {   gboolean do_idle;   do_idle = TRUE;   gdk_threads_enter();   if(*toggle_button != NULL &&      GTK_IS_TOGGLE_BUTTON(*toggle_button) &&      gtk_toggle_button_get_active(*toggle_button)){     do_idle = FALSE;   }   gdk_threads_leave();   return(do_idle); }

测试场景

因为这个 Tictactoe 程序非常简单,我们只需要确保点击了一个 GtkToggleButton 按钮即可。一旦该按钮肯定进入了激活状态,功能测试就可以执行。为了点击按钮,我们使用上面提到的很方便的 util 函数。

如图所示,我们假设,填满***行,玩家 A 就赢,因为玩家 B 没有注意,只填充了第二行。

GtkWindow *window; Tictactoe *ttt; void* ttt_functional_test_gtk_main(void *) {   gtk_main();   pthread_exit(NULL); } void ttt_functional_test_dumb_player_b() {   GtkButton *buttons[3][3];   guint i;   /* to avoid race-conditions copy the buttons */   gdk_threads_enter();   memcpy(buttons, ttt->buttons, 9 * sizeof(GtkButton *));   gdk_threads_leave();   /* TEST 1 - the dumb player B */   for(i = 0; i < 3; i++){     /* assert player A clicks the button successfully */     if(!ttt_functional_test_util_button_click(buttons[0][i])){       exit(-1);     }     functional_test_util_idle_condition_and_timeout(          ttt_functional_test_util_idle_test_toggle_active,          ttt_functional_test_util_default_timeout,          &buttons[0][i]);     /* assert player B clicks the button successfully */     if(!ttt_functional_test_util_button_click(buttons[1][i])){       exit(-1);     }     functional_test_util_idle_condition_and_timeout(          ttt_functional_test_util_idle_test_toggle_active,          ttt_functional_test_util_default_timeout,          &buttons[1][i]);   } } int main(int argc, char **argv) {   pthread_t thread;   gtk_init(&argc, &argv);   /* start the tictactoe application */   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);   ttt = tictactoe_new();   gtk_container_add(window, ttt);   gtk_widget_show_all(window);   /* start the Gtk+ dispatcher */   pthread_create(&thread, NULL,                  ttt_functional_test_gtk_main, NULL);   /* launch test routines */   ttt_functional_test_dumb_player_b();   /* terminate the application */   gdk_threads_enter();   gtk_main_quit();   gdk_threads_leave();   return(0); }

以上就是如何用C语言对Gtk及应用进行功能测试,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注行业资讯频道。

0