pytest是一个非常成熟的全功能的Python测试框架,主要特点有以下几点:1、简单灵活,容易上手;2、支持参数化;3、能够支持简单的单元测试和复杂的功能测试,还可以用来做selenium/appnium等自动化测试、接口自动化测试(pytest+requests);4、pytest具有很多第三方插件,并且可以自定义扩展,比较好用的如pytest-selenium(集成selenium)、pytest-html(完美html测试报告生成)、pytest-rerunfailures(失败case重复执行)、pytest-xdist(多CPU分发)等;5、测试用例的skip和xfail处理;6、可以很好的和jenkins集成;(二)安装

  pip install -U pytest

  pip install -U pytest-html

  pip install -U pytest-rerunfailures

此外还有很多很好的第三方插件,请到http://plugincompat.herokuapp.com/ 和 https://pypi.python.org/pypi?%3Aaction=search&term=pytest-&submit=search 查找

(三)例子

这里列几个pytest-document中的例子

1、默认执行当前目录下的所有以test_为前缀(test_*.py)或以_test为后缀(*_test.py)的文件中以test_为前缀的函数

import pytest

# content of test_sample.py
def func(x):
return x + 1
def test_answer():
assert func(3) == 5

运行 py.test  或 指定特定文件 py.test -q test_sample.py

2、使用类来组成多个用例的

import pytest

# content of test_class.py
class TestClass:
def test_one(self): x = "this"
assert 'h' in x
def test_two(self):
x = "hello"
assert hasattr(x, 'check')

3、在python中调用pytest: python test_class.py

import pytest

# content of test_class.py
class TestClass:
def test_one(self):
print 'one'
x = "this"
assert 'h' in x
def test_two(self):
print 'two'
x = "hello"
assert hasattr(x, 'check')
if __name__ == '__main__':
pytest.main("-q --html=a.html")

4、来个支持参数化的例子,参数化使用pytest.mark.parametrize的参数,第一个为变量的元组,第二个是变量赋值的元组列表,具体下面的章节会仔细介绍

# content of test_time.py
import pytest
from datetime import datetime, timedelta testdata = [
(datetime(2001, 12, 12), datetime(2001, 12, 11), timedelta(1)),
(datetime(2001, 12, 11), datetime(2001, 12, 12), timedelta(-1)),
] @pytest.mark.parametrize("a,b,expected", testdata)
def test_timedistance_v0(a, b, expected):
diff = a - b
assert diff == expected @pytest.mark.parametrize("a,b,expected", testdata, ids=["forward", "backward"])
def test_timedistance_v1(a, b, expected): diff = a - b
assert diff == expected def idfn(val):
if isinstance(val, (datetime,)):
# note this wouldn't show any hours/minutes/seconds
return val.strftime('%Y%m%d')
@pytest.mark.parametrize("a,b,expected", testdata, ids=idfn)
def test_timedistance_v2(a, b, expected):
diff = a - b
assert diff == expected

使用和调用

  • python -m pytest调用:

    • python -m pytest [...] 效果和py.test [...] 一样
  • 获取版本,选项名,环境变量
    • py.test --version 看版本
    • py.test --fixtures 查看内置参数
    • py.test -h | --help 命令行和配置文件帮助
  • 失败后停止
    • 首次失败后停止执行:py.test -x
    • py.test --maxfail=2 两次失败之后停止执行
  • 执行选择用例
    • py.test test_mod.py,执行模块中的用例
    • py.test somepath,执行路径中用例
    • py.test -k stringexpr,执行字符串表达式中的用例,比如"MyClass?and not method",选择TestMyClass.test_something,排除了TestMyClass.test_method_simple。
    • py.test --pyargs pkg,导入pkg,使用其文件系统位置来查找和执行用例。执行pypkg目录下的所有用例。
  • 调试输出:
    • py.test --showlocals 在traceback中显示本地变量
    • py.test --showlocals 在traceback中显示本地变量(快捷方式)
    • py.test --tb=long 默认的traceback信息格式化形式
    • py.test --tb=native 标准库格式化形式
    • py.test --tb=short 更短的格式
    • py.test --tb=line 每个错误一行
  • 失败时调用PDB (Python Debugger):

Python带有一个内置的Python调试器称为PDB。pytest可以在命令行选项指定调用:

py.test --pdb

这将每次失败时调用Python调试器。通常,您可能只希望这样做的第一个失败的测试,以 了解某些故障情况: py.test-X - PDB#下降到PDB上的第一次失败,然后结束测试阶段 py.test - PDB - maxfail=3#下降到PDB前三失败


几个pytest documentation中的例子:


例子1:


import pytest

# content of test_sample.py
def func(x):
return x + 1
def test_answer():
assert func(3) == 5

命令行切换到文件所谓目录,执行测试(也可以直接在IDE中运行):



image.png

这个测试返回一个失败报告,因为func(3)不返回5。


例子2:
当需要编写多个测试样例的时候,我们可以将其放到一个测试类当中,如:


class TestClass:
def test_one(self):
x = "this"
assert 'h' in x def test_two(self):
x = "hello"
assert hasattr(x, 'check')

运行以上例子:



image.png

从测试结果中可以看到,该测试共执行了两个测试样例,一个失败一个成功。同样,我们也看到失败样例的详细信息,和执行过程中的中间结果。-q即-quiet,作用是减少冗长,具体就是不再展示pytest的版本信息。


如何编写pytest测试样例


通过上面2个实例,我们发现编写pytest测试样例非常简单,只需要按照下面的规则:


  • 测试文件以test_开头(以_test结尾也可以)
  • 测试类以Test开头,并且不能带有 init 方法
  • 测试函数以test_开头
  • 断言使用基本的assert即可

运行模式


   Pytest的多种运行模式,让测试和调试变得更加得心应手,下面介绍5种常用的模式。在介绍之前需要提醒一句,运行pytest时会找当前目录及其子目录中的所有test_*.py 或 *_test.py格式的文件以及以test开头的方法或者class,不然就会提示找不到可以运行的case了。


1.运行后生成测试报告(htmlReport)


安装pytest-html:


pip install -U pytest-html

运行模式:


pytest --html=report.html

报告效果:



image.png

在以上报告中可以清晰的看到测试结果和错误原因,定位问题很容易。


2.运行指定的case


  当我们写了较多的cases时,如果每次都要全部运行一遍,无疑是很浪费时间的,通过指定case来运行就很方便了。


例子代码:


class TestClassOne(object):
def test_one(self):
x = "this"
assert 't'in x def test_two(self):
x = "hello"
assert hasattr(x, 'check') class TestClassTwo(object):
def test_one(self):
x = "iphone"
assert 'p'in x def test_two(self):
x = "apple"
assert hasattr(x, 'check')

运行模式:


模式1:直接运行test_se.py文件中的所有cases:


pytest test_se.py

模式2:运行test_se.py文件中的TestClassOne这个class下的两个cases:


pytest test_se.py::TestClassOne

模式3:运行test_se.py文件中的TestClassTwo这个class下的test_one:


pytest test_se.py::TestClassTwo::test_one

注意:定义class时,需要以T开头,不然pytest是不会去运行该class的。


3.多进程运行cases


  当cases量很多时,运行时间也会变的很长,如果想缩短脚本运行的时长,就可以用多进程来运行。


安装pytest-xdist:


pip install -U pytest-xdist

运行模式:


pytest test_se.py -n NUM

其中NUM填写并发的进程数。


4.重试运行cases


  在做接口测试时,有事会遇到503或短时的网络波动,导致case运行失败,而这并非是我们期望的结果,此时可以就可以通过重试运行cases的方式来解决。


安装pytest-rerunfailures:


pip install -U pytest-rerunfailures

运行模式:


pytest test_se.py --reruns NUM

NUM填写重试的次数。


5.显示print内容


  在运行测试脚本时,为了调试或打印一些内容,我们会在代码中加一些print内容,但是在运行pytest时,这些内容不会显示出来。如果带上-s,就可以显示了。


运行模式:


pytest test_se.py -s

  另外,pytest的多种运行模式是可以叠加执行的,比如说,你想同时运行4个进程,又想打印出print的内容。可以用:


pytest test_se.py -s -n 4

学习网站:
pytest documentation
好用的Pytest单元测试框架(《51测试天地》四十九(下)- 44)
Pytest学习笔记
pytest单元测试框架

 

兼容unittest与nose


如果之前你的单测全部是基于unittest或者nose来编写的。
不用担心,执行pytest命令同样可以正常运行这些用例并得到结果。
因此无需担心迁移单测框架从而带来额外的人工成本。


常用插件


在之前的内容中,我们提到了pytest的一个优点是有大量的插件支持,例如:


    • pytest-django: 针对Django框架的单测框架
    • pytest-twisted: 针对twisted框架的单测框架
    • pytest-cov: 产生覆盖率报告
    • pytest-instafail: 发送错误时报告错误信息
    • pytest-bdd 测试驱动开发工具
    • pytest-konira 测试驱动开发工具
    • pytest-timeout: 支持超时功能
    • pytest-pep8: 支持PEP8检查
    • pytest-flakes: 结合pyflakes进行代码检查

Python之pytest 基础的更多相关文章

  1. [资料分享]Python视频教程(基础篇、进阶篇、项目篇)

    Python是一种开放源代码的脚本编程语言,这种脚本语言特别强调开发速度和代码的清晰程度.它可以用来开发各种程序,从简单的脚本任务到复杂的.面向对象的应用程序都有大显身手的地方.Python还被当作一 ...

  2. Python学习入门基础教程(learning Python)--5.6 Python读文件操作高级

    前文5.2节和5.4节分别就Python下读文件操作做了基础性讲述和提升性介绍,但是仍有些问题,比如在5.4节里涉及到一个多次读文件的问题,实际上我们还没有完全阐述完毕,下面这个图片的问题在哪呢? 问 ...

  3. Python学习笔记基础篇——总览

    Python初识与简介[开篇] Python学习笔记——基础篇[第一周]——变量与赋值.用户交互.条件判断.循环控制.数据类型.文本操作 Python学习笔记——基础篇[第二周]——解释器.字符串.列 ...

  4. Python 3 集合基础和概念!

    Python 3 集合基础和概念! Python 3中,集合是无序的,所以不能进行切片和索引操作. 创建集合有两个方法:set()方法创建的集合是可变的,可被迭代的:frozenset()方法创建的集 ...

  5. [Python] 文科生零基础学编程系列二——数据类型、变量、常量的基础概念

    上一篇:[Python] 文科生零基础学编程系列--对象.集合.属性.方法的基本定义 下一篇: (仍先以最简单的Excel的VBA为例,语法与Python不同,但概念和逻辑需要理解透彻) p.p1 { ...

  6. [Python] 文科生零基础学编程系列三——数据运算符的基本类别

    上一篇:[Python] 文科生零基础学编程系列二--数据类型.变量.常量的基础概念 下一篇: ※ 程序的执行过程,就是对数据进行运算的过程. 不同的数据类型,可以进行不同的运算, 按照数据运算类型的 ...

  7. Python网络编程基础pdf

    Python网络编程基础(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/1VGwGtMSZbE0bSZe-MBl6qA 提取码:mert 复制这段内容后打开百度网盘手 ...

  8. Python Numpy shape 基础用法(转自他人的博客,如涉及到侵权,请联系我)

    Python Numpy shape 基础用法 shape函数是numpy.core.fromnumeric中的函数,它的功能是读取矩阵的长度,比如shape[0]就是读取矩阵第一维度的长度.它的输入 ...

  9. python网络编程基础(线程与进程、并行与并发、同步与异步、阻塞与非阻塞、CPU密集型与IO密集型)

    python网络编程基础(线程与进程.并行与并发.同步与异步.阻塞与非阻塞.CPU密集型与IO密集型) 目录 线程与进程 并行与并发 同步与异步 阻塞与非阻塞 CPU密集型与IO密集型 线程与进程 进 ...

随机推荐

  1. percona顶级项目(针对数据库)

    percona顶级项目(针对数据库) 地址:https://github.com/Percona-Lab 1.mongodb_consistent_backupTool for getting con ...

  2. root_objectlist, root_object, container_objectlist, container_object 之间的关系。

  3. 接口,定义接口的关键字是 interface 实现接口关键字是 implements

    当抽象类中的方法都是抽象的时候,这时可以将该抽象类用另一种形式定义和表示,就是接口interface特点:对于接口中常见的成员:而且这些成员都有固定的修饰符,不写就默认存在1:全局常量 :  都是 p ...

  4. 查看npm仓库版本号

    http://repo.inspur.com:8081/artifactory/webapp/#/artifacts/browse/simple/General/thirdparty iop 找到现在 ...

  5. 以太坊nonce

    以太坊系列(ETH&ETC)在发送交易有三个对应的RPC接口,分别是ethsendTransaction.ethsendRawTransaction和personal_sendTransact ...

  6. [LeetCode] 744. Find Smallest Letter Greater Than Target_Easy tag: **Binary Search

    Given a list of sorted characters letters containing only lowercase letters, and given a target lett ...

  7. [xdoj]1303jlz的刷题黑科技

    先分析复杂度,给的数据是1e5的,那么我们至少需要一个nlogn的算法才可以.由于答案是一个数字,首先想到是二分法(一般答案是一个数字都可以通过二分法来完成) 下面是思路: 1.可以完成题目的条件是, ...

  8. Python+Selenium框架设计之框架内封装基类和实现POM

    原文地址https://blog.csdn.net/u011541946/article/details/70269965 作者:Anthony_tester 来源:CSDN    博客地址https ...

  9. Cocos Code IDE (下载地址)

    Cocos Code IDE 1.2.0 下载地址       Cocos Code IDE 1.2.0 Win32 下载地址: http://www.cocos2d-x.org/filedown/c ...

  10. IDEA2017及DataGrip2017注册码

    访问http://idea.lanyus.com/,网页中有相关说明,最简单的方式是将“0.0.0.0 account.jetbrains.com”添加到hosts文件中,然后点击页面底部的“获得注册 ...