1.python + appium +图片对比实现UI自动化:

背景:

当手机需要适配不同的语言时,测试过程中易出现因为语言不熟悉,导致UIbug被遗漏(例如setting中的描述性文字显示不完整等等问题)

环境搭建:

需使用模块PIL,Windows版本链接地址:http://pythonware.com/products/pil/

ubuntu (使用16.04虚拟机):sudo apt-get install python-imaging

安装过程遭遇

Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?

强制解锁进行的下一步

sudo rm /var/cache/apt/archives/lock

sudo rm /var/lib/dpkg/lock

各种小毛病:

安装PIL模块提示python2.7没有注册,解决方法:

https://www.cnblogs.com/thinksasa/p/3283695.html

虚拟机连接手机提示没有权限的问题:

在root账号下,kill-server 然后start-server

在win7 64位会报错:tThe _imaging C module is not installed,安装64位的PIL可解决,

https://www.lfd.uci.edu/~gohlke/pythonlibs/#pillow

安装后在python下执行import ImageFon,不报错就OK。安装过程各种不爽,用python3.6搭配64位的PIL在Windows下成功执行(上面的网址可以下载)

在使用ImageChops.difference函数时,部分结果图片显示为一张网格图,导致压根看不到两张图的差异,结合如下链接

https://blog.csdn.net/qq_41500251/article/details/82919656

对图片进行取反,使得结果可见

逻辑梳理:

保存已确认过的UI截图,在测试时将当前页面进行截图,与保存的期望截图做对比

问题一

期望结果截图和测试结果截图时间不同,当前已运行的程序不同,会导致状态栏显示不同,并且有时候navigation bar也会不一样(Android P手机倾斜时,出现一个转屏操作按钮)

方案:将图片进行裁剪,只保留需要对比的部分。

截图使用到如下模块:

im = Image.open(im_path)

cropedIm = im.crop((700, 100, 1200, 1000))#此处为(左,上,右,下)坐标

cropedIm.save(r'C:\Users\Administrator\Desktop\cropped.png')

https://www.cnblogs.com/sun-haiyu/p/7127582.html

#在不同的机种上需要重新适配截图的大小

目录结构:

-----------

├─WlanUi.py 主程序,负责测试报告生成

│ └─Test_case 存放测试case

│ └─test_Network01.py

├─DesiredResult 此处存放期望结果图片

│ ├─test_NetworkEN01.png

│ └─test_NetworkEN02.png

├─DiffPicture 当期望结果和世界结果不同时,生成一张差分图,存放于此路径

├─testReport 测试报告(.html)

├─testResult实际测试结果截图

├─readme.md

代码:

test_Network01.py

#coding=utf-8

#python3

import unittest

from appium import webdriver

import time

import os

from PIL import Image

from PIL import ImageChops

#如下导入解决‘image file is truncated’问题

from PIL import ImageFile

ImageFile.LOAD_TRUNCATED_IMAGES = True

PATH = lambda p: os.path.abspath(p)

def screenshot(testcase):

path = PATH(os.getcwd() + "/TestResult")

if not os.path.isdir(PATH(os.getcwd() + "/TestResult")):

os.makedirs(path)

os.popen("adb wait-for-device")

time.sleep(1)#由于多次出现截图延迟现象(每次截图都截的是上次操作的画面),故此处设置一个等待

os.popen("adb shell screencap -p /data/local/tmp/tmp.png")

time.sleep(1)

os.popen("adb pull /data/local/tmp/tmp.png " + PATH(path + "/" + testcase + '.png'))

time.sleep(1)

os.popen("adb shell rm /data/local/tmp/tmp.png")

time.sleep(1)

im = Image.open(PATH(path + "/" + testcase + '.png'))

cropedIm = im.crop((0, 70, 1079,2080 ))

cropedIm.save(PATH(path + "/" + testcase + '.png'))

def compare_images(path_one, path_two, diff_save_location):

"""

比较图片,如果有不同则生成展示不同的图片

@参数一: path_one: 第一张图片的路径

@参数二: path_two: 第二张图片的路径

@参数三: diff_save_location: 不同图的保存路径

"""

image_one = Image.open(path_one)

image_two = Image.open(path_two)

try:

diff = ImageChops.difference(image_one, image_two)

if diff.getbbox() is None:

# 图片间没有任何不同则直接退出

return True

else:

diff.save(diff_save_location)

return False

except ValueError as e:

text = ("表示图片大小和box对应的宽度不一致,参考API说明:Pastes another image into this image."

"The box argument is either a 2-tuple giving the upper left corner, a 4-tuple defining the left, upper, "

"right, and lower pixel coordinate, or None (same as (0, 0)). If a 4-tuple is given, the size of the pasted "

"image must match the size of the region.使用2纬的box避免上述问题")

print("【{0}】{1}".format(e,text))

class Test(unittest.TestCase):

def setUp(self):

#appium 固定设置,沿用之前的即可

self.desired_caps = {}

self.desired_caps['platformName'] = 'Android'

self.desired_caps['platformVersion'] = '9'

self.desired_caps['deviceName'] = 'Android Emulator'

self.desired_caps['appPackage'] = 'com.android.settings'

self.desired_caps['appActivity'] = '.Settings$NetworkDashboardActivity'

self.desired_caps['noReset'] = 'true'

self.driver = webdriver.Remote('http://localhost:4723/wd/hub', self.desired_caps)

def test01(self):

'''Network & internetEN01'''

driver = self.driver

driver.wait_activity(".Settings$NetworkDashboardActivity", 30)

screenshot('test_NetworkEN01')

driver.find_element_by_xpath("//*[@text='Advanced']").click()

time.sleep(2)

#讲道理这个截图应该放到test02里面的,只是跑逻辑,就懒得改了

screenshot('test_NetworkEN02')

time.sleep(5)

#下面这个可以用参数来写,会显得短一些,懒得改了

ac = compare_images('./TestResult/test_NetworkEN01.png','./DesiredResult/test_NetworkEN01.png','./DiffPicture/test_NetworkEN01.png')

self.assertEqual(ac, True)

def test02(self):

'''Network & internetEN02'''

bc = compare_images('./TestResult/test_NetworkEN02.png','./DesiredResult/test_NetworkEN02.png','./DiffPicture/test_NetworkEN02.png')

self.assertEqual(bc, True)

#clear envirment

def tearDown(self):

#self.assertTrue(ac != preStatus)

self.driver.quit()

if __name__ == '__main__':

unittest.main()

WlanUi.py

#coding=utf-8

import time

import unittest

from HTMLTestRunner import HTMLTestRunner

import os

if __name__=='__main__':

print ('=====AutoTest Start======')

test_dir = './Test_case/'

#知道测试报告的路径

test_report_dir='./testReport/'

PATH = lambda p: os.path.abspath(p)

if not os.path.isdir(PATH(os.getcwd() + "/testReport")):

os.makedirs(test_report_dir)

discover=unittest.defaultTestLoader.discover(test_dir, pattern='test_*.py')

now=time.strftime('%Y-%m-%d_%H_%M_%S_')

filename = test_report_dir+'/'+ now + 'result.html'

fp=open(filename ,'wb')

runner = HTMLTestRunner(stream=fp,title=u'测试报告',description=u'用例执行情况:')

runner.run(discover)

#注意:调用函数一定要加括号,一个括号害死个人,哎,查了几天的问题,才发现导致html文件始终显示空白,就是因为close函数调用不正确,漏了括号。

fp.close()

#2.取最新测试报告

# new_report=new_file(test_report_dir)

#调试用的

# print new_report

#3.发送邮件,发送最新测试报告html

# send_email(new_report)

print('=====AutoTest Over======')

time.sleep(10)

左侧是原始截图,右侧是截取的对比区域

初次实现时, ImageChops.difference得到的截图基本上看不清差异点,见下图:

左侧有张图,但是看不清,使用ImageChops.invert 后变成这样了

代码:

def invert(im1):

IM = Image.open(im1)

im3 = ImageChops.invert(IM)

im3.save('./DesiredResult/test_NetworkEN04.png')

im3.close()

拼凑代码查了多方资料,实在罗列不出各大大的链接,见谅!!

初次写总结,感觉不怎么流畅,啥都想写,尴尬得一撇

'''

以下为临时笔记,备忘:

2.文件名以路径首单词为名字命名,eg:Sound/Display/Battery and so on

如下链接详细介绍了ImageChops的使用

https://blog.csdn.net/icamera0/article/details/50727599

'''

python图片比对、自动化测试_基于python+appium通过图片对比来做的UI自动化相关推荐

  1. python通信自动化测试_基于Python的无线通信设备自动化测试软件的研制

    基于Python的无线通信设备自动化测试软件的研制 中国电子科技集团公司第十研究所 冯启俊 [期刊名称]<电子世界> [年(卷),期]2019(000)015 [总页数]2 无线通信设备的 ...

  2. 基于python爬虫技术的应用_基于Python爬虫技术的应用

    办公自动化杂志 一.引言 本文主要是对 Python 爬虫技术进行阐述,基于 python 的爬虫与其他语言相比的有很多优势.通过爬去某个网站的所有新闻这个案例,来进一步阐释 Python 爬虫技术的 ...

  3. python图片识别验证码软件_基于python图片识别工具(图片识别,车牌,PDF,验证码)...

    先上图  不多说. 对于一般的用户来说识别率还是能达到百分之90以上. 已经打包成exe文件.windows用户可以直接使用.要软件的加我QQ python代码: # -*- coding: UTF- ...

  4. python 按需加载_基于python的opcode优化和模块按需加载机制研究(学习与个人思路)(原创)...

    基于python的opcode优化和模块按需加载机制研究(学习与思考) 姓名:XXX 学校信息:XXX 主用编程语言:python3.5 文档转换为PDF有些图片无法完全显示,请移步我的博客查看 完成 ...

  5. python实现数据可视化软件_基于Python实现交互式数据可视化的工具

    作者:Alark Joshi 翻译:陈雨琳 校对:吴金笛 本文2200字,建议阅读8分钟. 本文将介绍实现数据可视化的软件包. 这学期(2018学年春季学期)我教授了一门关于数据可视化的数据科学硕士课 ...

  6. 基于python的网络爬虫编程_基于Python的网络爬虫程序设计

    程序设计 ●Program Design 基于 Python的网络爬虫程序设计 网络 信 息量 的迅 猛 增 长,对 如何从海量的信息中准确的搜索 到用户需要的信息提 出了极大的 挑战.网络爬 虫具有 ...

  7. python卡方检验筛选特征原理_基于Python的遥感特征筛选—递归特征消除(RFE)与极限树(Extra-Trees)...

    引言 基于前几篇文章关于筛选方法的介绍,本篇同样给大家介绍两种python封装的经典特征降维方法,递归特征消除(RFE)与极限树(Extra-Trees, ET).其中,RFE整合了两种不同的超参数, ...

  8. 基于python的压测工具_基于Python和SIPp的自动化压力测试系统设计和实现

    信斌 王桂花 摘要:首先,分析了现有测试系统的不足,之后,介绍了软件组成和运行环境说明,最后,设计了基于Python和SIPp的自动化压力测试系统,并给出了相关代码.新的测试系统克服了现有测试系统的不 ...

  9. python实现ocr识别算法_基于Python的OCR实现示例

    摘要: 近几天在做一个东西,其中需要对图像中的文字进行识别,看了前辈们的文章,找到两个较简单的方法:使用python的pytesseract库和调用百度AI平台接口.写下这篇文章做一个比较简短的记录和 ...

最新文章

  1. nagios插件之登陆防火墙实现session监控
  2. 【bzoj 4764】弹飞大爷
  3. 3.8 Anchor Boxes-深度学习第四课《卷积神经网络》-Stanford吴恩达教授
  4. 毕业的答辩需要的要求(从校方的角度)
  5. linux svn配置教程,linux svn搭建及配置
  6. armadillo 配置
  7. 指针%p输出的一些认识
  8. [前台]---js中方法的强制返回和java中方法的强制返回
  9. php新窗口打开链接,wordpress如何设置在新窗口打开链接
  10. [Twisted] transport
  11. 基于OWIN WebAPI 使用OAUTH2授权服务【授权码模式(Authorization Code)】
  12. 数据库中的日期相减_sql日期相减得到天数【sql日期时间相减语句】
  13. 腾讯云内容分发网络 CDN 产品认证课程笔记(三)——腾讯云CDN操作指引
  14. windows 豆沙绿参数
  15. QQ揭秘:如何实现窗体靠边隐藏?【低调赠送:QQ高仿版GG 4.2 最新源码】
  16. Android OpenGL探索之纯色背景绘制
  17. Coding and Paper Letter(八十七)
  18. 2021-2027全球与中国主线稳定器市场现状及未来发展趋势
  19. 牛客网暑期ACM多校训练营(第六场)J-Heritage of skywalkert
  20. 程序人生:初学者中最最最常问的问题都有哪些呢???

热门文章

  1. 51单片机学习笔记——SH88F4051A
  2. MySQL插入数据库乱码问题Incorrect string value: ‘\xE8\xB5\xB5‘ for column ‘name‘ at row 1
  3. Google Drive—谷歌云盘大文件下载
  4. 让我们的爱洒满孩子们的心
  5. RS485_Modbus通讯笔记
  6. 爬取 48048 条评论,解读 9.3 分的「毒液」是否值得一看?
  7. VSCode中将LaTeX的PDF阅读器设置为暗色
  8. OpenCV计算图像像素最大值、最小值
  9. SATA 3.0 双通道 - 硬盘数据线 + 硬盘电源线
  10. java email bean_JavaWeb学习笔记-第四章JavaBean技术