ATX python uiautomator2 截图转为 base64 加入 HTMLTestRunner 报告中

我叫不迷糊 · 2018年09月06日 · 最后由 黄先森 回复于 2022年10月28日 · 2450 次阅读

改造 uiautomator2screenshot 方法

uiautomator2 不支持 base64 格式截图,需要对截图的方法进行改造。
uiautomator2/__init__.py中找到 screenshot 方法,添加生成 base64 格式图片的代码,改造后的方法如下:

def screenshot(self, filename=None, format='pillow'):
        """
        Image format is JPEG

        Args:
            filename (str): saved filename
            format (string): used when filename is empty. one of "pillow" or "opencv"

        Raises:
            IOError, SyntaxError

        Examples:
            screenshot("saved.jpg")
            screenshot().save("saved.png")
            cv2.imwrite('saved.jpg', screenshot(format='opencv'))
        """
        r = requests.get(self.server.screenshot_uri, timeout=10)
        if filename:
            with open(filename, 'wb') as f:
                f.write(r.content)
            return filename
        elif format == 'pillow':
            from PIL import Image
            buff = io.BytesIO(r.content)
            return Image.open(buff)
        elif format == 'opencv':
            import cv2
            import numpy as np
            nparr = np.fromstring(r.content, np.uint8)
            return cv2.imdecode(nparr, cv2.IMREAD_COLOR)
        elif format == 'raw':
            return r.content
        #----新增代码开始------
        elif format == 'base64':
            import base64
            # b64encode是编码,b64decode是解码
            base64_data = base64.b64encode(r.content)
            # base64.b64decode(base64data)
            return base64_data
        #----新增代码结束------
        else:
            raise RuntimeError("Invalid format " + format)

python 将图片转 base64,前端显示

截图添加进入测试报告

HTMLTestRunner_cn 项目的 gitbub 地址中下载 HTMLTestRunner_cn.py 文件,放入C:\Python27\Lib文件夹中

生成报告的 demo:

# coding: utf-8

import uiautomator2 as u2
from HTMLTestRunner_cn import HTMLTestRunner
import unittest
import os, re

class TestCaseUi2(unittest.TestCase):
    """docstring for TestCaseUi2"""

    @classmethod
    def setUpClass(cls):
        deviceInfo = os.popen("adb devices").read().strip('\n')
        deviceSerial = re.search('attached\n(.*)\t', deviceInfo).group(1).strip()
        print deviceSerial
        cls.driver = u2.connect(deviceSerial)

    @classmethod
    def tearDownClass(cls):
        pass


    def add_img(self):
        self.imgs.append(self.driver.screenshot(format='base64'))
        return True

    def setUp(self):
        self.driver.session('com.szchmtech.parkingfee')

    def tearDown(self):
        self.driver.app_stop('com.szchmtech.parkingfee')

    def test_case1(self):
        self.add_img()
        self.add_img()


if __name__ == "__main__":
    suite = unittest.TestLoader().loadTestsFromTestCase(TestCaseUi2)
    runer = HTMLTestRunner(title="带截图的测试报告", description="小试牛刀", stream=open("sample_test_report_uiautomator2.html", "wb"), verbosity=2, retry=1, save_last_try=True)
    runer.run(suite)

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 15 条回复 时间 点赞
hazelning 回复

因为 base64.b64encode 结果是 bytes 类型,要 decode 转一下,其实不用改造,直接再封装一下就可以了。
data = self.driver.screenshot(format='raw')
base64_data = base64.b64encode(data).decode('utf-8')

仅楼主可见

请教高手,在 screenshot()里增加了下面的代码,但 html report 里的截图显示不出来,返回的 base64 字符串好像不太对。

#----新增代码开始------
elif format == 'base64':
import base64
# b64encode 是编码,b64decode 是解码
base64_data = base64.b64encode(r.content)
# base64.b64decode(base64data)
return base64_data
#----新增代码结束------

这个是返回的 base64,是 b'开头呢?
data:image/jpg;base64,b'/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAeABDgDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkK

codeskyblue 回复

哦~好的~~

那我这种就不能用函数了~~~

🙈 谢谢你

function 的返回值需要是一个 function

codeskyblue 回复

大神,我改成用插件的方式,但是我写成函数没有成功,写成类成功了。
是不是函数的我哪里写错了,可是看了半天也没看出问题。
写成函数的代码

#coding: utf-8
import uiautomator2 as u2
def screenshot_base64(d):
    import base64
    base64_data = base64.b64encode(d.screenshot(format='raw'))
    return base64_data

u2.plugin_register("screenshot_base64", screenshot_base64)

d = u2.connect('LNKREEMV99999999')
print d.ext_screenshot_base64()

报错如下:

G:\004-Study\workspace\appTest\venv\Scripts\python.exe G:/004-Study/workspace/appTest/Common/u2_plugin.py
Traceback (most recent call last):
  File "G:/004-Study/workspace/appTest/Common/u2_plugin.py", line 12, in <module>
    print d.ext_screenshot_base64()
TypeError: 'str' object is not callable

Process finished with exit code 1

写成类的代码,这个就是可以的

# coding: utf-8
import uiautomator2 as u2

class ScreenshotBase64(object):
    def __init__(self, d):
        self.d = d

    def screenshot_base64(self):
        import base64
        base64_data = base64.b64encode(self.d.screenshot(format='raw'))
        return base64_data


u2.plugin_register("screenshot_base64", ScreenshotBase64)

d = u2.connect('LNKREEMV99999999')
print d.ext_screenshot_base64.screenshot_base64()

这个是为什么呀~~~~

codeskyblue 回复

嗯嗯,看到了你的文章~
我去改成用插件的方式,谢谢~~~~😊

现在你可以不用改 uiautomator2 的源码了,现在新开发了插件机制,用函数 plugin_register('b64img', plugin-function here) 然后截图得时候 d.ext_b64img() 得到 base64 的字符串

hello 回复

嗯嗯,好的,待我再去学习下🙈

10楼 已删除
arrow 回复

我现在还是个弱鸡,没学会怎么把这些存到数据库和绑定页面呢。现在是存在报告里,发邮件。🤣等你说的学会了就取缔这个,感谢你的建议

我当时是为了发邮件方便才用 base64 存图片在单文件里的,如果有其他展现平台,像其他人说的存数据库,不转也行~~

报告只一个模板就好了,测试结果数据保存文件或者数据库中,查看报告时,加载相应的数据就好 了

arrow 回复

感觉说的好有道理

其实没必要转成 base64
还有就是 一些关键的测试数据,比如:测试输入数据、测试执行步骤、测试结果、截图等,不建议直接放在测试报告文件里面,最好是可以记录到数据库,要查看的时候,再将数据绑定到页面上,这样有利于做测试数据分析。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册