自动化测试中的失败截图和存log

如果我们在执行自动化测试的时候,希望能在失败的时候保存现场,方便事后分析。 对于UI自动化,我们希望截图在测试报告中。 对于api自动化,我们希望截取出错的log在测试报告中。 我开始自己蛮干,写了两个出错截图的方法。

  1. def save_screenshot():

  2. '''

  3. 页面截屏保存截图

  4. :return:

  5. '''

  6. file_name = IMG_PATH + "\\{}.png".format(time.strftime("%Y%m%d%H%M%S", time.localtime()))

  7. d.screenshot(file_name)

  8. with open(file_name, mode='rb') as f:

  9. file = f.read()

  10. allure.attach(file, allure.attachment_type.PNG)

出错截图,我写了一个装饰器

  1. def fail_screenshot(func):

  2. '''

  3. 失败页面截屏保存截图

  4. :return:

  5. '''

  6. def wrapper(*args, **kwargs):

  7. try:

  8. func(*args, **kwargs)

  9. except:

  10. file_name = FAIL_IMG_PATH + "\\{}_{}.png".format(func.__name__,

  11. time.strftime("%Y%m%d%H%M%S", time.localtime()))

  12. d.screenshot(file_name)

  13. # with open(file_name, mode='rb') as f:

  14. # file = f.read()

  15. # allure.attach(file, allure.attachment_type.PNG)

  16. return wrapper

似乎能达到我的期望,就是太烦了,每次需要调用或者将装饰器写在函数上。 然后我发现allue里面有一个钩子函数。

  1. from _pytest import runner

  2. # 对应源码

  3. def pytest_runtest_makereport(item, call):

  4. """ return a :py:class:`_pytest.runner.TestReport` object

  5. for the given :py:class:`pytest.Item` and

  6. :py:class:`_pytest.runner.CallInfo`.

  7. """

这里item是测试用例,call是测试步骤,具体执行过程如下:

先执行when='setup' 返回setup 的执行结果

然后执行when='call' 返回call 的执行结果

最后执行when='teardown'返回teardown 的执行结果

例如:

 
  1. # conftest.py

  2. import pytest

  3. @pytest.hookimpl(hookwrapper=True, tryfirst=True)

  4. def pytest_runtest_makereport(item, call):

  5. print('------------------------------------')

  6. # 获取钩子方法的调用结果

  7. out = yield

  8. print('用例执行结果', out)

  9. # 3. 从钩子方法的调用结果中获取测试报告

  10. report = out.get_result()

  11. print('测试报告:%s' % report)

  12. print('步骤:%s' % report.when)

  13. print('nodeid:%s' % report.nodeid)

  14. print('description:%s' % str(item.function.__doc__))

  15. print(('运行结果: %s' % report.outcome)

运行用例的过程会经历三个阶段:setup-call-teardown,每个阶段都会返回的 Result 对象和 TestReport 对象,以及对象属性。

如果setup执行失败了,setup的执行结果的failed,后面的call用例和teardown都不会执行了。

如果setup正常执行,但是测试用例call失败了。那么此时运行的结果就是failed。

如果setup正常执行,测试用例call正常执行,teardown失败了,这种情况,最终统计的结果:1 passed, 1 error in 0.16 seconds

只获取call的时候,我们在写用例的时候,如果保证setup和teardown不报错情况,只关注测试用例本身的运行结果,前面的 pytest_runtest_makereport 钩子方法执行了三次。

可以加个判断:if report.when == "call"

  1. import pytest

  2. from _pytest import runner

  3. '''

  4. # 对应源码

  5. def pytest_runtest_makereport(item, call):

  6. """ return a :py:class:`_pytest.runner.TestReport` object

  7. for the given :py:class:`pytest.Item` and

  8. :py:class:`_pytest.runner.CallInfo`.

  9. """

  10. '''

  11. @pytest.hookimpl(hookwrapper=True, tryfirst=True)

  12. def pytest_runtest_makereport(item, call):

  13. print('------------------------------------')

  14. # 获取钩子方法的调用结果

  15. out = yield

  16. # print('用例执行结果', out)

  17. # 3. 从钩子方法的调用结果中获取测试报告

  18. report = out.get_result()

  19. if report.when == "call":

  20. print('测试报告:%s' % report)

  21. print('步骤:%s' % report.when)

  22. print('nodeid:%s' % report.nodeid)

  23. print('description:%s' % str(item.function.__doc__))

  24. print(('运行结果: %s' % report.outcome))

  25. @pytest.fixture(scope="session", autouse=True)

  26. def fix_a():

  27. print("setup 前置操作")

  28. yield

  29. print("teardown 后置操作")

allure报告集成错误截图 需要使用conftest.py文件,conftest.py需要存在在测试目录中,文件名不能变更,可以根据模块创建层级嵌套。

具体参照pytest的官方文档

  1. @pytest.hookimpl(tryfirst=True, hookwrapper=True)

  2. def pytest_runtest_makereport(item, call):

  3. '''

  4. hook pytest失败

  5. :param item:

  6. :param call:

  7. :return:

  8. '''

  9. # execute all other hooks to obtain the report object

  10. outcome = yield

  11. rep = outcome.get_result()

  12. # we only look at actual failing test calls, not setup/teardown

  13. if rep.when == "call" and rep.failed:

  14. mode = "a" if os.path.exists("failures") else "w"

  15. with open("failures", mode) as f:

  16. # let's also access a fixture for the fun of it

  17. if "tmpdir" in item.fixturenames:

  18. extra = " (%s)" % item.funcargs["tmpdir"]

  19. else:

  20. extra = ""

  21. f.write(rep.nodeid + extra + "\n")

  22. # pic_info = adb_screen_shot()

  23. with allure.step('添加失败截图...'):

  24. allure.attach(driver.get_screenshot_as_png(), "失败截图", allure.attachment_type.PNG)

好了,我们可以用在我们自己的项目里面来了。 我们可以在conftest.py里面定义:

  1. import pytest

  2. from selenium import webdriver

  3. import os

  4. import allure

  5. _driver = None

  6. @pytest.hookimpl(tryfirst=True, hookwrapper=True)

  7. def pytest_runtest_makereport(item, call):

  8. '''

  9. 获取每个用例状态的钩子函数

  10. :param item:

  11. :param call:

  12. :return:

  13. '''

  14. # 获取钩子方法的调用结果

  15. outcome = yield

  16. rep = outcome.get_result()

  17. # 仅仅获取用例call 执行结果是失败的情况, 不包含 setup/teardown

  18. if rep.when == "call" and rep.failed:

  19. mode = "a" if os.path.exists("failures") else "w"

  20. with open("failures", mode) as f:

  21. # let's also access a fixture for the fun of it

  22. if "tmpdir" in item.fixturenames:

  23. extra = " (%s)" % item.funcargs["tmpdir"]

  24. else:

  25. extra = ""

  26. f.write(rep.nodeid + extra + "\n")

  27. # 添加allure报告截图

  28. if hasattr(_driver, "get_screenshot_as_png"):

  29. with allure.step('添加失败截图...'):

  30. allure.attach(_driver.get_screenshot_as_png(), "失败截图", allure.attachment_type.PNG)

  31. @pytest.fixture(scope='session')

  32. def browser():

  33. global _driver

  34. if _driver is None:

  35. _driver =webdriver.Chrome()

  36. yield _driver

  37. print("1111111111")

  38. _driver.quit()

然后写一个测试用例,如在某度上搜一个关键词。

  1. @allure.feature('self study')

  2. class TestLesson():

  3. @allure.story('user course page')

  4. @allure.description('be course')

  5. def test_be_ge_course(self,browser):

  6. url = 'http://www.baidu.com'

  7. browser.get(url)

  8. time.sleep(2)

  9. browser.find_element_by_id('kw').send_keys("python")

  10. with allure.step('查找元素...'):

  11. browser.find_element_by_id('su').click()

  12. time.sleep(2)

  13. assert browser.title == 'python'

这是一个失败的用例,所以执行错误会截图。

这样你的报告就看起来高大上了。 截图还可以直接用allure.attach allure.attach(挺有用的) 作用:allure报告还支持显示许多不同类型的附件,可以补充测试结果;自己想输出啥就输出啥,挺好的

  1. 语法:allure.attach(body, name, attachment_type, extension)

  2. 参数列表

  3. body:要显示的内容(附件)

  4. name:附件名字

  5. attachment_type:附件类型,是 allure.attachment_type 里面的其中一种

  6. extension:附件的扩展名(比较少用)

allure.attach.file(source, name, attachment_type, extension) source:文件路径,相当于传一个文件

其他参数和上面的一致:

  1. TEXT = ("text/plain", "txt")

  2. CSV = ("text/csv", "csv")

  3. TSV = ("text/tab-separated-values", "tsv")

  4. URI_LIST = ("text/uri-list", "uri")

  5. HTML = ("text/html", "html")

  6. XML = ("application/xml", "xml")

  7. JSON = ("application/json", "json")

  8. YAML = ("application/yaml", "yaml")

  9. PCAP = ("application/vnd.tcpdump.pcap", "pcap")

  10. PNG = ("image/png", "png")

  11. JPG = ("image/jpg", "jpg")

  12. SVG = ("image/svg-xml", "svg")

  13. GIF = ("image/gif", "gif")

  14. BMP = ("image/bmp", "bmp")

  15. TIFF = ("image/tiff", "tiff")

  16. MP4 = ("video/mp4", "mp4")

  17. OGG = ("video/ogg", "ogg")

  18. WEBM = ("video/webm", "webm")

  19. PDF = ("application/pdf", "pdf")

根据需要,在报告里将更多的信息展现出来。 这周末啥也没干,主要就搞明白了这个。

 

总结:

感谢每一个认真阅读我文章的人!!!

作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

 

          视频文档获取方式:
这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片即可自行领取。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值