DevExpress WinForms中文教程 - 如何通过UI测试自动化增强应用可靠性?(二)

DevExpress WinForm拥有180+组件和UI库,能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForm能完美构建流畅、美观且易于使用的应用程序,无论是Office风格的界面,还是分析处理大批量的业务数据,它都能轻松胜任!

UI自动化测试利用特定的工具/框架来模拟用户与界面的交互,并帮助确保应用程序满足相关的最终用户需求。当与其他测试方法(API测试、单元测试等)结合使用时,UI自动化可以提高应用程序的稳定性,减少花在手工测试上的时间,当然还可以提高用户满意度。在本文中,我们将向您展示如何使用UI自动化在Visual Studio 2022中编写简单/高级UI测试。

DevExpress WinForms中文教程图集

在开始之前,我们先看看UI测试的优势:

  • UI测试以应用程序为目标,允许您测试应用程序流(端到端测试),涵盖应用程序的所有元素,包括UI和业务逻辑(而单元测试侧重于测试应用程序中的单个模块、类或组件)。
  • UI测试有助于识别与导航、数据输入和跨不同屏幕的工作流相关的问题,这些问题可能不会被其他测试捕获。
  • UI测试为测试复杂场景和边缘情况提供了效率和可伸缩性(单元测试对于测试单个代码单元是必不可少的)。请注意,UI测试可能需要更长的时间来执行,因为它们与UI交互,并在应用程序开发管道中稍后运行(单元测试通常更快,并且在提交到存储库之前进行了检查)。

获取DevExpress v23.2.5正式版下载(Q技术交流:909157416)

在上文中(点击这里回顾>>),我们为大家介绍了UI测试自动化是如何工作的、开始创建UI自动化测试等,本文将继续介绍如何创还能UI自动化测试。

创建UI自动化测试
3. 为登录表单创建测试

在进行测试之前,我想澄清几点:

  • AutomationElement.RootElement静态属性包含根元素,使用此属性访问应用程序。
  • AutomationElement.FindFirst方法允许您找到一个特定的UI元素:
AutomationElement logInFormElement = AutomationElement.RootElement.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "CRM Log In Form"));

FindFirst方法有两个参数,第一个参数(scope)指定搜索的范围,第二个参数(条件)指定要匹配的标准(在我的例子中,这是一个AutomationName = "CRM Log In Form"的表单)。

UI控件可以根据其他设置(例如,Text)自动“计算”AutomationName。
如果需要,您可以显式地设置AutomationName属性或处理DXAccessible.QueryAccessibleInfo事件,来向DevExpress UI元素提供可访问性信息。

  • 在某些情况下,被测试的应用程序可能没有时间生成UI元素,因为UI自动化框架执行操作非常快。因此,我们建议使用“poll”间隔。
    下面的例子实现了FindFirstWithTimeout方法,并反复调用FindFirst(带有延迟),直到找到指定的UI元素:
public static class AutomationElementExtensions {
public static AutomationElement FindFirstWithTimeout(this AutomationElement @this,
TreeScope scope, Condition condition, int timeoutMilliseconds = 1000) {
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
do {
var result = @this.FindFirst(scope, condition);
if (result != null)
return result;
Thread.Sleep(100);
}
while (stopwatch.ElapsedMilliseconds < timeoutMilliseconds);
return null;
}
}

下面的测试将执行以下操作:

  • 输入错误的登录名和密码。
  • 确保在“LogIn”表单中显示错误消息。
[Test]
public void NonExistingUsernameLoginTest() {
afterLogInAction = CheckErrorLabel;
LogIn("TestNonExistingUser", "123456");
}
void CheckErrorLabel() {
AutomationElement errorLabelElement = loginForm.FindFirstByNameWithTimeout(
TreeScope.Children,
"Invalid User or Password",
10000);
Assert.IsNotNull(errorLabelElement);
}
void LogIn(string username, string password) {
// Finds the LogIn form and its main UI elements.
loginForm = AutomationElement.RootElement.FindFirstByNameWithTimeout(
TreeScope.Children,
logInFormAccessbleName,
10000);
AutomationElement usernameElement = loginForm.FindFirstByNameWithTimeout(TreeScope.Children, usernameAccessbleName, 10000);
AutomationElement passwordElement = loginForm.FindFirstByNameWithTimeout(TreeScope.Children, passwordAccessbleName, 10000);
AutomationElement logInButtonElement = loginForm.FindFirstByNameWithTimeout(TreeScope.Children, logInButtonAccessbleName, 10000);// Gets automation patterns to fill "UserName" and "Password" inputs (editors).
ValuePattern usernameValuePattern = (ValuePattern)usernameElement.GetCurrentPattern(ValuePattern.Pattern);
ValuePattern passwordValuePattern = (ValuePattern)passwordElement.GetCurrentPattern(ValuePattern.Pattern);
InvokePattern invokePattern = (InvokePattern)logInButtonElement.GetCurrentPattern(InvokePattern.Pattern);// Sets editor values. Fills in username and password input fields.
usernameValuePattern.SetValue(username);
passwordValuePattern.SetValue(password);
invokePattern.Invoke();// Performs an action after a log in attempt.
afterLogInAction?.Invoke();
}

正如您所看到的,编写测试可以归结为获取一个AutomationElement并调用它的模式方法。

4. 为客户表单创建一个测试

让我们考虑一个更复杂的情况,并在DevExpress WinForm数据网格(GridControl)中测试数据编辑。DevExpress数据网格包含一个带有布尔值的“Is Modified”未绑定列,该列的值表示用户是否修改了“Name”列的值。

我使用TablePattern与网格控件一起工作,下面的例子展示了如何编写一个测试来修改我们的WinForms Grid中的客户名称,并检查“Is Modified”列中的值是否从false变为true:

[Test]
public void ModifiedCustomerTest() {
LogIn(testExistingUserLogin, testExistingUserPassword);// Finds the GridControl and gets its TablePattern.
customersForm = AutomationElement.RootElement.FindFirstByNameWithTimeout(
TreeScope.Children,
customersFormAccessbleName,
10000);
AutomationElement customersGrid = customersForm.FindFirstByIdWithTimeout(
TreeScope.Children,
customersGridAutomationID,
10000);
TablePattern customersTablePattern = (TablePattern)customersGrid.GetCurrentPattern(TablePattern.Pattern);// Activates a cell within the GridControl.
AutomationElement cellToUpdate = customersTablePattern.GetItem(1, 1);
InvokePattern testCellInvokePattern = (InvokePattern)cellToUpdate.GetCurrentPattern(InvokePattern.Pattern);
testCellInvokePattern.Invoke();// Modifies the cell's value.
AutomationElement editingControl = customersGrid.FindFirstByNameWithTimeout(TreeScope.Descendants, "Editing control", 1000);
ValuePattern editedCellValuePattern = (ValuePattern)editingControl.GetCurrentPattern(ValuePattern.Pattern);
editedCellValuePattern.SetValue("Value updated!");
Thread.Sleep(1000); // Sets a delay for demonstration purposes.// Selects the next data row.
AutomationElement nextRowCell = customersTablePattern.GetItem(2, 1);
SelectionItemPattern selectionItemPattern = (SelectionItemPattern)TreeWalker.ControlViewWalker.GetParent(nextRowCell).GetCurrentPattern(SelectionItemPattern.Pattern);
selectionItemPattern.Select();
Thread.Sleep(1000);// Checks if the value in the "Is Modified" column has changed.
int isModiedColumnIndex = customersTablePattern.Current.GetColumnHeaders().ToList().FindIndex(h => h.Current.Name == "Is Modified");
AutomationElement isModifiedCell = customersTablePattern.GetItem(1, isModiedColumnIndex);
ValuePattern isModifiedCellValuePattern = (ValuePattern)isModifiedCell.GetCurrentPattern(ValuePattern.Pattern);
Assert.AreEqual(isModifiedCellValuePattern.Current.Value, "Checked");
}
5. 运行测试

要运行我刚刚创建的测试,将用tests展开项目(“TestRunner”),右键单击*.cs文件来调用上下文菜单,然后单击"Run Tests"。

DevExpress WinForms中文教程图集

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/610742.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

选择正确的Go Module Path

最近我在查看项目代码时&#xff0c;注意到有人在go.mod文件中将module path写为com.example.foo了。根据这个写法&#xff0c;相信屏幕前的读者也可以推断出这位开发人员可能是从Java阵营转到Go的。实际开发中可能有很多开发者会使用类似的内容作为module path&#xff0c;但这…

STM32 SPI CRC polynominal = 7 含义

STM32 SPI CRC polynominal 7 含义 1. CRC校验1.1 多项式公式1.2 多项式简记式1.3 数据宽度1.4 初始值与结果异或值1.5 输入值反转与输出值反转 2. 常见的CRC算法3. CRC校验算法前置知识3.1 异或3.2 模2加法3.3 模2减法3.4 模2除法 4. CRC原理5. 计算示例6. STM32 SPI 中的CRC…

C++常用技巧与算法总结(简洁)

前言警告&#xff1a; 1、注意数据的边界&#xff0c;数组不能越界&#xff01; 2、 时间复杂度 3、开long long 4、注意输出的四舍五入 printf("%d %.0f\n",k,sum*1.0/k);//double类型输出会自动四舍五入&#xff1b; 5、让Dev C支持C11 先在dev的【工具】里找…

SpringMVC中拦截所有请求后,<mvc:resources/>不起作用

报错显示 出现这种问题的前提是&#xff0c;用DispatcherServlet将所有的请求拦截&#xff0c;然后导致静态资源无法访问。 拦截代码如下&#xff0c;配置卸载web.xml文件中。 <servlet><servlet-name>dispatcherServlet</servlet-name><servlet-class&…

Apache SeaTunnel 社区 3 月月报

各位热爱 SeaTunnel 的小伙伴们&#xff0c;SeaTunnel 社区 3 月月报来啦&#xff01;这里将记录 SeaTunnel 社区每个月的重要更新&#xff0c;并评选出月度之星&#xff0c;欢迎关注。 SeaTunnel 月度 Merge Stars 感谢以下小伙伴 3 月为 Apache SeaTunnel 做的精彩贡献&…

libVLC 提取视频帧使用QWidget渲染

在前面的文章中&#xff0c;我们使用libvlc_media_player_set_hwnd设置了视频的显示的窗口。 libvlc_media_player_set_hwnd(vlc_mediaPlayer, (void *)ui.widgetShow->winId()); 如果我们想要提取每一帧数据&#xff0c;将数据渲染到QWidget上&#xff0c;该如何操作呢&a…

使用Android Studio制作一个蓝牙软件 ---(一)

一、创建项目&#xff08;项目名称---BluetoothActivity&#xff09; 二、创建HomeActivity页面 1.点击一个文件夹 --- 鼠标右击 --- 新建 --- Acyivity --- Empty Views Activity 三、创建styles.xml 点击 values文件夹 --- 鼠标右击 --- 新建 --- Values Resource File sty…

IJKPLAYER源码分析-iOS端显示

1 简介 1.1 EAGL(Embedded Apple Graphics Library) 与Android系统使用EGL连接OpenGL ES与原生窗口进行surface输出类似&#xff0c;iOS则用EAGL将CAEAGLLayer作为OpenGL ES输出目标。 与 Android EGL 不同的是&#xff0c;iOS EAGL 不会让应用直接向 BackendFrameBuffer 和 F…

AJAX 入门到实战 第1天 2024 笔记

1.1-AJAX入门与axios使用 1.2-认识URL 1.3-查询参数 1.4-案例_地区查询 <script src"https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script><script>/*获取地区列表: http://hmajax.itheima.net/api/area查询参数:pname: 省份或直辖市…

2024年认证杯A题保暖纤维的保暖能力完整思路代码论文讲解与分析

保暖纤维的保暖能力建模 摘要 本文针对保暖纤维的保暖能力建模问题进行了深入研究。首先,文章指出现有的一些保暖性能指标,如热导率、热阻值、CLO值等,存在一些局限性,无法全面反映保暖材料的实际保暖性能。因此,本文提出了建立一个更加完善的保暖能力评价指标体系,包括热传导…

文献学习-33-一个用于生成手术视频摘要的python库

VideoSum: A Python Library for Surgical Video Summarization Authors: Luis C. Garcia-Peraza-Herrera, Sebastien Ourselin, and Tom Vercauteren Source: https://arxiv.org/pdf/2303.10173.pdf 这篇文章主要关注的是如何通过视频摘要来简化和可视化手术视频&#xff0c…

SpringCloud集成Skywalking链路追踪和日志收集

1. 下载Agents https://archive.apache.org/dist/skywalking/java-agent/9.0.0/apache-skywalking-java-agent-9.0.0.tgz 2. 上传到服务器解压 在Spring Cloud项目中&#xff0c;每部署一个服务时&#xff0c;就拷贝一份skywalking的agent文件到该服务器上并解压。不管是部署…