详解如何使用Pytest进行自动化测试


Posted in Python onJanuary 14, 2021

为什么需要自动化测试

自动化测试有很多优点,但这里有3个主要的点

  • 可重用性:不需要总是编写新的脚本,除非必要,即使是新的操作系统版本也不需要编写脚本。
  • 可靠性:人容易出错,机器不太可能。当运行不能跳过的重复步骤/测试时,速度会更快。
  • 全天运行:您可以在任何时间或远程启动测试。夜间运行正在测试你的软件,即使是在你睡着的时候。

成熟的、功能齐全的Python测试工具——pytest

目前有多种可用的测试框架和工具。这些框架的风格也各不相同,比如数据驱动、关键字驱动、混合、BDD等等。您可以选择最适合您的要求。

Python和pytest在这场竞争中占据了巨大的份额。Python及其相关工具之所以被大量使用,可能是因为与其他语言相比,没有或很少编程经验的人更能负担得起它们。

pytest框架使得编写小型测试变得很容易,但是可以扩展到支持应用程序和库的复杂功能测试。

Pytest的一些主要特性:

  • 自动发现测试模块和功能
  • 有效的CLI来更好地控制您想要运行或跳过的内容
  • 大型第三方插件生态系统
  • 固定装置-不同的类型,不同的范围
  • 与传统的单元测试框架一起工作
  • 如何使用Pytest进行自动化测试

自动和可配置的测试发现

在默认情况下,pytest期望在名称以test_开头或以test.py结尾的python模块中找到测试。在默认情况下,它期望测试函数名以test 开头。但是,可以通过在pytest的一个配置文件中添加您自己的配置来修改这个测试发现协议。

# content of pytest.ini
# Example 1: have pytest look for "check" instead of "test"
# can also be defined in tox.ini or setup.cfg file, although the section
# name in setup.cfg files should be "tool:pytest"
[pytest]
python_files = check_*.py
python_classes = Check
python_functions = *_check

让我们看一下非常基本的测试函数。

class CheckClass(object):
  def one_check(self):
    x = "this"
    assert 'h' in x

  def two_check(self):
    x = "hello"
    assert hasattr(x, 'check')

你注意到什么了吗?没有花哨的assertEqual或assertDictEqual等,只是简单明了的断言。对于比较两个对象的简单操作,不需要导入这些断言函数。assert是python已经提供的功能,因此无需重新发明。

固定装置会起作用的

查看测试功能,测试钱包软件的基本操作,比如,

// test_wallet.py
from wallet import Walletdef test_default_initial_amount():
  wallet = Wallet()
  assert wallet.balance == 0
  wallet.close()def test_setting_initial_amount():
  wallet = Wallet(initial_amount=100)
  assert wallet.balance == 100
  wallet.close()def test_wallet_add_cash():
  wallet = Wallet(initial_amount=10)
  wallet.add_cash(amount=90)
  assert wallet.balance == 100
  wallet.close()def test_wallet_spend_cash():
  wallet = Wallet(initial_amount=20)
  wallet.spend_cash(amount=10)
  assert wallet.balance == 10
  wallet.close()

嗯,有意思!你注意到了吗,很多样板文件。另一件值得注意的事情是,测试除了测试功能之外还做了一些其他的事情,例如实例化钱包并关闭它——Wallet .close()

现在让我们看看如何使用pytest fixture去除样板

import pytest
from _pytest.fixtures import SubRequest
from wallet import Wallet#==================== fixtures
@pytest.fixture
def wallet(request: SubRequest):
  param = getattr(request, ‘param', None)
  if param:
   prepared_wallet = Wallet(initial_amount=param[0])
  else:
   prepared_wallet = Wallet()
  yield prepared_wallet
  prepared_wallet.close()#==================== testsdef test_default_initial_amount(wallet):
  assert wallet.balance == 0@pytest.mark.parametrize(‘wallet', [(100,)], indirect=True)
def test_setting_initial_amount(wallet):
  assert wallet.balance == 100@pytest.mark.parametrize(‘wallet', [(10,)], indirect=True)
def test_wallet_add_cash(wallet):
  wallet.add_cash(amount=90)
  assert wallet.balance == 100@pytest.mark.parametrize(‘wallet', [(20,)], indirect=True)
def test_wallet_spend_cash(wallet):
  wallet.spend_cash(amount=10)
  assert wallet.balance == 10

整洁!不是吗。测试函数非常微妙,只做它们想做的事情。夹具钱包负责设置和拆卸、实例化和关闭钱包。它不仅有助于编写可重用的代码,还增加了数据分离的本质。如果仔细看,钱包数量是一块测试逻辑之外提供的测试数据,而不是硬编码在测试函数内部。

@pytest.mark.parametrize(‘wallet', [(10,)], indirect=True)

在更可控的环境中,您可以在存储库中有一个测试数据文件,例如test-data.ini,以及读取该文件的包装器,并且您的测试函数可以调用包装器的另一个接口来读取测试数据。

但是,建议将您的fixture作为conftest.py文件的一部分。这是pytest中的一个特殊文件,它允许测试发现全局fixture。

但是,有一个针对许多不同数据集执行的测试用例!

不用担心,pytest有一个很酷的特性来参数化您的fixture。让我们用一个例子来看看它。

假设您的产品公开CLI接口以在本地管理它。此外,您的产品在启动时设置了许多默认参数,您需要验证所有这些参数的默认值。

我们可以考虑为每个设置编写一个测试用例,但是使用pytest就容易得多了

@pytest.mark.parametrize(“setting_name, setting_value”, [(‘qdb_mem_usage', ‘low'),
(‘report_crashes', ‘yes'),
(‘stop_download_on_hang', ‘no'),
(‘stop_download_on_disconnect', ‘no'),
(‘reduce_connections_on_congestion', ‘no'),
(‘global.max_web_users', ‘1024'),
(‘global.max_downloads', ‘5'),
(‘use_kernel_congestion_detection', ‘no'),
(‘log_type', ‘normal'),
(‘no_signature_check', ‘no'),
(‘disable_xmlrpc', ‘no'),
(‘disable_ntp', ‘yes'),
(‘ssl_mode', ‘tls_1_2'),])def test_settings_defaults(self, setting_name, setting_value):
  assert product_shell.run_command(setting_name) == \
   self.”The current value for \'{0}\' is   \'{1}\'.”.format(setting_name, setting_value), \
 ‘The {} default should be {}'.format(preference_name, preference_value)

很酷,不是吗!,你只写了13个测试用例(每个不同setting_value),在未来如果你添加一个新的设置到你的产品,你需要做的就是,再添加一个tuple上面。

它是如何与selenium和API测试的UI测试集成的

嗯,你的产品可以有多种界面。CLI -就像我们上面讨论的。类似地,GUI和API。在部署软件之前,对所有软件进行测试是很重要的。在多个组件相互依赖和耦合的企业软件中,某个部分的更改可能会影响其他部分。

记住,pytest只是一个促进“测试”的框架,而不是特定类型的测试。因此,您可以使用selenium构建GUI测试,或者使用Python的请求库构建API测试,然后使用pytest运行它。

例如,在高层次上,这可能是您的测试存储库结构。

详解如何使用Pytest进行自动化测试

正如您在上面看到的,这可以很好地分离组件。

  • apiobjects:为调用API端点创建包装器的好地方。您可以使用BaseAPIObject和派生类来满足您的需求。
  • helper:编写您的helper方法
  • 库文件,它可以被不同的组件使用,例如你的fixture在conftest, pageobjects等。
  • pageobjects:pageobjects设计模式可用于创建不同GUI页面的类。我们在站得住使
  • 用Webium,它是Python的一个页面对象模式实现库。
  • 套件:您可以在这里编写pylint代码验证套件,这将有助于您对代码质量有信心。
  • 测试:可以根据测试的风格对测试目录进行分类。它使管理和研究您的测试变得容易。

这只是供参考,存储库的结构和依赖关系可以按照您的需要进行布局。

我有足够的测试用例,想并行运行它们

您的测试套件中可能有大量的测试用例,并且有时您可能想并行地运行测试用例,以减少总体测试执行时间。

Pytest提供了一个很棒的并行运行测试的插件,名为Pytest -xdist,它用一些独特的执行模式扩展了Pytest。使用pip安装此插件

pip install pytest-xdist

让我们通过一个示例来快速研究它。

我有一个自动化测试存储库CloudApp,用于使用selenium进行GUI测试。此外,它还随着新的测试用例不断增长,现在已经有了数百个测试。我想做的是并行运行它们,并减少测试执行时间。

在终端中,只需在项目根文件夹/ tests文件夹中键入pytest。这将执行所有测试。

pytest -s -v -n=2

详解如何使用Pytest进行自动化测试

并行运行测试的pytest-xdist

这还可以帮助您在多个浏览器上并行运行测试。

报告

Pytest内置支持创建结果文件,可由Jenkins、Bamboo或其他持续集成服务器读取,使用如下调用:

pytest test/file/path — junitxml=path

这可以生成很好的XML风格的输出,可以由许多CI系统解析器解释。

结论

Pytest的受欢迎程度逐年上升。此外,它还拥有广泛的社区支持,这让您可以访问很多扩展,比如pytest-django,它可以帮助您为Django web应用程序集成编写测试。记住,pytest支持运行unittest测试用例,所以如果您正在使用unittest, pytest是值得考虑的。

到此这篇关于详解如何使用Pytest进行自动化测试的文章就介绍到这了,更多相关Pytest 自动化测试内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
videocapture库制作python视频高速传输程序
Dec 23 Python
Python中使用SAX解析xml实例
Nov 21 Python
python内存管理分析
Apr 08 Python
Python CSV模块使用实例
Apr 09 Python
安装dbus-python的简要教程
May 05 Python
python 实现视频流下载保存MP4的方法
Jan 09 Python
解决yum对python依赖版本问题
Jul 05 Python
Django Channels 实现点对点实时聊天和消息推送功能
Jul 17 Python
带你彻底搞懂python操作mysql数据库(cursor游标讲解)
Jan 06 Python
python实现串口通信的示例代码
Feb 10 Python
pycharm 2020 1.1的安装流程
Sep 29 Python
Python用dilb提取照片上人脸的示例
Oct 26 Python
matplotlib对象拾取事件处理的实现
Jan 14 #Python
用python查找统一局域网下ip对应的mac地址
Jan 13 #Python
python 写一个水果忍者游戏
Jan 13 #Python
python中编写函数并调用的知识点总结
Jan 13 #Python
Python jieba库分词模式实例用法
Jan 13 #Python
python中yield的用法详解
Jan 13 #Python
利用python+request通过接口实现人员通行记录上传功能
Jan 13 #Python
You might like
让PHP COOKIE立即生效,不用刷新就可以使用
2011/03/09 PHP
深入PHP变量存储的详解
2013/06/13 PHP
解析php中eclipse 用空格替换 tab键
2013/06/24 PHP
通过jquery实现tab标签浏览效果
2007/02/20 Javascript
js 效率组装字符串 StringBuffer
2009/12/23 Javascript
jquery将一个表单序列化为一个对象的方法
2014/01/03 Javascript
jquery的trigger和triggerHandler的区别示例介绍
2014/04/20 Javascript
ANGULARJS中使用JQUERY分页控件
2015/09/16 Javascript
JS实用技巧小结(屏蔽错误、div滚动条设置、背景图片位置等)
2016/06/16 Javascript
jQuery移除或禁用html元素点击事件常用方法小结
2017/02/10 Javascript
解决在vue项目中,发版之后,背景图片报错,路径不对的问题
2018/03/06 Javascript
vue 注册组件的使用详解
2018/05/05 Javascript
Vue.js实现的表格增加删除demo示例
2018/05/22 Javascript
vue中如何让子组件修改父组件数据
2018/06/14 Javascript
vue监听input标签的value值方法
2018/08/27 Javascript
javascript中UMD规范的代码推演
2018/08/29 Javascript
基于Vue SEO的四种方案(小结)
2019/07/01 Javascript
京东优选小程序的实现代码示例
2020/02/25 Javascript
vue实现单一筛选、删除筛选条件
2020/10/26 Javascript
[01:12](回顾)DOTA2国际邀请赛,全世界DOTAer的盛宴
2014/07/01 DOTA
浅谈Python 中整型对象的存储问题
2016/05/16 Python
在Python程序和Flask框架中使用SQLAlchemy的教程
2016/06/06 Python
python实现合并多个list及合并多个django QuerySet的方法示例
2019/06/11 Python
python time.sleep()是睡眠线程还是进程
2019/07/09 Python
python中threading开启关闭线程操作
2020/05/02 Python
使用HTML5 Canvas API控制字体的显示与渲染的方法
2016/03/24 HTML / CSS
Whittard官方海外旗舰店:英国百年茶叶品牌
2018/02/22 全球购物
澳大利亚波西米亚风连衣裙在线商店:Fortunate One
2019/04/01 全球购物
农田水利实习自我鉴定
2013/09/19 职场文书
京剧自荐信
2014/01/26 职场文书
酒店中秋节促销方案
2014/01/30 职场文书
环境科学专业教师求职信
2014/07/12 职场文书
毕业纪念册寄语大全
2015/02/26 职场文书
职场中的你,辞职信写对了吗?
2019/06/26 职场文书
导游词之五台山
2019/10/11 职场文书
Windows11 Insider Preview Build 25206今日发布 更新内容汇总
2022/09/23 数码科技