文章目录
- 参数化 parametrize
- 适用场景
- 一个典型的例子
- 前置fixture+参数化
- 适用场景
- 一个典型的例子
- 示例2
- 个人疑问?
pytest既可以用来做单元测试,也可以用来做自动化接口测试,pytest可以结合allure生成漂亮的测试报告,经过一段时间的学习,记录下在单元测试中用到的比较常用的方法
参数化 parametrize
适用场景
在学习pytest的时候学的时候用的最多且最先学习的是参数化,
- 他的应用场景是:比如我需要用自己设计的用例来调用某一个函数多次,当我设计了10个不同的用例,那么我就需要调用十次函数。
- 以常规的思路想,循环也可以做到啊。但是pytest有参数化这个强大的功能。
一个典型的例子
# content of test_expectation.py# coding:utf-8import pytest
#这里设置了三组测试用例,每组用例用()来表示,用例之间用“,”隔开
@pytest.mark.parametrize("test_input,expected",[ ("3+5", 8),("2+4", 6),("6 * 9", 42),])
def test_eval(test_input, expected): #此处用参数化命名的参数名assert eval(test_input) == expected#
if __name__ == "__main__":pytest.main(["-s", "test_canshu1.py"])
运行结果:
================================== FAILURES ===================================
_____________________________ test_eval[6 * 9-42] _____________________________test_input = '6 * 9', expected = 42@pytest.mark.parametrize("test_input,expected",[ ("3+5", 8),("2+4", 6),("6 * 9", 42),])def test_eval(test_input, expected):
> assert eval(test_input) == expected
E AssertionError: assert 54 == 42
E + where 54 = eval('6 * 9')test_canshu1.py:11: AssertionError
===================== 1 failed, 2 passed in 1.98 seconds ======================
前置fixture+参数化
适用场景
在继参数化之后用到的一个功能强大的是前置fixture
- 应用场景1:用例1需要先登录,用例2不需要登录,用例3需要
先登录 - 应用场景2:比如说你需要实例化一个类之后再分别调用里面的各个函数,而且是需要在实例化的时候传入几个不同的用例(参数化解决)
- 以常规的做法来做场景2,需要在每个函数调用的时候都实例化一次,所以fixture前置来做实例化(例2会有示例)
一个典型的例子
# coding:utf-8import pytest# 不带参数时默认scope="function"
@pytest.fixture()
def login():print("输入账号,密码先登录")def test_s1(login):print("用例1:登录之后其它动作111")def test_s2(): # 不传loginprint("用例2:不需要登录,操作222")def test_s3(login):print("用例3:登录之后其它动作333")if __name__ == "__main__":pytest.main(["-s", "test_fix.py"])
运行结果:
============================= test session starts =============================
platform win32 -- Python 3.6.0, pytest-3.6.3, py-1.5.4, pluggy-0.6.0
rootdir: E:\YOYO, inifile:
collected 3 itemstest_fix.py 输入账号,密码先登录
用例1:登录之后其它动作111
.用例2:不需要登录,操作222
.输入账号,密码先登录
用例3:登录之后其它动作333
.========================== 3 passed in 0.06 seconds ===========================
示例2
#coding = utf-8
import os,re
import sys
lib_path = os.path.abspath(os.path.join('E:\测试项目\models'))
sys.path.append(lib_path)
import pytest
import dataModel as A
import logging
import pandas as pd
import numpy as np
from utils.type_processing import stringToTimelogging.basicConfig(level=logging.DEBUG,format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')#五个需要测试的用例,参数化需要用到的参数
data = [("E:\测试项目\讲话.xlsx"),("E:\测试项目\党章党规目录(2019年6月26日版).xls"),("E:\测试项目\lilun.txt"),("E:\\测试项目\\test1.xlsx"),("E:\\测试项目\\test1.txt")]#前置fixture,范围为module,代表每个class执行一次
@pytest.fixture(scope = "module")
def a(request):filepath = request.paramx = A.DataModel(filepath) #此处是实例化print("现在测试的是文件 %s" % filepath)return x#参数化,把上面五个用例传入,a代表前置fixture
@pytest.mark.parametrize("a",data,indirect=True)
class TestData(object):#存在title的文件def test_title(self,a):C = a if C.df.empty:print("文件为空")else:msg = "文件的标题为空"title = C.extract_title()assert title != -1,msgdef test_author(self,a):C = aif C.df.empty:print("文件为空")else:msg = "文件的作者为空"author = C.extract_author()assert author != -1,msgdef test_content(self,a):C = aif C.df.empty:print("文件为空")else:#msg = "文件的标题为空"content = C.extract_content()assert content is not Nonedef test_time(self,a):C = aif C.df.empty:print("文件为空")else:msg = "文件的时间为空"time = C.extract_time()assert time != -1,msg
为什么参数化函数@pytest.mark.parametrize("a",data,indirect=True)
参数a为前置fixture?解答:注意在参数化那里写了一个indirect=True的参数,所以前面“a”为前置,后面的data为参数化的参数名。
个人疑问?
- pytest的应用场景那么广,但是为什么网上的单元测试的代码或者博文却很少,大多数都是做的接口自动化?
- 如果pytest应用于单元测试,那么断言对于我来说,通常是一个比较大的障碍,因为大多时候一个函数的输出,在用参数化的时候,输出的结果不能用统一的assert来做出判断。
- 单元测试似乎不受到特别的重视,或者说一个项目没有完整的单元测试?
- 还需努力呀!