make UI testing more stablize

copy from http://www.cnblogs.com/realdigit/archive/2011/05/11/2042806.html

UITestControl.WaitForControlXXX() methods

Description

WaitForControlReady

Waits for the control to be ready to accept mouse and keyboard input. The engine implicitly calls this API for all actions to wait for the control to be ready before doing any operation. However, in certain esoteric scenario, you may have to do explicit call.

WaitForControlEnabled

Waits for the control to be enabled when the wizard is doing some asynchronous validation of the input by making calls to the server. For example, you can method to wait for the Next button of the wizard to be enabled (). For an example of this method, see Walkthrough: Creating, Editing and Maintaining a Coded UI Test.

WaitForControlExist

Waits for the control to appear on the UI. For example, you are expecting an error dialog after the application has done the validation of the parameters. The time taken for validation is variable. You can use this method to wait for the error dialog box.

WaitForControlNotExist

Waits for the control to disappear from the UI. For example, you can wait for the progress bar to disappear.

WaitForControlPropertyEqual(String, Object)

Waits for the specified property of the control to have the given value. For example, you wait for the status text to change to Done.

WaitForControlPropertyNotEqual(String, Object)

Waits for the specified property of the control to have the opposite of a specified value. For example, you wait for the edit box to be not read-only, that is, editable.

WaitForControlCondition(Predicate(Of UITestControl))

Waits for the specified predicate returns to be true. This can be used for complex wait operation (like OR conditions) on a given control. For example, you can wait until the status text is Succeeded or Failed as shown in the following code:

WaitForCondition(Of T)(T, Predicate(Of T))

All the previous methods are instance methods of UITestControl. This method is a static method. This method also waits for the specified predicate to be true but it can be used for complex wait operation (like OR conditions) on multiple controls. For example, you can wait until the status text is Succeeded or until an error message appears, as shown in the following code:

dsfs

 

 

 

 

如何使用

这些方法,其实无论是测试Winform,还是测试Web,WPF,Silverlight,都可以使用,因为Winform理解起来最简单,所以这里以Winform程序为例进行说明。

一.WaitForControlExist()

作用:等待某一个控件,直到它出现为止。

返回值:bool类型值,控件是否在规定时间内出现

典型的使用场景:测试Web程序,当我们点击某一个链接,我们需要等待某一个页面出现。又如测试Winform程序,我们点击“提交”按钮,然后等待“提交成功!”弹出框出现。或者用于一些动态生成的控件。

举例:

Act.1输入账号密码,点击登陆

Act.2 这个时候通过网络会送您的登录信息,确认无误后弹出系统主窗口,然后我们想点击“用户管理”->“添加用户”

未优化代码:

1 UI用户名Edit.Text = " Admin " ;
2
3 UI密码Edit.Text = " 123456 " ;
4
5 Mouse.Click(UI登陆Button, new Point( 1 , 1 ));
6
7 Mouse.Click(UI用户管理MenuItem, new Point( 1 , 1 ));
8
9 Mouse.Click(UI添加用户MenuItem, new Point( 1 , 1 ));

可能造成的问题:

在Mouse.Click(UI登陆Button, new Point(1 , 1))之后就直接Mouse.Click(UI用户管理MenuItem, new point(1 , 1))了,但是这个时候,可能因为网速或服务器处理速度,信息还没返回,这个时候还在登录界面,系统主窗口还未弹出,所以“UI用户管理MenuItem”是不存在的,也就没法点击,这样,测试代码可能会在执行的时候报错。

优化过后的代码:

1 UI用户名Edit.Text = " Admin " ;
2
3 UI密码Edit.Text = " 123456 " ;
4
5 Mouse.Click(UI登陆Button, new Point( 1 , 1 ));
6
7 UI系统主窗口Window. WaitForControlExist( 20000 ); // 等待“UI系统主窗口Window”出现,最多20秒,一旦“UI系统主窗口Window”出现,立即结束等待,执行下一句代码。
8
9 Mouse.Click(UI用户管理MenuItem, new Point( 1 , 1 ));
10
11 Mouse.Click(UI添加用户MenuItem, new Point( 1 , 1 ));

二.WaitForControlNotExist()

作用:和WaitForControlExist相反,它是等待某一个控件,直到它消失为止。

返回值:bool类型值,控件是否在规定时间内消失。

典型的使用场景:点击页面或窗体上的关闭按钮,等待对应的页面或窗体关闭。或者用于执行了某个操作后,界面上的某些控件会消失。

举例:

现在想要点击“取消”按钮,退出系统登录模块,并验证是否退出成功。

未优化代码:

1 Mouse.Click(UI取消Button, new Point( 1 , 1 ));
2
3 bool isClosed = ! (UI系统登录Window.Exists);
4
5 Assert.isTrue(isClosed, " 未成功退出该模块 " );

可能造成的问题:

看上去是没有问题的,但您一定要相信我们的Windows大哥随时可能会出现这样的情况:

于是就被卡在这里了,当然,卡完了他是可以关闭的,不过运行中的代码可不会等他卡完。

于是代码在执行这一句“bool isClosed = !(UI系统登录Window.Exists);”时,得到一个false,然后接下来断言就会失败。

优化过后的代码:

1 Mouse.Click(UI取消Button, new Point( 1 , 1 ));
2
3 bool isClosed = UI系统登录Window. WaitForControlNotExist( 20000 ); // 等待“UI系统登录Window”消失,最多等20秒,一旦消失,立即结束等待,返回True,执行下一句代码。
4
5 Assert.isTrue(isClosed, " 未成功退出该模块 " );

三.WaitForControlPropertyEqual()

作用:等待某个控件的属性的变化,直到它变换为指定的值。

返回值:bool类型值,是否在规定时间内属性是否变换为指定值。

典型的使用场景:执行某个操作之后,窗体或页面上的某一个控件的属性会发生变化,而且这个变化是可以预期的。

举例:

Act.1 为了修改用户头像,现在我们要上传一个文件,假设这个时候已经选择了要上传的文件,点击开始上传

Act.2 上传完成后,点击确认,提交信息

未优化代码:

1 Mouse.Click(UI开始上传Button, new Point( 1 , 1 ));
2
3 Playback.Wait( 10000 ); // 也可以用Thread.Sleep(10000);
4
5 Mouse.Click(UI确认Button, new Point( 1 , 1 ));

可能造成的问题:

一看就可以发现,中间等待10秒。

10秒难道就够了?万一刚好是11秒呢?或者可能要等个30秒呢?等待时间过短,可能还未上传结束就开始点击“确认”按钮了。

有的人可能干脆会用“Playback.Wait(30000);” ,但是这会出现我们之前提到的问题:万一1秒就上传成功了呢?那不是还要等29秒?测试不就卡在那里了。

其实大家换个思路,就可以发现其实在上传前后,上传状态是不一样的。

上传前是

上传后是

所以只要上传状态这个Label变为“上传完成”,我们就可以断定是上传完毕了。

优化过后的代码:

1 Mouse.Click(UI开始上传Button, new Point( 1 , 1 ));
2
3 UI上传状态Text.WaitForControlPropertyEqual( " DisplayText " , " 上传完成 " , 30000 ); // 等待“UI上传状态Text”的文本变为"上传完成",最多等30秒,一旦变为"上传完成",立即结束等待,返回True,执行下一句代码。
4
5 Mouse.Click(UI确认Button, new Point( 1 , 1 ));

四.WaitForControlPropertyNotEqual()

作用:等待某个控件的属性的变化,直到它变换为不同于指定的值。

返回值:bool类型值,是否在规定时间内属性是否变换为不同于指定的值。

典型的使用场景:执行某个操作之后,窗体或页面上的某一个控件的属性会发生变化,而且这个变化是只可估计范围,无法估计具体值。(和WaitForControlPropertyEqual相反,PropertyEqual是在可估计出变化后的具体值时使用)。

举例:

本章开头的那个例子大家还记得吧

这里有一个查询模块,我们接下来的操作是,点击查询,然后获取他的查询出的行数,从界面上可以看到将会查询出5行数据

未优化代码:

1 int userCount = 0 ;
2
3 Mouse.Click(uI查询Button, new Point( 1 , 1 ));
4
5 Playback.Wait( 5000 ); // 也可以用Thread.Sleep(5000)
6
7 userCount = this .UI查询用户Window.UIUserGridViewWindow.UIDataGridViewTable.Rows.Count;

可能造成的问题:

我们知道,其实代码是会一行一行执行的,中途没有等待时间,假如这个时候我们网速有点卡,查询出来要等7,8秒,但是,我们的代码可不会等待,或者说等待时间较少(例如这里的5秒),点击“查询”后,他会立即判断这个UIDataGridViewTable有多少行,然后赋值给userCount(但这个时候行数还为0,不是查询完之后的5),于是我们就得到了错误的结果。

如果使用Playback.Wait(30000)来粗糙地解决,就会涉及到我们之前提到的测试效率问题。

但如果我们仔细观察,就可以发现,UIDataGridViewTable在查询前后,Rows属性是有发生变化的(查询前没有行,查询后有行),如何利用这个变化编写相应的代码,提高测试的稳定性呢?

优化过后的代码:

1 int userCount = 0 ;
2
3 Mouse.Click(uI查询Button, new Point( 1 , 1 ));
4
5 this .UI查询用户Window.UIUserGridViewWindow.UIDataGridViewTable.WaitForControlPropertyNotEqual( " Rows " ,Null, 30000 ) // 等待“UIDataGridViewTable”的属性Rows不为空(在没有查询出数据前,Rows属性是等于Null的),最多等30秒,一旦变为非空,立即结束等待,返回True,执行下一句代码。
6
7 userCount = this .UI查询用户Window.UIUserGridViewWindow.UIDataGridViewTable.Rows.Count;

五.WaitForControlReady ()

作用:等待某个控件,直到它解除了线程阻塞,并允许接受外界输入(例如鼠标,键盘操作)。

返回值:bool类型值,是否在规定时间内接触线程阻塞并可以接受输入。

典型的使用场景:执行某个操作之后,窗体或页面上进行相关数据的加载,导致线程阻塞,控件(例如文本框,下拉框)无法接收输入。但加载完之后,页面上的各控件属性没有变化(或者变化了但读取不到)。(因为属性没有变化或者读取不到,也就没法用WaitPropertyEqual和NotEqual,只好被迫用WaitForControlReady)

举例:

Act.1 假设有一个程序,他要为图片添加水印,点击“添加水印”按钮

Act.2 程序卡了一阵之后,水印添加完毕,但是这个水印是是通过GDI+在UI上直接绘制的,您根本没法读取到相应的属性,所以水印是否添加完毕,您无从判断

Act.3 水印添加完毕后,点击保存。

未优化代码:

1 Mouse.Click(UI添加水印Button, new Point( 1 , 1 ));
2
3 Playback.Wait( 5000 ); // 或者Thread.Sleep(5000);
4
5 Mouse.Click(UI保存Button, new Point( 1 , 1 ));

可能造成的问题:

如果等待时间过短,则可能水印没有添加成功就保存了,如果等待时间过程,又会引发之前提到的测试效率问题。

需要注意的是,一般程序在这个时候都是单线程处理,也就是说,当我们点击“添加水印”的时候,程序将进行渲染,同时,线程发生阻塞,无法接受外界输入(就像是机器卡的时候会出现“未响应”的状态),而一旦渲染完毕,线程阻塞将终止,可以接受外界输入。

基于这一点,我们可以使用WaitForControlReady来代替Playback.wait

优化过后的代码:

1 Mouse.Click(UI添加水印Button, new Point( 1 , 1 ));
2
3 UI保存Button.WaitForControlReady( 30000 ); // 等待“UI保存Button”直到它能够接受外界输入,最多等30秒,一旦可以接受,立即结束等待,返回True,执行下一句代码。
4
5 Mouse.Click(UI保存Button, new Point( 1 , 1 ));

六.WaitForControlEnabled()

作用:等待某个控件,直到它启用。等同于WaitForPropertyEqual("Enabled", true )

返回值:bool类型值,是否在规定时间内启用。

典型的使用场景:执行某个操作之后,窗体或页面上某个控件会设置为启用状态

举例:

Act.1 假设有一个模块,实现导入报表功能,如下所示,在点击“文件导入”并导入完成前,“保存”按钮一直禁用。选择一个文件,然后点击“文件导入”

Act.2 文件导入完成后,点击“保存”

未优化代码:

1 Mouse.Click(UI文件导入Button, new Point( 1 , 1 ));
2
3 Playback.Wait( 10000 ); // 或Thread.Sleep(3000);
4
5 Mouse.Click(UI保存Button, new Point( 1 , 1 ));

可能造成的问题:

等待时间少了,保存按钮没有启用就去点击了,等待时间长了,又可能有损测试效率。

优化过后的代码:

1 Mouse.Click(UI文件导入Button, new Point( 1 , 1 ));
2
3 UI保存Button .WaitForControlEnabled( 30000 ); // 等待“UI保存Button”直到它启用,最多等30秒,一旦启用,立即结束等待,返回True,执行下一句代码。
4
5 Mouse.Click(UI保存Button, new Point( 1 , 1 ));

七.WaitForControlCondition和WaitForCondition

http://www.cnblogs.com/realdigit/archive/2011/05/11/2043558.html

总结

本章介绍了提高UI测试稳定性的8种方法。相信大家有这样的经历,我们在运行UI测试时,很多测试不通过的情况,其实大多是由于测试代码不够稳定而造成的,而不是被测试程序本身的错误。因此,如何解决这些稳定性问题,一直是UI测试成败的关键之一。

编写测试代码的时候,使用这些方法,无疑可以大大提高测试的稳定性,建议以后代码中凡是出现需要等待一段时间再操作的情况,都是用WaitForControlXXX方法,而不是使用不太给力的Playback.wait或者Thread.Sleep。

附:发布计划

编码的UI测试系列之一:入门篇 一个简单的示例(Released)

编码的UI测试系列之二:入门篇 操作动作的录制原理(上)(Released)

编码的UI测试系列之二:入门篇 操作动作的录制原理(下)(Released)

编码的UI测试系列之三:入门篇 操作对象的识别原理 (Released)

编码的UI测试系列之四:进阶篇 通过编写测试代码的方式建立UI测试(上)(Released)

编码的UI测试系列之四:进阶篇 通过编写测试代码的方式建立UI测试(下)(Released)

编码的UI测试系列之:进阶篇 常用测试要点和函数(1(Released)

编码的UI测试系列之六:进阶篇 常用测试要点和函数(2)(Released)

编码的UI测试系列之七:进阶篇 UI测试之间的互相引用和测试组织

编码的UI测试系列之八:高级篇 远程调用其他机器进行测试

编码的UI测试系列之九:高级篇 使用MS测试管理器组织测试

 

 

 

 

 

 

UITestControl.WaitForControlXXX() methods

Description

WaitForControlReady

Waits for the control to be ready to accept mouse and keyboard input. The engine implicitly calls this API for all actions to wait for the control to be ready before doing any operation. However, in certain esoteric scenario, you may have to do explicit call.

WaitForControlEnabled

Waits for the control to be enabled when the wizard is doing some asynchronous validation of the input by making calls to the server. For example, you can method to wait for the Next button of the wizard to be enabled (). For an example of this method, see Walkthrough: Creating, Editing and Maintaining a Coded UI Test.

WaitForControlExist

Waits for the control to appear on the UI. For example, you are expecting an error dialog after the application has done the validation of the parameters. The time taken for validation is variable. You can use this method to wait for the error dialog box.

WaitForControlNotExist

Waits for the control to disappear from the UI. For example, you can wait for the progress bar to disappear.

WaitForControlPropertyEqual(String, Object)

Waits for the specified property of the control to have the given value. For example, you wait for the status text to change to Done.

WaitForControlPropertyNotEqual(String, Object)

Waits for the specified property of the control to have the opposite of a specified value. For example, you wait for the edit box to be not read-only, that is, editable.

WaitForControlCondition(Predicate(Of UITestControl))

Waits for the specified predicate returns to be true. This can be used for complex wait operation (like OR conditions) on a given control. For example, you can wait until the status text is Succeeded or Failed as shown in the following code:

WaitForCondition(Of T)(T, Predicate(Of T))

All the previous methods are instance methods of UITestControl. This method is a static method. This method also waits for the specified predicate to be true but it can be used for complex wait operation (like OR conditions) on multiple controls. For example, you can wait until the status text is Succeeded or until an error message appears, as shown in the following code:

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值