测试开发进阶之Pytest框架实战

今天我们使用pytest来进行自动化测试的实战:

一.pytest基础操作

pytest规则:

1.pytest中的 测试用例(函数): 必须以 test_ 开头 或 _test结尾
2.pytest中的 测试模块文件(test_xxx.py): 必须以 test_开头
3.pytest中的 测试类 必须以 Testxxx开头

二.pytest运行方式

pytest.main([*args])

*args参数详解:

-s 显示输出语句的内容

-v 打印测试用例执行的状态

-m 标记名 执行指定标记名对应的测试用例

test_login.py 指定测试运行文件

三.pytest前置后置

类级别前置后置:

setup_class(cls)、teardown_class(cls)

函数级别前置后置:

setup(self)、teardown(self)

class TestDemo:

# 前置: 每条以test_开头的测试用例执行前, 执行一次

def setup(self):

print("setup")

# 后置:  每条以test_开头的测试用例执行后, 执行一次
def teardown(self):
    print('teardown')

# 类级别前置: 第一条测试用例执行前, 执行一次, 仅一次
@classmethod
def setup_class(cls):
    print("setup_class")
# 类级别后置, 最后一条测试用例执行后, 执行一次, 仅一次
@classmethod
def teardown_class(cls):
    print("teardown_class")

四.pytest.ini配置文件

pytest.ini配置文件的优先级, 高于所有的pytest框架中的其它模块内容.

pytest.ini配置文件, 编码格式, 必须是 gbk.

[pytest]

opts == options 选项/参数

addopts = -s -v

指定测试用例类所在 模块文件的命名规则 必须满足 test_xxx.py

python_files = test_*.py

测试用例类的命名规则 Testxxx

python_classes = Test*

测试用例命名规则

python_functions = test_*

在执行pytest中的测试用例时, 测试用例函数在加载前会优先加载 pytest.ini中的规则.

markers标记: 过滤用例, 对用例进行分组执行.

markers =

smoke : smoking test

login : login test

demo : demo test

对测试用例进行标记:

@pytest.mark.标记名 # 标记名 必选先在 pytest.ini中的markers中进行描述, 才可以使用

执行时, 通过 参数 '-m 标记名' 进行过滤即可.

pytest.main(['-m 标记名'])

五.pytest参数化

@pytest.mark.parametrize("argsname",argsvalue)

argsvalue 必须是 列表[] 或 元组(); argsname是字符串参数数据; argsname必须作为形参出入到测试用例函数的形参位置

argsvalue 如果是嵌套结构, 当参数为1时, 将列表/元组中的元素, 循环赋值给字符串参数, 列表/元组中的元素有多少个, 则会循环多少次, 赋值了多少次.

当参数为2 或 多个时, 对于argsvalue的数据格式要求必须满足: 二维列表(嵌套列表) 或 列表嵌套元组, 元组嵌套列表.

反向测试数据

err_data = [

['错误的用户名','qftest02','qftest01.',{"code":1,"msg":"账号或密码不正确"}],

['错误的密码','qftest01','qftest01',{"code":1,"msg":"账号或密码不正确"}],

['用户名为空',None,'qftest01',{"code": 1, "msg": "参数不能为空"}],

['密码为空','qftest01',None,{"code": 1, "msg": "参数不能为空"}]

]

通过参数化的方式, 一个函数多次执行不同的 数据 实现相同函数内容的测试用例

参数化通过: @pytest.mark.parametrize(argsname, argsvalue)

argsname必须是字符串, argsname中的参数必须与argsvalue中的元素个数 保持一致

argsname会被pytest识别为 测试用例函数的 形参

parametrize() 建议使用列表或元组

@pytest.mark.parametrize("title,username,password,expect", err_data)

def test_login_errcase(self,title, username, password, expect):

result = login_check(username, password)

print(title)# 用例标题

assert result == expect

六.pytest断言- assert

assert a == b 断言a与b相等

assert a != b断言a与b不相等

assert a in b断言a包含在b中

assert a not in b断言a不包含在b中

assert a is None 断言a的值为None

assert a is not None 断言a的值不为None

案例:

test_login.py

from time import sleep

import pytest

import allure

from selenium import webdriver

err_datas = [

['错误的用户名','13800138007','123456','1111'],

['错误的密码','13800138006','1234567','1111'],

['用户名输入空字符串','','123456','1111'],

['密码输入空字符串','13800138006','','1111'],

['验证码输入空字符串','13800138006','123456',''],

['用户名超出长度','13800','123456','1111']

]

@allure.feature("登录功能")

class TestLogin:

def setup(self):
    pass

def teardown(self):
    sleep(1)
    # 每条用例执行后, 刷新
    self.driver.refresh()

@classmethod # 通过classmethod修饰的函数 级别是 类方法/类函数
def setup_class(cls):
    cls.driver = webdriver.Chrome() # 创建Chrome类对象, 赋值给 类变量 cls.driver
    cls.driver.maximize_window()
    cls.driver.implicitly_wait(10)
    cls.driver.get('http://10.36.176.114/index.php/Home/user/login.html')

@classmethod
def teardown_class(cls):
    sleep(2)
    cls.driver.quit()

@allure.story('反向')
@pytest.mark.err
@pytest.mark.parametrize('title,name,pwd,code', err_datas)
def test_login_err_case(self, title, name, pwd, code):
    allure.dynamic.title(title)
    self.driver.find_element_by_id("username").send_keys(name)
    self.driver.find_element_by_id("password").send_keys(pwd)
    self.driver.find_element_by_id("verify_code").send_keys(code)
    self.driver.find_element_by_name('sbtbutton').click()

@allure.story("正向")
@pytest.mark.smoke
def test_login_success(self):
    self.driver.find_element_by_id("username").send_keys('13800138006')
    self.driver.find_element_by_id("password").send_keys('123456')
    self.driver.find_element_by_id("verify_code").send_keys('111')
    self.driver.find_element_by_name('sbtbutton').click()

runner.py

-- coding: utf-8 --

import pytest
import os
import shutil

if name == 'main':
# 1.判断 ./html ./report 目录是否存在
# 2. 如果存在, 则删除; 如果不存在, 则pass 略过
if os.path.exists('./html') and os.path.exists('./report'):
shutil.rmtree('./html')
shutil.rmtree('./report')
# --aluredir 目录 指定运行测试用例产生数据保存的目录
pytest.main(['--alluredir','./report'])
# allure generate 生成allure报告 从./report中加载数据 -o output 生成报告存储的位置
os.system('allure generate ./report -o ./html --clean') # --clean 清除之前的数据

最后:下面是配套学习资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!

软件测试面试小程序

被百万人刷爆的软件测试题库!!!谁用谁知道!!!全网最全面试刷题小程序,手机就可以刷题,地铁上公交上,卷起来!

涵盖以下这些面试题板块:

1、软件测试基础理论 ,2、web,app,接口功能测试 ,3、网络 ,4、数据库 ,5、linux

6、web,app,接口自动化 ,7、性能测试 ,8、编程基础,9、hr面试题 ,10、开放性测试题,11、安全测试,12、计算机基础

  全套资料获取方式:点击下方小卡片自行领取即可

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值