您好,欢迎访问一九零五行业门户网

利用Java、Selenium和OpenCV结合的方法,解决自动化测试中滑块验证问题

1、滑块验证思路
被测对象的滑块对象长这个样子。相对而言是比较简单的一种形式,需要将左侧的拼图通过下方的滑块进行拖动,嵌入到右侧空槽中,即完成验证。
要自动化完成这个验证过程,关键点就在于确定滑块滑动的距离。
根据上面的分析,验证的关键点在于确定滑块滑动的距离。但是看似简单的一个需求,完成起来却并不简单。
如果使用自然逻辑来分析这个过程,可以拆解如下:
1. 定位到左侧拼图所在的位置,由于拼图的形状和大小固定,那么其实只需要定位其左边边界离背景图片的左侧距离。(实际在本例中,拼图的起始位置也是固定的,节省了不少工夫)
2. 定位到右侧凹槽所在位置,同样其形状和大小是固定的,那么只需要定位其左边边界离背景图片的左侧距离。
3. 用2中探测到的距离减去1中的距离,既是滑块需要被拖动的距离。
要完成上述的探测计算,首先我们想到的是使用元素定位的方法定位到拼图和凹槽的位置。
然而这一想法是不可行的,原因在于这个验证模块是使用两个canvas即画布元素实现的:
拼图和凹槽都是“画”在画布上的,其本身并不是一个页面元素,不能使用元素定位的方法。
因此我们考虑使用图片解析的方法,分析画布图像本身,来确定相应图形的位置。
2、使用opencv进行图片解析这里我们将引入opencv库,来帮我完成图片解析过程:
opencv是一个基于apache2.0许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在linux、windows、android和mac os操作系统上。 
它轻量级而且高效——由一系列 c 函数和少量 c++ 类构成,同时提供了python、ruby、matlab等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
opencv用c++语言编写,它具有c ++,python,java和matlab接口,并支持windows,linux,android和mac os,opencv主要倾向于实时视觉应用,并在可用时利用mmx和sse指令, 如今也提供对于c#、ch、ruby,go的支持。
2.1 opencv引入项目1:下载 opencv
进入到官网 https://opencv.org/releases/ 下载对应系统的 opencv 软件包后,解压放置到本地。
使用maven依赖并不能引入正确的opencv外部依赖,这里需使用外部
2:工程中添加 jar 包
intellij 中选择 file -> project structure -> modules -> dependencies
点击 add -> jars or directories... 选择
3. 新建滑块验证工具类,引入opencv动态链接库文件:opencv_java450.dll
public class slideutil { public static string dllpath = "d:\\autotest\\src\\main\\resources\\lib\\opencv\\opencv_java450.dll"; public static void main(string[] args) { //getdistance();//调试用的main方法,调用一个getdistance方法,获取拼图和凹槽之间的距离,返回double类型数值。 }
2.2 实现图片解析,计算所需距离由于本项目的特点,拼图的形状和位置是固定的,首先我们将拼图和凹槽图片下载到本地,方便后续处理。(其它项目可能出现图片形状不固定的情况,可以直接用selenium实时下载图片,这过程比较简单,因此不赘述)。
下载完的图片如下:
凹槽图片:
拼图图片:
下面直接上代码再做说明:
public static double getdistance(){ // 加载opencv本地库 system.load(dllpath); //system.loadlibrary(core.native_library_name);//对拼图图形进行处理,存储为mat类型① mat slideblockmat=imgcodecs.imread("slide_blk.png");//由于本项目的特点,拼图的形状和位置是固定的,因此直接将拼图图片保存到本地进行使用了//step1、灰度化图片② imgproc.cvtcolor(slideblockmat,slideblockmat,imgproc.color_bgr2gray); imwrite("cvt_blk.png",slideblockmat);//step2、去除周围黑边 for (int row = 0; row < slideblockmat.height(); row++) { for (int col = 0; col < slideblockmat.width(); col++) { if (slideblockmat.get(row, col)[0] == 0) { slideblockmat.put(row, col, 96); } } } imwrite("nsr_blk.png",slideblockmat);//step3、转黑白图 core.inrange(slideblockmat, scalar.all(96), scalar.all(96), slideblockmat); imwrite("ezh_blk.png",slideblockmat);<br>//对滑动背景图进行处理③ mat slidebgmat = imgcodecs.imread("slide_bg.png");//背景凹槽图片需要动态获取,见下面的解析//step1、灰度化图片④ imgproc.cvtcolor(slidebgmat,slidebgmat,imgproc.color_bgr2gray); imwrite("hdh_bg.png",slidebgmat);//step2、二值化 //core.inrange(slidebgmat, scalar.all(96), scalar.all(96), slidebgmat); imgproc.threshold(slidebgmat,slidebgmat,127,255, imgproc.thresh_binary); imwrite("ezh_bg.png",slidebgmat); mat g_result = new mat(); /* * 将凹槽背景和拼图图形进行匹配⑤ */ imgproc.matchtemplate(slidebgmat,slideblockmat,g_result, imgproc.tm_ccoeff_normed); point matchlocation= core.minmaxloc(g_result).maxloc;//返回匹配点的横向距离 system.out.println(matchlocation.x); return matchlocation.x; }
2.3 算法解析说明①什么是mat类型:
mat 是 opencv 中用来存储图像信息的内存对象。mat 对象中除了存储图像的像素数据外,还包括图像的其它属性:宽、高、类型、维度、大小、深度等。可以认为在opencv中,一个mat对象就定义了一个图像。②对于slide_blk.png的处理经过了以下过程:灰度化:
去黑边:
二值化:
最终的目的在于将图形转化为黑白分明的图形,便于后续匹配。
③本项目中,由于背景凹槽图片,凹槽的位置是动态的,所以需要实时动态获取:(如果遇到拼图也需要动态获取,可以同样处理)
webelement bg_canvas = driver.findelement(slide_ver_bg_by);//元素定位,定位到背景图片 object base64 = ((javascriptexecutor) driver) .executescript("return arguments[0].todataurl('image/png').substring(21);", bg_canvas);//页面元素转base64 string base64str = base64.tostring(); generateimage(base64str , "slide_bg.png");// 将base64把字符串装换成图片
④对于slide_bg.png的处理经过了以下过程:
灰度化:
二值化:
这里省略了去黑边这一过程,因为实践发现,经过上述两部后,我们已经能够进行较为准确的图片匹配了。
⑤matchtemplate:在模板和输入图像之间寻找匹配,获得匹配结果图像
esult:保存匹配的结果矩阵
tm_ccoeff_normed标准相关匹配算法
minmaxloc:在给定的结果矩阵中寻找最大和最小值,并给出它们的位置
3、selenium处理滑块滑动selenium的滑块处理是库里的标准玩法,使用actions类或者javascript的方式都可以实现,本例采用的是actions类方法:
public void slide_verify(webdriver driver) throws interruptedexception { double slidedistance = getdistance();//此处就是调用2中的opencv计算拼图和凹槽距离 system.out.println("滑动距离是" + slidedistance); webelement dragelement = driver.findelement(slide_obj_by);//定位到滑块 actions actions = new actions(driver); actions.clickandhold(dragelement);//模拟鼠标动作,按住滑块 thread.sleep(300);<br>//滑动,分两次进行① actions.movebyoffset(((int)slidedistance - 11)/2,0); thread.sleep(1000); thread.sleep(500); actions.release(); actions.perform(); }
①这里进行滑动时,首先滑动距离之所以要减去11,是因为本例中拼图的初始位置固定离整体图形的左边距是11.
分两次滑行并且中间sleep了一个时间,是为了防止全匀速拖动而被识别为机器人。
以上就是利用java、selenium和opencv结合的方法,解决自动化测试中滑块验证问题。的详细内容。
其它类似信息

推荐信息