pytest自动化测试

单元测试介绍

单元测试: 在软件开发过程中,对软件的最小单位(函数、类等)进行正确性的检查测试(一般由开发人员完成)。是自动化测试的一部分。

 

常用框架

java中常用junit / testng,
python 中常用unittest / pytest

单元测试框架的作用:从项目中的多个文件中找到测试用例,然后按照特定的顺序、规则依次执行,生成结果后使用断言方式判断是否符合预期;最后生成测试报告。
 

pytest介绍

  1. python实现的单元测试框架,非常成熟,灵活易上手;
  2. 可以selenium/requests/appium结合实现web自动化、app自动化等;
  3. 可以跳过用例、重跑失败的用例;
  4. 可以结合allure-pytest插件实现美观的测试报告;
  5. 插件强大,结合pytest-html生成html格式的测试报告;结合pytest-xdist实现分布式执行测试用例;pytest-ordering 改变测试用例的执行顺序;结合pytest-rerunfailures重跑失败的用例。

以上pytest库及插件的安装,可以使用递归式安装:

# 1. 将所有的库名字放入requirements.txt中
# pytest
# pytest-html
# ...

# 2. 递归安装
pip install -r requirements.txt

# -U 表示更新

# 查看
pytest --version
pytest --help

 

默认的测试用例编写规则

pytest默认的测试用例规则如下:

  1. 测试目录 test_case;
  2. 测试模块test_xxx.py;
  3. 测试类 TestXxxx,且没有init方法;
  4. 测试方法(用例)test_xxx, 如test_001(self)
import pytest


# 模拟被测试函数单元
def func(a, b):
    return a ** b


# 测试类 以Test开头,不能有init
class TestLaufing:
    # 测试用例(方法),以test_开头
    def test_func(self):
        a, b = 2, 3
        c = 8

        assert c == func(a, b)
        print("test func 成功")

    def test_002(self):
        assert 1 == 2

    # 跳过如下测试用例
    @pytest.mark.skip
    def test_003(self):
        assert 1 == 1


if __name__ == '__main__':
    # 主函数方式执行
    # 执行所有的测试用例
    # 执行该模块即可
    pytest.main()

测试结果如下:
在这里插入图片描述
. 代表测试通过;
F 代表测试失败;
s 代表测试用例跳过;
E 代表有异常;

 

执行方式

测试用例的执行方法如下:

  1. 主函数形式
    创建run_pytest_main.py模块,名字随意,这里只是为了执行主函数,然后放入项目的根目录。内部执行主函数:
    在这里插入图片描述
# 导包
import pytest


if __name__ == '__main__':
    # 主函数方式执行
    # 执行web_app目录下的所有测试用例
    pytest.main(["-vs", "web_app"])

说明:
pytest.main() 执行所有的测试用例;
pytest.main([“-v”, “web_app”]) 执行该目录下的所有的测试用例;
pytest.main([“-v”, “./web_app/test_xxx.py”]) 执行该目录中指定模块的测试用例;
pytest.main([“-v”, “web_app/test_pytest_demo.py::TestWeb::test_func”]) 指定单个测试用例;

  1. 命令行形式
    切换到项目的根目录下:
    python -m pytest 执行项目中所有的测试用例;(注意测试模块等不能重名)
    python -m pytest -v app 只执行app目录中的测试用例;
    python -m pytest -v app/test_xxx.py 只执行app目录中指定模块的测试用例;
    python -m pytest -v app/test_xxx.py::TestApp::test_func 只执行app目录中指定模块的单个测试用例;
  2. 配置文件形式(pytest.ini)
    稍后介绍

 
参数说明:
-v 输出详细信息;
-s 输出print打印的信息;
-vs 可以结合使用;
-n 多线程执行(必须安装pytest-xdist 插件);
pytest.main([‘-vs’, ‘app’, ‘-n=2’]) ;
pytest -vs app -n 2 ;
相当于有个两个线程的线程池,一次跑两个用例(两个线程)。
–maxfail=2 两个用例失败后退出测试;
pytest.main([“-vs”, “web_app”, “-n=2”, “–maxfail=2”])
-x 有一个测试用例失败即退出测试;
-q 删除更少的信息;
–reruns 5 失败用例的重跑(num次);需要安装pytest-rerunfailures
-k 匹配测试用例的部分字符串;匹配到则执行用例;
如 -k “_laufing”

 

测试用例执行顺序

unittest: 按照ASCII码执行;
pytest: 按照(测试类中的用例)从上到下的顺序;
在这里插入图片描述

要改变执行顺序:

  1. 安装插件pytest-ordering
  2. @pytest.mark.run(order=1) 装饰测试用例
# 测试类 以Test开头,不能有init
class TestWeb:
    # 测试用例(方法),以test_开头
    def test_func(self):
        time.sleep(3)
        a, b = 2, 3
        c = 8

        assert c == func(a, b)
        print("test func 成功")

    def test_002(self):
        time.sleep(3)
        assert 1 == 2

    # 跳过如下测试用例
    @pytest.mark.skip
    def test_003(self):
        assert 1 == 1

    @pytest.mark.run(order=1)
    def test_004(self):
        time.sleep(3)
        assert 1 == 2

执行结果:
在这里插入图片描述
 

pytest.ini配置文件

它是pytest的核心配置文件,放在项目的根目录下;
pytest执行测试(不管主函数形式还是命令行形式)前,必先读取配置文件,可以改变其默认行为;
配置文件编码格式必须是ANSI,可以使用txt修改编码格式;

配置如下:
模块名、类名、函数名可以不按照默认的规则,实现随意命名。
在这里插入图片描述

测试用例分组执行

使用mark标记,可以将不同模块的用例标记为一组,然后分组执行。

如下:

  1. app目录> test_app_module.py:
import pytest


# 模拟被测试函数单元
def func(a, b):
    return a ** b


# 配置文件可以改变默认的行为 
class TestAppClass:
    # 测试用例(方法),以test_开头
    def test_func(self):
        a, b = 2, 3
        c = 8

        assert c == func(a, b)
        print("test func 成功")

    @pytest.mark.user1  # 标记为user1组
    def test_app_002(self):
        print("app_002: user1组")
        assert 1 == 2

    # 跳过如下测试用例
    @pytest.mark.skip
    def test_003(self):
        assert 1 == 1

  1. web_app目录>test_web_app_module.py
import pytest


# 模拟被测试函数单元
def func(a, b):
    return a ** b


# 测试类 以Test开头,不能有init
class TestWebAppClass:
    # 测试用例(方法),以test_开头
    def test_func(self):
        a, b = 2, 3
        c = 8
        assert c == func(a, b)
        print("test func 成功")

    @pytest.mark.user1  # 标记为user1组
    def test_web_app_002(self):
        print("web app: user1组")
        assert 1 == 2

    # 跳过如下测试用例
    @pytest.mark.skip
    def test_003(self):
        assert 1 == 1

  1. pytest.ini配置文件(项目根目录下且ANSI编码)
[pytest]
addopts = -vs
testpaths = ./
python_files = test_*.py
python_classes = Test*
python_functions = test
# 从以上选择到的用例中再选择分组
markers =
    user1: user1 group
    user2: user2 group

使用txt记事本打开,另存为修改编码方式

  1. 执行user1分组的测试用例
pytest -m 'user1'

# 执行多个分组
pytest -m 'user1 or user2'

在这里插入图片描述

跳过测试用例

# 无条件跳过
@pytest.mark.skip(reason="xxx")
def test_002(self):
	assert 1 == 2

# 有条件的跳过
num = 6
@pytest.mark.skipif(num >= 5, reason="xxx")
def test_002(self):
	assert 1 == 2

 

生成html测试报告(不常用)

  1. 安装pytest-html
  2. 添加–html参数
# 主函数形式
pytest.main(['-vs', '--html=./report.html', 'test_case'])
# 命令行
pytest -vs test_case --html ./report.html

# 配置文件
addopts = -vs --html ./report.html

 

测试案例

  • 项目部分代码
    在这里插入图片描述
# 定义功能函数
def get_max_area(arr: list):
    if len(arr) < 2:
        return 0

    # 降序排列
    descend_list = sorted(arr, reverse=True)

    print("descend list:", descend_list)

    # 最大面积
    result = 0
    # 计算索引差值序列
    for i in range(1, len(arr)):
        temp = i * descend_list[i]
        if temp > result:
            result = temp

    return result
  • 编写测试用例;
# 项目根目录下创建test目录,并编写test_xxx.py
import pytest
from algorithm.hangtian import get_max_area


class TestAlgorithm:
    def test_get_max_area(self):
        case = [20, 19, 14, 14, 12, 9, 8, 6, 3, 2]
        assert 48  == get_max_area(case)
        return

    def test_002(self):
        assert 1
        return
  • 开始测试,并生成html格式的测试报告
# 项目根目录下 编写main_test.py
import pytest


if __name__ == '__main__':
	# -v 冗余信息,详细信息
	# -s 输出print的信息
	# ./test 从test目录中找到所有的测试用例
	# -n 多线程执行测试用例  需要安装pytest-xdist插件
	# --reruns 重跑失败的用例  需要安装pytest-rerunfailures 插件
	# --maxfail 最多失败三个测试用例,则停止测试
	# --html 生成html格式的测试报告  需要安装pytest-html插件
    pytest.main(["-vs", "./test", "-n=2", "--reruns=5", "--maxfail=3", "--html=./lauf.html"])

在这里插入图片描述
 

单元测试覆盖率

  • 软件系统中的函数被测试的语句行数 / 总语句行数
  • 使用pytest-cov 插件,统计覆盖率
# 统计以上单元测试案例的 测试覆盖率
# 只需增加 --cov=要覆盖的目录 --cov-report=html
pytest.main(["-vs", "./test", "-n=2", "--reruns=5", "--maxfail=3", "--html=./lauf.html", "--cov=./algorithm", "--cov-report=html"])

在这里插入图片描述

在hangtian.py模块中的函数有11行声明代码,仅仅测试了10行(第一部分的if分支情况没有测试);对get_max_area函数的所有的可能分支,均编写测试用例,再次测试。
在这里插入图片描述
测试用例:

class TestAlgorithm:
    def test_get_max_area(self):
        case = [20, 19, 14, 14, 12, 9, 8, 6, 3, 2]
        assert 48  == get_max_area(case)
        return

    def test_get_max_area2(self):
        assert 0 == get_max_area([])

 
 
下一篇:测试用例的前后置操作

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

laufing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值