pytest自动化测试1-pytest基础知识

pytest自动化测试基础教程
本文介绍了pytest自动化测试的基础知识,包括如何在PyCharm中创建虚拟环境,pytest的安装,用例规则,执行方法,断言使用,setup和teardown的运用,以及用例执行结果的类型。

一、通过pycharm下创建一个基于虚拟环境的项目

在这里插入图片描述

二、pytest安装

方法1:pycharm工具下安装pytest
在这里插入图片描述
方法2:pip安装pytest

#默认源安装
pip install -U pytest

#华为镜像源安装
pip3 install pytest -i https://mirrors.huaweicloud.com/ --trusted-host mirrors.huaweicloud.com/

#查看版本
pytest --version

方法3:通过requirements.txt文件批量安装pytest及其插件

在项目的根目录下新建文件requirements.txt,在文件中把需要的插件名字写进去,例如

requirements.txt

pytest
pytest-html
pytest-xdist
pytest-ordering
pytest-rerunfailures
allure-pytest
pyyaml
requests

然后通过如下命令进行安装和查看插件安装结果

#批量安装第三方库
pip install -r requirements.txt
#查看安装结果和版本
pip freeze

三、一个pytest的例子

创建一个文件test_start.py,内容如下

#!/usr/bin/env python
# -*- coding: utf-8 -*-

def func(x):
    return x + 1

def test_case1(): #函数需要以test_开头
    assert func(13) == 15

class TestClass: #类名也需要以Test开头
    def test_case2(self): #类中的方法名也需要以test_开头
        x = "this"
        assert "h" in x

    def test_case3(self):
        x = "hello"
        assert hasattr(x, "check")

用例执行方法:
(1) 命令行方式:在cmd下直接执行 pytest 即可运行测试用例。
(2)代码方式:在任意一个py文件中的main中调用pytest.main(),例如:

if __name__ == '__main__':
	pytest.main()	# 直接写在py文件中运行,()里可以填写运行的参数,也可以不写

(3)在pycharm工具上运行
在settings里面设置单元测试框架为Pytest
在这里插入图片描述
在项目、文件夹或文件上右键,选择pytest方式运行。
在这里插入图片描述

四、Pytest用例的规则

​pytest是自动发现、收集、执行测试用例的,当在哪个目录下执行pytest.main()指令,那么pytest就会自动发现当前目录下所有符合规则的py文件,将这些文件当成测试用例文件。pytest根据以下规则去发现用例:
1、模块名以 test_*.py 文件和*_test.py(即以test_开头或_test结尾的py文件)
2、以 test_ 开头的函数
3、以 Test 开头的类,不能包含 init 方法
4、以 test_ 开头的类里面的方法
5、所有的包 package 必须要有__init__.py 文件
6、pytest是根据规则按顺序匹配:模块 > > 类名 > > 方法名,同一个py文件中,从上往下执行测试用例。如果一个测试用例的方法在一个类或者模块下面,该测试用例的方法名符合规则,但是类名或者模块名不符合规则,那么该测试用例方法是不会被发现也不会被执行的。
7、可以在pytest.ini中配置自定义的查找规则。pytest.ini文件要放在项目的根目录下,pytest.ini文件内容举例如下:

[pytest]	# 只能修改=右边的值
python_files = demo_*.py	# 模块名以demo_开头
python_functions = demo_*	# 方法名以demo_开头
python_classes = Demo*	    # 类名名以Demo开头

五、Pytest用例执行及其参数

1、执行某个目录下所有的用例。pytest会查找当前目录及其子目录下以 test_*.py 或 *_test.py 文件,找到文件后,在文件中找到以 test_ 开头函数并执行。

pytest           #不指定目录,为当前目录及子目录下的所有测试文件
pytest testcase  #指定某个目录及子目录下的所有测试文件

2、执行指定的某一个 py 文件(模块)下的用例,例如对start.py文件 (文件名不需要是 test_*.py 或 *_test.py )

pytest start.py

3、运行start.py 模块里面的某个函数,或者某个类,某个类里面的方法。​加-v时打印的信息更详细。

pytest start.py::TestClass::test_case2
pytest -v start.py::TestClass::test_case2
pytest start.py::test_case1

4、-m 标记表达式,只执行用 @pytest.mark.xxx 装饰器修饰的所有用例

pytest -m xxx

5、-q 简单打印,只打印测试用例的执行结果

pytest -q start.py

6、-s 详细打印执行日志

pytest -s start.py

7、-x 遇到错误时停止测试

pytest start.py -x

8、–maxfail=num,当用例错误个数达到指定数量时,停止测试

pytest start.py --maxfail=1

9、-k 匹配用例名称

pytest -s -k http start.py  #执行测试用例名称包含http的所有用例
pytest -s -k "not http" start.py  #根据用例名称排除包含http的用例
pytest -s -k "method or weibo" start.py  #同时匹配不同的用例名称

六、Pytest中的断言使用

1、assert方法
pytest使用assert关键字来进行断言,assert关键字后面可以接一个表达式。

assert 表达式, 错误提示信息

表达式的结果为True,则断言通过,用例执行成功,否则用例执行失败。例如:

def test_function():
    a = 1
    assert a % 2 == 0, "判断 a 为偶数,当前 a 的值为:%s" % a

断言后面的字符串,在用例执行失败后会打印,方便查看失败原因。
pytest的断言,常用的有以下几种:

assert xx :判断 xx 为真
assert not xx :判断 xx 不为真
assert a in b :判断 b 包含 a
assert a not in b:判断b不包含a
assert a == b :判断 a 等于 b
assert a != b :判断 a 不等于 b

2、异常断言
可以使用 pytest.raises 作为上下文管理器,当抛出异常时可以获取到对应的异常实例。

# 断言异常
def test_zero_division_long():
    with pytest.raises(ZeroDivisionError) as excinfo:
        1 / 0

    # 断言异常类型 type
    assert excinfo.type == ZeroDivisionError
    # 断言异常 value 值
    assert "division by zero" in str(excinfo.value)

excinfo 是一个异常实例,其主要属性有: .type (异常类型)、 .value(异常值) 、 .traceback
注意:断言 type 的时候,异常类型是不需要加引号的,断言 value值的时候需转 str类型。

3、match关键字参数
可以将 match 关键字参数传递给上下文管理器,以测试正则表达式与异常的字符串是否匹配。
注意:这种方法只能断言value,不能断言type。

def test_zero_division_long():
    with pytest.raises(ZeroDivisionError, match=".*zero.*") as excinfo:
        1 / 0

4、检查断言装饰器

# 断言装饰器
@pytest.mark.xfail(raises=ZeroDivisionError)
def test_f():
    1 / 0

上述代码会抛出异常,但是抛出的异常和raises指定的异常类相匹配,所以不会断言失败。它相当于一个检查异常装饰器,目的是检查是否有异常,不确定是否有异常。
with pytest.raise(ZeroDivisionError) 对于故意测试异常代码的情况,使用可能会更好。
而@pytest.mark.xfail(raises=ZeroDivisionError) 对于检查未修复的错误(即可能会发生异常),使用检查断言可能会更好。

七、setup和teardown的使用

pytest中提供了多种不同的前置方法和后置方法,分别是:
模块级别:setup_module、teardown_module
函数级别:setup_function、teardown_function,不在类中的方法
类级别:setup_class、teardown_class
方法级别:setup_method、teardown_method,在类中的方法

示例:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pytest

def setup_module():
    print("=====整个.py模块开始前只执行一次setup_module,打开浏览器=====")

def teardown_module():
    print("=====整个.py模块结束后只执行一次teardown_module,关闭浏览器=====")

def setup_function():
    print("===每个函数级别用例开始前都执行setup_function===")

def teardown_function():
    print("===每个函数级别用例结束后都执行teardown_function====")

def test_one():
    print("one")

def test_two():
    print("two")

class TestCase():
    def setup_class(self):
        print("====整个测试类开始前只执行一次setup_class====")

    def teardown_class(self):
        print("====整个测试类结束后只执行一次teardown_class====")

    def setup_method(self):
        print("==类里面每个用例执行前都会执行setup_method==")

    def teardown_method(self):
        print("==类里面每个用例结束后都会执行teardown_method==")

    def test_three(self):
        print("three")

    def test_four(self):
        print("four")

if __name__ == '__main__':
    pytest.main(["-q", "-s", "-ra", "test_main.py"])

执行结果如下:

============================= test session starts =============================
collecting ... collected 4 items

test_main.py::test_one =====整个.py模块开始前只执行一次setup_module,打开浏览器=====
===每个函数级别用例开始前都执行setup_function===
PASSED                                            [ 25%]one
===每个函数级别用例结束后都执行teardown_function====

test_main.py::test_two ===每个函数级别用例开始前都执行setup_function===
PASSED                                            [ 50%]two
===每个函数级别用例结束后都执行teardown_function====

test_main.py::TestCase::test_three 
test_main.py::TestCase::test_four 

============================== 4 passed in 0.06s ==============================

Process finished with exit code 0
====整个测试类开始前只执行一次setup_class====
==类里面每个用例执行前都会执行setup_method==
PASSED                                [ 75%]three
==类里面每个用例结束后都会执行teardown_method==
==类里面每个用例执行前都会执行setup_method==
PASSED                                 [100%]four
==类里面每个用例结束后都会执行teardown_method==
====整个测试类结束后只执行一次teardown_class====
=====整个.py模块结束后只执行一次teardown_module,关闭浏览器=====

八、Pytest用例执行结果类型

Pytest用例执行完成后的用例状态,一般有:
passed:测试通过
failed:断言失败(例如:测试用例断言失败,或者 用例执行期间抛出了异常)
error:用例本身代码报错(例如:函数参数中调用的fixture不存在,或者 fixture里面有错误),error的测试用例数量越多,说明测试用例质量越差
xfail:预期失败,加了 @pytest.mark.xfail()
例如,下面代码返回xfail:

# 断言装饰器
@pytest.mark.xfail(raises=ZeroDivisionError)
def test_case1():
    1 / 0

代码有异常且和raised的异常类匹配,所以是xfail(是测试通过的一种,表示符合期望捕捉到的异常),不算failed。如果和raised的异常类不匹配,则是failed。

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值