用C语言对Gtk+应用进行功能测试

简介:

用C语言对Gtk+应用进行功能测试

这个简单教程教你如何测试你应用的功能。

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

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

基础设置

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


 
 
  1. #define TTT_FUNCTIONAL_TEST_UTIL_IDLE_CONDITION(f) ((TttFunctionalTestUtilIdleCondition)(f)) 
  2. #define TTT_FUNCTIONAL_TEST_UTIL_REACTION_TIME (125000) 
  3. #define TTT_FUNCTIONAL_TEST_UTIL_REACTION_TIME_LONG (500000) 
  4. typedef gboolean (*TttFunctionalTestUtilIdleCondition)(gpointer data); 
  5. struct timespec ttt_functional_test_util_default_timeout = { 
  6.   20, 
  7.   0, 
  8. }; 

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


 
 
  1. void 
  2. ttt_functional_test_util_reaction_time() 
  3.   usleep(TTT_FUNCTIONAL_TEST_UTIL_REACTION_TIME); 
  4. void 
  5. ttt_functional_test_util_reaction_time_long() 
  6.   usleep(TTT_FUNCTIONAL_TEST_UTIL_REACTION_TIME_LONG); 

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


 
 
  1. void 
  2. ttt_functional_test_util_idle_condition_and_timeout( 
  3.      TttFunctionalTestUtilIdleCondition idle_condition, 
  4.      struct timespec *timeout, 
  5.      pointer data) 
  6.   struct timespec start_time, current_time
  7.   clock_gettime(CLOCK_MONOTONIC, 
  8.                 &start_time); 
  9.   while(TTT_FUNCTIONAL_TEST_UTIL_IDLE_CONDITION(idle_condition)(data)){ 
  10.     ttt_functional_test_util_reaction_time(); 
  11.     clock_gettime(CLOCK_MONOTONIC, 
  12.                   &current_time); 
  13.     if(start_time.tv_sec + timeout->tv_sec < current_time.tv_sec){ 
  14.       break; 
  15.     } 
  16.   } 
  17.   ttt_functional_test_util_reaction_time(); 

与图形化用户界面交互

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

  • gdk_display_warp_pointer()
  • gdk_test_simulate_button()
  • gdk_test_simulate_key()

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


 
 
  1. gboolean 
  2. ttt_functional_test_util_button_click(GtkButton *button) 
  3.   GtkWidget *widget; 
  4.   GdkWindow *window; 
  5.   gint x, y; 
  6.   gint origin_x, origin_y; 
  7.   if(button == NULL || 
  8.      !GTK_IS_BUTTON(button)){ 
  9.     return(FALSE); 
  10.   } 
  11.   widget = button; 
  12.   if(!GTK_WIDGET_REALIZED(widget)){ 
  13.     ttt_functional_test_util_reaction_time_long(); 
  14.   } 
  15.   /* retrieve window and pointer position */ 
  16.   gdk_threads_enter(); 
  17.   window = gtk_widget_get_window(widget); 
  18.   x = widget->allocation.x + widget->allocation.width / 2.0; 
  19.   y = widget->allocation.y + widget->allocation.height / 2.0; 
  20.   gdk_window_get_origin(window, &origin_x, &origin_y); 
  21.   gdk_display_warp_pointer(gtk_widget_get_display(widget), 
  22.                            gtk_widget_get_screen(widget), 
  23.                            origin_x + x, origin_y + y); 
  24.   gdk_threads_leave(); 
  25.   /* click the button */ 
  26.   ttt_functional_test_util_reaction_time(); 
  27.   gdk_test_simulate_button(window, 
  28.                            x, 
  29.                            y, 
  30.                            1, 
  31.                            GDK_BUTTON1_MASK, 
  32.                            GDK_BUTTON_PRESS); 
  33.   ttt_functional_test_util_reaction_time(); 
  34.   gdk_test_simulate_button(window, 
  35.                            x, 
  36.                            y, 
  37.                            1, 
  38.                            GDK_BUTTON1_MASK, 
  39.                            GDK_BUTTON_RELEASE); 
  40.   ttt_functional_test_util_reaction_time(); 
  41.   ttt_functional_test_util_reaction_time_long(); 
  42.   return(TRUE); 

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


 
 
  1. gboolean 
  2. ttt_functional_test_util_idle_test_toggle_active( 
  3.      GtkToggleButton **toggle_button) 
  4.   gboolean do_idle; 
  5.   do_idle = TRUE
  6.   gdk_threads_enter(); 
  7.   if(*toggle_button != NULL && 
  8.      GTK_IS_TOGGLE_BUTTON(*toggle_button) && 
  9.      gtk_toggle_button_get_active(*toggle_button)){ 
  10.     do_idle = FALSE
  11.   } 
  12.   gdk_threads_leave(); 
  13.   return(do_idle); 

测试场景

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

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


 
 
  1. GtkWindow *window; 
  2. Tictactoe *ttt; 
  3. void* 
  4. ttt_functional_test_gtk_main(void *) 
  5.   gtk_main(); 
  6.   pthread_exit(NULL); 
  7. void 
  8. ttt_functional_test_dumb_player_b() 
  9.   GtkButton *buttons[3][3]; 
  10.   guint i; 
  11.   /* to avoid race-conditions copy the buttons */ 
  12.   gdk_threads_enter(); 
  13.   memcpy(buttons, ttt->buttons, 9 * sizeof(GtkButton *)); 
  14.   gdk_threads_leave(); 
  15.   /* TEST 1 - the dumb player B */ 
  16.   for(i = 0; i < 3; i++){ 
  17.     /* assert player A clicks the button successfully */ 
  18.     if(!ttt_functional_test_util_button_click(buttons[0][i])){ 
  19.       exit(-1); 
  20.     } 
  21.     functional_test_util_idle_condition_and_timeout( 
  22.          ttt_functional_test_util_idle_test_toggle_active, 
  23.          ttt_functional_test_util_default_timeout, 
  24.          &buttons[0][i]); 
  25.     /* assert player B clicks the button successfully */ 
  26.     if(!ttt_functional_test_util_button_click(buttons[1][i])){ 
  27.       exit(-1); 
  28.     } 
  29.     functional_test_util_idle_condition_and_timeout( 
  30.          ttt_functional_test_util_idle_test_toggle_active, 
  31.          ttt_functional_test_util_default_timeout, 
  32.          &buttons[1][i]); 
  33.   } 
  34. int 
  35. main(int argc, char **argv) 
  36.   pthread_t thread; 
  37.   gtk_init(&argc, &argv); 
  38.   /* start the tictactoe application */ 
  39.   window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
  40.   ttt = tictactoe_new(); 
  41.   gtk_container_add(window, ttt); 
  42.   gtk_widget_show_all(window); 
  43.   /* start the Gtk+ dispatcher */ 
  44.   pthread_create(&thread, NULL
  45.                  ttt_functional_test_gtk_main, NULL); 
  46.   /* launch test routines */ 
  47.   ttt_functional_test_dumb_player_b(); 
  48.   /* terminate the application */ 
  49.   gdk_threads_enter(); 
  50.   gtk_main_quit(); 
  51.   gdk_threads_leave(); 
  52.   return(0); 

(题图:opensource.com)


本文作者:Joël Krähemann

来源:51CTO

相关文章
|
19天前
|
Java 测试技术 数据安全/隐私保护
软件测试中的自动化策略与工具应用
在软件开发的快速迭代中,自动化测试以其高效、稳定的特点成为了质量保证的重要手段。本文将深入探讨自动化测试的核心概念、常见工具的应用,以及如何设计有效的自动化测试策略,旨在为读者提供一套完整的自动化测试解决方案,帮助团队提升测试效率和软件质量。
|
22天前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
43 5
|
22天前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
21天前
|
机器学习/深度学习 算法 数据挖掘
C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出
本文探讨了C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出。文章还介绍了C语言在知名机器学习库中的作用,以及与Python等语言结合使用的案例,展望了其未来发展的挑战与机遇。
39 1
|
21天前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
49 1
|
22天前
|
网络协议 物联网 数据处理
C语言在网络通信程序实现中的应用,介绍了网络通信的基本概念、C语言的特点及其在网络通信中的优势
本文探讨了C语言在网络通信程序实现中的应用,介绍了网络通信的基本概念、C语言的特点及其在网络通信中的优势。文章详细讲解了使用C语言实现网络通信程序的基本步骤,包括TCP和UDP通信程序的实现,并讨论了关键技术、优化方法及未来发展趋势,旨在帮助读者掌握C语言在网络通信中的应用技巧。
34 2
|
22天前
|
存储 算法 C语言
用C语言开发游戏的实践过程,包括选择游戏类型、设计游戏框架、实现图形界面、游戏逻辑、调整游戏难度、添加音效音乐、性能优化、测试调试等内容
本文探讨了用C语言开发游戏的实践过程,包括选择游戏类型、设计游戏框架、实现图形界面、游戏逻辑、调整游戏难度、添加音效音乐、性能优化、测试调试等内容,旨在为开发者提供全面的指导和灵感。
37 2
|
22天前
|
Java 测试技术 API
软件测试中的自动化测试框架选择与应用##
在快速迭代的软件开发周期中,选择合适的自动化测试框架对于提高软件质量和开发效率至关重要。本文探讨了当前流行的几种自动化测试框架的特点和适用场景,旨在为软件开发团队提供决策依据。 ##
|
24天前
|
机器学习/深度学习 人工智能 安全
探索AI在软件工程中的最新应用:自动化测试与代码审查
探索AI在软件工程中的最新应用:自动化测试与代码审查
|
18天前
|
存储 C语言 开发者
【C语言】字符串操作函数详解
这些字符串操作函数在C语言中提供了强大的功能,帮助开发者有效地处理字符串数据。通过对每个函数的详细讲解、示例代码和表格说明,可以更好地理解如何使用这些函数进行各种字符串操作。如果在实际编程中遇到特定的字符串处理需求,可以参考这些函数和示例,灵活运用。
39 10
下一篇
DataWorks