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. centos、mac的grafana安装和简单使用

    1.安装: 参考官方文档安装说明:https://grafana.com/grafana/download Redhat & Centos(64 Bit): wget https://s3-u ...

  2. ECC数据结构

    在SM2 ECC算法中,有针对签名加密的数据结构,下面对这些结构进行分析 #define ECCref_MAX_BITS 512 #define ECCref_MAX_LEN ((ECCref_MAX ...

  3. [Angular] Communicate Between Components Using Angular Dependency Injection

    Allow more than one child component of the same type. Allow child components to be placed within the ...

  4. Android网络编程之使用HTTP訪问网络资源

    使用HTTP訪问网络资源 前面介绍了 URLConnection己经能够很方便地与指定网站交换信息,URLConnection另一个子类:HttpURLConnection,HttpURLConnec ...

  5. MySQL 当记录不存在时插入,当记录存在时更新

    第一种: 示例一:插入多条记录 假设有一个主键为 client_id 的 clients 表,可以使用下面的语句: INSERT INTO clients (client_id,client_name ...

  6. smartfoxserver扩展里面过滤聊天的不合法字符

    http://blog.csdn.net/yc7369/article/details/35567105 近期做手游客户要求加上一个聊天功能.事实上嘛,个人认为这个聊天功能比較鸡肋,这部分差点儿已经有 ...

  7. sql server 笔记1--case、WAITFOR、TRY CATCH

    一.case 转自:http://blog.csdn.net/add8849/article/details/576424 深入使用:http://blog.csdn.net/akuoma/artic ...

  8. asp.net编码解码的两篇文章

    http://www.cnblogs.com/freshman0216/p/4165949.html http://www.cnblogs.com/freshman0216/p/4172655.htm ...

  9. C# 中串口通信 serialport1.DataReceived 函数无法触发或者出发延时等等问题解决方法

    以前这个问题困扰我多天最后查资料一大堆,最后最终攻克了,看到非常多人做C#串口都遇到相同的问题,所以写一篇博文,以便学习交流. 一定要在com实例化的时候设置ReceivedBytesThreshol ...

  10. keywords和favicon

    1.<meta name="keywords" content="xxx"> 曾经网站风靡关键词堆积,往往在首页上设置大量的关键词,以获取最大范围搜 ...