详解如何使用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 相关文章推荐
Python创建文件和追加文件内容实例
Oct 21 Python
python实现删除文件与目录的方法
Nov 10 Python
在Python中使用M2Crypto模块实现AES加密的教程
Apr 08 Python
使用Python的Twisted框架编写简单的网络客户端
Apr 16 Python
Python简单获取自身外网IP的方法
Sep 18 Python
Python部署web开发程序的几种方法
May 05 Python
PyQt5实现拖放功能
Apr 25 Python
在Pycharm中将pyinstaller加入External Tools的方法
Jan 16 Python
Django框架自定义session处理操作示例
May 27 Python
python tools实现视频的每一帧提取并保存
Mar 20 Python
在flask中使用python-dotenv+flask-cli自定义命令(推荐)
Jan 05 Python
Pytorch反向传播中的细节-计算梯度时的默认累加操作
Jun 05 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
投票管理程序
2006/10/09 PHP
PHP使用PDO、mysqli扩展实现与数据库交互操作详解
2019/07/20 PHP
JavaScript实现的内存数据库LokiJS介绍和入门实例
2014/11/17 Javascript
javascript中setTimeout和setInterval的unref()和ref()用法示例
2014/11/26 Javascript
js拖拽功能实现代码解析
2016/11/28 Javascript
jQuery实现分页功能(含ajax请求、后台数据、附完整demo)
2017/04/03 jQuery
JS二分查找算法详解
2017/11/01 Javascript
使用flow来规范javascript的变量类型
2019/09/12 Javascript
如何使用proxy实现一个简单完整的MVVM库的示例代码
2019/09/17 Javascript
微信公众号开发之微信支付代码记录的实现
2019/10/16 Javascript
Express 配置HTML页面访问的实现
2020/11/01 Javascript
[02:34]DOTA2亚洲邀请赛 BG战队出场宣传片
2015/03/09 DOTA
python模块之StringIO使用示例
2015/04/08 Python
探究python中open函数的使用
2016/03/01 Python
Python通用循环的构造方法实例分析
2018/12/19 Python
Python模块的加载讲解
2019/01/15 Python
解决Python3 控制台输出InsecureRequestWarning问题
2019/07/15 Python
树莓派极简安装OpenCv的方法步骤
2019/10/10 Python
Python搭建HTTP服务过程图解
2019/12/14 Python
Python StringIO如何在内存中读写str
2020/01/07 Python
Python爬取新型冠状病毒“谣言”新闻进行数据分析
2020/02/16 Python
python批量合成bilibili的m4s缓存文件为MP4格式 ver2.5
2020/12/01 Python
进程的查看和调度分别使用什么命令
2013/12/14 面试题
咖啡书吧创业计划书
2014/01/13 职场文书
2014年情人节活动方案
2014/02/16 职场文书
毕业生欢送会主持词
2014/03/31 职场文书
企业安全生产承诺书
2014/05/22 职场文书
新学期开学演讲稿
2014/05/24 职场文书
课例研修方案
2014/05/31 职场文书
支行行长竞聘报告
2014/11/06 职场文书
离婚律师函范本
2015/05/27 职场文书
亮剑观后感500字
2015/06/05 职场文书
Python基础之操作MySQL数据库
2021/05/06 Python
ConstraintValidator类如何实现自定义注解校验前端传参
2021/06/18 Java/Android
JS 基本概念详细介绍
2021/10/16 Javascript
MSSQL基本语法操作
2022/04/11 SQL Server