Pytest简单介绍

(pytest是python的一个测试框架,主要是用来进行一些小的测试)

  • 安装:pip install -U pytest
  • 查看是否安装成功:pytest --version
  • 运行:在当前文件所在目录下执行pytest,会寻找当前目录以及子目录下以test开头的py文件或者以test结尾的py文件,找到文件后,在文件中找到以test开头函数并执行。(或者执行pytest 文件名--这样可以指定某个文件进行pytest的测试  或者  python -m pytest xxx.py)

在执行pytest xxx.py时,若增加参数:pytest -v -s xxx.py   (-v:显示运行的函数;-s:显示内部的打印信息)

  • 编写pytest测试样例的规则:
    1. 测试文件以test_开头
    2. 测试类以Test开头,并且不能带有init方法
    3. 测试函数以test_开头
    4. 断言使用基本的assert即可
  • 断言--正常:
assert value == 0
  • 断言--异常(pytest.raise方法):
 #断言1除以0,将产生一个ZeroDivisionError类型的异常。
import pytest
def test_zero_division():
with pytest.raises(ZeroDivisionError):
1 / 0 #有的时候,我们可能需要在测试中用到产生的异常中的某些信息,比如异常的类型type,异常的值value等等。下面我们修改下上面的测试:
import pytest
def test_recursion_depth():
with pytest.raises(ZeroDivisionError) as excinfo:
1/0
assert excinfo.type == 'RuntimeError'
#因为该测试断言产生的异常类型是RuntimeError,而实际上产生的异常类型是ZeroDivisionError,所以测试失败了。在测试结果中,可以看到assert子表达式excinfo.type的值。
  • 在test前,可以通过增加skip或xfail进行跳过(失败)测试案例
 import pytest

 # @pytest.mark.skipif()   跳过
# @pytest.mark.skip() 跳过
# @pytest.mark.xfail() 若出错跳过,pass也跳过,但会显示pass
def test_123():
# pytest.skip() 也可以实现'跳过'目的
assert 1 == 0
  • 简单例子:
 # coding:utf-8
import pytest def fun(x):
return x + 1 def test_fun():
assert fun(2) == 3

结果:

(venvX) F:\test_jiaxin>pytest test_para1.py
============================= test session starts =============================
platform win32 -- Python 2.7.9, pytest-3.7.1, py-1.5.3, pluggy-0.7.1
rootdir: F:\test_jiaxin, inifile:
plugins: allure-adaptor-1.7.10
collected 1 item test_para1.py . [100%] ========================== 1 passed in 0.09 seconds ===========================

pytest之feature-scope

  • function:每个test都运行,默认是function的scope.
  • class:每个class的所有test只运行一次.
  • module:每个module的所有test只运行一次.
  • session:每个session只运行一次.

比如你的所有test都需要连接同一个数据库,那可以设置为module,只需要连接一次数据库,对于module内的所有test,这样可以极大的提高运行效率。

代码:

 @pytest.fixture(scope="module")
def hero_backup_policy(self, acmp_cfg):
return AcloudBackupPolicy(acmp_cfg) @pytest.fixture(scope="function")
def hero_acloud_backup_policy(self, acmp_cfg):
return Server(acmp_cfg)

pytest的参数化方式

  • pytest.fixture()方式进行参数化,fixture装饰的函数可以作为参数传入其他函数

  • conftest.py 文件中存放参数化函数,可作用于模块内的所有测试用例

  • pytest.mark.parametrize()方式进行参数化

待测试代码片段:(is_leap_year.py)

 # coding:utf-8
def is_leap_year(year):
# 先判断year是不是整型
if isinstance(year, int) is not True:
raise TypeError("传入的参数不是整数")
elif year == 0:
raise ValueError("公元元年是从公元一年开始!!")
elif abs(year) != year:
raise ValueError("传入的参数不是正整数")
elif (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
print"%d年是闰年" % year
return True
else:
print"%d年不是闰年" % year
return False
  • pytest.fixture()

  1. pytest.fixture()中传入的参数为list,用例执行时,遍历list中的值,每传入一次值,则相当于执行一次用例。

  2. @pytest.fixture()装饰的函数中,传入了一个参数为request。

  3. 这里的测试数据是直接存在list中的,能否存入json文件或者xml文件再进行读取转换为list呢?

代码:

 # coding:utf-8
import is_leap_year
import pytest class TestPara():
is_leap = [4, 40, 400, 800, 1996, 2996]
is_not_leap = [1, 100, 500, 1000, 1999, 3000]
is_valueerror = [0, -4, -100, -400, -1996, -2000]
is_typeerror = ['-4', '', '', 'ins', '**', '中文'] @pytest.fixture(params=is_leap)
def is_leap(self, request):
return request.param @pytest.fixture(params=is_typeerror)
def is_typeerror(self, request):
return request.param def test_is_leap(self, is_leap):
assert is_leap_year.is_leap_year(is_leap) == True def test_is_typeerror(self, is_typeerror):
with pytest.raises(TypeError):
is_leap_year.is_leap_year(is_typeerror)
  • conftest.py 文件 -- 测试数据与用例分离

  1. 采用conftest.py文件存储参数化数据和函数,模块下的用例执行时,会自动读取conftest.py文件中的数据。

代码:

 conftest.py文件
1 # coding:utf-8
import pytest is_leap = [4, 40, 400, 800, 1996, 2996]
is_not_leap = [1, 100, 500, 1000, 1999, 3000]
is_valueerror = [0, -4, -100, -400, -1996, -2000]
is_typeerror = ['-4', '', '', 'ins', '**', '中文'] @pytest.fixture(params=is_leap)
def is_leap(request):
return request.param @pytest.fixture(params=is_typeerror)
def is_typeerror(request):
return request.param
 test_para.py文件
1 # coding:utf-8 import is_leap_year
import pytest class TestPara():
def test_is_leap(self, is_leap):
assert is_leap_year.is_leap_year(is_leap) == True def test_is_typeerror(self, is_typeerror):
with pytest.raises(TypeError):
is_leap_year.is_leap_year(is_typeerror)
  • pytest.mark.parametrize() -- 进行参数化

  1. 采用标记函数参数化,传入单个参数,pytest.mark.parametrize("参数名",lists)。
  2. 采用标记函数传入多个参数,如pytest.mark.parametrize("para1, para2", [(p1_data_0, p2_data_0), (p1_data_1, p2_data_1),...]。
  3. 这里:测试用例中传入2个参数,year和期望结果,使输入数据与预期结果对应,构造了2组会失败的数据,在执行结果中,可以看到失败原因。

代码:

 # coding:utf-8
import is_leap_year
import pytest class TestPara():
# 参数传入year中
@pytest.mark.parametrize('year, expected', [(1, False), (4,True), (100, False), (400, True), (500, True)])
def test_is_leap(self, year, expected):
assert is_leap_year.is_leap_year(year) == expected @pytest.mark.parametrize('year, expected', [(0, ValueError),('-4', TypeError), (-4, ValueError), ('ss', TypeError), (100.0, ValueError)])
def test_is_typeerror(self, year, expected):
if expected == ValueError:
with pytest.raises(ValueError) as excinfo:
is_leap_year.is_leap_year(year)
assert excinfo.type == expected
else:
with pytest.raises(TypeError) as excinfo:
is_leap_year.is_leap_year(year)
assert excinfo.type == expected

参考链接:https://blog.csdn.net/zhusongziye/article/details/79902772

pytest-fixture扩展内容

1.  把一个函数定义为Fixture很简单,只能在函数声明之前加上“@pytest.fixture”。其他函数要来调用这个Fixture,只用把它当做一个输入的参数即可。

 import pytest

 @pytest.fixture()
def before():
print '\nbefore each test' def test_1(before):
print 'test_1()' def test_2(before):
print 'test_2()'

result:

(venvX) F:\test_jiaxin>pytest -v -s test_compute.py
============================= test session starts =============================
platform win32 -- Python 2.7.9, pytest-3.7.1, py-1.5.3, pluggy-0.7.1 -- f:\projects\sandom\venvx\scripts\python.exe
cachedir: .pytest_cache
rootdir: F:\test_jiaxin, inifile:
plugins: allure-adaptor-1.7.10
collected 2 items test_compute.py::test_1
before each test
test_1()
PASSED
test_compute.py::test_2
before each test
test_2()
PASSED ========================== 2 passed in 0.17 seconds ===========================

2.  进行封装

 import pytest

 @pytest.fixture()
def before():
print '\nbefore each test' # 每个函数前声明
@pytest.mark.usefixtures("before")
def test_1():
print 'test_1()'
@pytest.mark.usefixtures("before")
def test_2():
print 'test_2()' #封装在类里,类里的每个成员函数声明
class Test1:
@pytest.mark.usefixtures("before")
def test_3(self):
print 'test_1()'
@pytest.mark.usefixtures("before")
def test_4(self):
print 'test_2()' #封装在类里在前声明
@pytest.mark.usefixtures("before")
class Test2:
def test_5(self):
print 'test_1()'
def test_6(self):
print 'test_2()'

result:

(venvX) F:\test_jiaxin>pytest -v -s test_compute.py
============================= test session starts =============================
platform win32 -- Python 2.7.9, pytest-3.7.1, py-1.5.3, pluggy-0.7.1 -- f:\projects\sandom\venvx\scripts\python.exe
cachedir: .pytest_cache
rootdir: F:\test_jiaxin, inifile:
plugins: allure-adaptor-1.7.10
collected 6 items test_compute.py::test_1
before each test
test_1()
PASSED
test_compute.py::test_2
before each test
test_2()
PASSED
test_compute.py::Test1::test_3
before each test
test_1()
PASSED
test_compute.py::Test1::test_4
before each test
test_2()
PASSED
test_compute.py::Test2::test_5
before each test
test_1()
PASSED
test_compute.py::Test2::test_6
before each test
test_2()
PASSED ========================== 6 passed in 0.11 seconds ===========================

3.  fixture还可以带参数,可以把参数赋值给params,默认是None。对于param里面的每个值,fixture都会去调用执行一次,就像执行for循环一样把params里的值遍历一次。

 import pytest

 @pytest.fixture(params=[1, 2, 3])
def test_data(request):
return request.param def test_not_2(test_data):
print('test_data: %s' % test_data)
assert test_data != 2

result:

(venvX) F:\test_jiaxin>pytest -v -s test_compute.py
============================= test session starts =============================
platform win32 -- Python 2.7.9, pytest-3.7.1, py-1.5.3, pluggy-0.7.1 -- f:\projects\sandom\venvx\scripts\python.exe
cachedir: .pytest_cache
rootdir: F:\test_jiaxin, inifile:
plugins: allure-adaptor-1.7.10
collected 3 items test_compute.py::test_not_2[1] test_data: 1
PASSED
test_compute.py::test_not_2[2] test_data: 2
FAILED
test_compute.py::test_not_2[3] test_data: 3
PASSED ================================== FAILURES ===================================
________________________________ test_not_2[2] ________________________________ test_data = 2 def test_not_2(test_data):
print('test_data: %s' % test_data)
> assert test_data != 2
E assert 2 != 2 test_compute.py:64: AssertionError
===================== 1 failed, 2 passed in 0.12 seconds ======================

pytest单侧模块_入门汇总的更多相关文章

  1. 【转】Nginx模块开发入门

    转自: http://kb.cnblogs.com/page/98352/ 结论:对Nginx模块开发入门做了一个helloworld的示例,简单易懂.也有一定的深度.值得一看. Nginx模块开发入 ...

  2. Nginx模块开发入门

    前言 Nginx是当前最流行的HTTP Server之一,根据W3Techs的统计,目前世界排名(根据Alexa)前100万的网站中,Nginx的占有率为6.8%.与Apache相比,Nginx在高并 ...

  3. [转] Nginx模块开发入门

    前言 Nginx是当前最流行的HTTP Server之一,根据W3Techs的统计,目前世界排名(根据Alexa)前100万的网站中,Nginx的占有率为6.8%.与Apache相比,Nginx在高并 ...

  4. Nginx模块开发入门(转)

    前言 Nginx是当前最流行的HTTP Server之一,根据W3Techs的统计,目前世界排名(根据Alexa)前100万的网站中,Nginx的占有率为6.8%.与Apache相比,Nginx在高并 ...

  5. Nginx模块开发入门(转)

    前言 Nginx是当前最流行的HTTP Server之一,根据W3Techs的统计,目前世界排名(根据Alexa)前100万的网站中,Nginx的占有率为6.8%.与Apache相比,Nginx在高并 ...

  6. FW: Nginx模块开发入门

    前言 Nginx是当前最流行的HTTP Server之一,根据W3Techs的统计,目前世界排名(根据Alexa)前100万的网站中,Nginx的占有率为6.8%.与Apache相比,Nginx在高并 ...

  7. nginx http模块开发入门

    导语 本文对nginx http模块开发需要掌握的一些关键点进行了提炼,同时以开发一个简单的日志模块进行讲解,让nginx的初学者也能看完之后做到心里有谱.本文只是一个用作入门的概述. 目录 背景 主 ...

  8. 论坛模块_版块管理_增删改查&实现上下移动

    论坛模块_版块管理1_增删改查 设计实体Forum.java public class Forum { private Long id; private String name; private St ...

  9. 系统管理模块_用户管理1_实现用户有关的功能_测试功能、解决事务的问题、对密码进行MD5摘要

    系统管理模块__用户管理1__实现用户有关的功能 了解用户管理要做什么(增删改查初始化密码) 设计实体 分析功能有几个对应几个请求 增删改查有6个请求,初始化密码一个 实现增删改查一组功能的步骤流程 ...

随机推荐

  1. java基础语法——方法,static关键字

    一:方法: 1.什么是方法: 通俗地讲,方法就是行为.它是完成特定功能的代码块能执行一个功能.它包含于类和对象中. 2.为什么要有方法: *提高代码的复用性. *提高效率 *利于程序维护 3.命名规则 ...

  2. 微服务 Framework

    Dubbo :https://github.com/dubbo Spring Cloud :https://github.com/spring-cloud

  3. nexus3.1私服搭建

    原文:http://blog.csdn.net/qqqqq210/article/details/52993337 1.简介 近期公司需要搭建jenkins自动化构建部署,需要搭建nexus私服环境, ...

  4. 项目中遇到的HQL查询问题

    问题描写叙述: 目的:想要查询出全部最新版本号的组件 说明:组件:版本号 =1:n关系 ,假设这个组件仅仅有一个版本号也要可以查出来. 项目中使用的是内存数据库,无法看到表结构,这里的样例仅仅用于模拟 ...

  5. Angular2.x

    Angular版本 Angular1和Angular4分别是Angular的两个版本,也就是Angular1.x和Angular2.x(除了Angular1以外,其余都属于Angular2.x). 1 ...

  6. ZOJ 3632 Watermelon Full of Water (线段树 区间更新 + dp)

    题目大意: 让每天都能吃到西瓜. 最少须要花多少钱. 思路分析: dp[pos] 就表示  要让 前i天每天都有西瓜吃.最少须要花多少钱. 那么假设你买这个西瓜的话. 那么这个西瓜能吃的持续时间都要更 ...

  7. 从PRISM开始学WPF(一)WPF?

    从PRISM开始学WPF(一)WPF?   我最近打算学习WPF ,在寻找MVVM框架的时候发现了PRISM,在此之前还从一些博客上了解了其他的MVVM框架,比如浅谈WPF中的MVVM框架--MVVM ...

  8. IE9版本号下面ajax 跨域问题解决

    ajax跨域请求数据在谷歌火狐我本地IE11都是没问题的. 让測试就发现问题了,IE8下请求不到数据.然后我查看一下自己写的js看有没有不兼容问题.但是都没有啊.为什么就请求不到呢. 我把ajax的e ...

  9. ubuntu hadoop伪分布式部署

    环境 ubuntu hadoop2.8.1 java1.8 1.配置java1.8 2.配置ssh免密登录 3.hadoop配置 环境变量 配置hadoop环境文件hadoop-env.sh core ...

  10. Hibernate 之 Mapping

    转自:  http://blog.csdn.net/jnqqls/article/details/8372732 从前面的介绍的Hibernate文章中我们已经对Hibernate有了一个初步的认识, ...