IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> python测试与调式基础模块 -> 正文阅读

[开发测试]python测试与调式基础模块

1 unittest

单元测试

1.1 组成部分
TestCase: 测试用例,框架的组成部分,真正用来书写用例代码
TestSuite: 测试套件,管理组装多个TestCase
TestRunner: 测试执行,测试运行,执行TestSuite
TestLoader: 测试加载,对TestSuit的功能补充
Fixture: 测试夹具,书写在TestCase代码中,是一个代码结构,在每个方法执行前后都执行的内容
1.2 TestCase
import unittest


class TestDemo(unittest.TestCase):
    """测试类,继承TestCase
    测试方法:必须以 test_ 开头
    
    运行:鼠标放在相应的方法上可指定执行相应的方法,放在类上执行所有方法
    """

    def test_print(self):
        print("测试1")

    def test_print2(self):
        print("测试2")
1.3 TestSuite、TestRunner
import unittest
from learn_unitest.t1 import TestDemo
from learn_unitest.t2 import TestDemo2

# 使用套件对象添加用例方法
suite = unittest.TestSuite()
suite.addTest(TestDemo('test_print'))  # 添加指定方法
# 添加类中所有方法: suite.addTest(unittest.makeSuite(类名))
suite.addTest(unittest.makeSuite(TestDemo2))

# 实例化运行对象
runner = unittest.TextTestRunner()

# 执行
runner.run(suite)

# 运行结果中的 "." 表示用例通过,F表示用例不通过,E用例代码有问题
1.4 TestLoader
import unittest

# 实例化加载对象并添加用例
# 发现TestCase: discover("用例所在的路径", "用例的代码文件名") ,可以使用通配符*
loader = unittest.TestLoader().discover("./", "t*.py")
# loader = unittest.defaultTestLoader.discover("./", "t*.py")

# 实例化运行对象
unittest.TextTestRunner().run(loader)
1.5 Fixture
# 每个方法执行之前 setUp , 方法执行之后 tearDown
# 每个测试用例类所有方法执行之前类方法 setUpClass,所有方法执行之后 tearDownClass
# 每个代码文件(模块)执行之前定义函数setup_module,执行之后 teardown_module
# 以上方法均无返回值


import unittest


def setup_module():
    print("+++++模块执行之前+++++")


def teardown_module():
    print("+++++模块执行之后+++++")


class TestFixture(unittest.TestCase):

    def setUp(self):
        print("每个方法执行之前")

    def tearDown(self) -> None:
        print("每个方法执行之后")

    @classmethod
    def setUpClass(cls):
        print("类中方法执行之前")

    @classmethod
    def tearDownClass(cls) -> None:
        print("类中方法执行之后")

    def test_print(self):
        print("测试方案1")

    def test_print2(self):
        print("测试方案2")
1.6 断言
# 判断表达式 assert
# 判断结果是否相等  self.assertEqual(预期结果,实际结果)   
# 判断预期结果是否包含在实际结果中  self.assertIn(预期结果, 实际结果)

...
    def test_print(self):
        # 通过
        self.assertIn("abc", "abcdef")
1.7 参数化
# pip install parameterized

import unittest
from parameterized import parameterized

data = [
    (1, 2),
    (1, 1),
    (2, "2"),
    ([1], [1])
]


class TestDemo(unittest.TestCase):

    # 传参
    @parameterized.expand(data)
    def test_print(self, a, b):
        self.assertEqual(a, b)
1.8 跳过
# @unittest.skip("跳过的原因")
# @unittest.skipIf(判断条件, "原因")


import unittest


class TestSkip(unittest.TestCase):

    @unittest.skipIf(1 == 1, "测试跳过")
    def test_sk(self):
        print("测试skip")

    def test_sk2(self):
        print("测试skip2")
1.9 测试报告
# TestCase自带测试报告,左下角框顶右侧的"export test results"导出

# 生成第三方测试报告HTMLTestRunner
# pip install html-testRunner

import unittest
import HtmlTestRunner

# 实例化加载对象并添加用例
# 发现TestCase: discover("用例所在的路径", "用例的代码文件名") ,可以使用通配符*
loader = unittest.TestLoader().discover("./", "t_fix*.py")

# 实例化运行对象
runner = HtmlTestRunner.HTMLTestRunner(output="static/")
runner.run(loader)
1.10 mock
# 使用模拟对象来替换对象
import unittest
from unittest import mock

from t1 import A

# print(A().f())  # 1   


class TestA(unittest.TestCase):

    @mock.patch.object(A, "f")
    def test_f(self, f):
        f.return_value = 2
        print(f())

        

# patch替换值
from unittest.mock import patch
import t1  # t1.f = 1

patch("t1.f", None).start()

print(t1.f)

2 pytest

2.1 测试用例
# 模块名必须以test_开头或_test结尾
# 测试类必须以Test开头,且不能有init方法
# 测试方法必须以test开头

pip install 包名
pytest
pytest-xdist  # 多线程执行
pytest-html   # html格式报告
pytest-ordering  # 改边测试用例的执行顺序
pytest-rerunfailures   # 用例失败后重跑
allure-pytest   # 生成美观的测试报告
2.2 运行测试用例
# 主函数模式运行
pytest.main()  # 运行所有
pytest.main(['-vs', '文件名/目录名', '-n=3'])  # 指定模块或目录运行
pytest.main(['-vs', '目录名.文件名::函数名', '--reruns=2'])  # 指定一般函数运行
pytest.main(['文件名::类名::函数名'])  # 指定类中的函数名

# 参数
-s 输出调试信息包括print
-v 显示更详细的信息
-n 多线程执行   # 要先安装pytest-xdist
--reruns=2   # 失败后重复执行
-x  # 只要有一个用例报错,就停止
--maxfail=2  # 出现两个用例失败就停止
--html 路径  # 生成html报告   

# 命令行运行
pytest  # 运行所有

# 指定顺序执行,在方法上装饰,数字越小越先执行
@pytest.mark.run(order=5)

# 通过读取pytest.ini文件来执行
# 文件放在项目根目录,注意编码

# 指定自定义类型运行
# 先使用 @pytest.mark.类型名 给相关方法加上类型标记,比如@pytest.mark.usermanager
# 在pytest.ini中指定参数运行 -m 类型名
# 在pytest.ini中定义markers标记自定义的类型

# 跳过
@pytest.mark.skip("原因")
@pytest.mark.skipif(条件, reason="原因")

pytest.ini格式

[pytest]
# 最后文件删除掉中文注释
# 命令行参数,空格分割,-m指定执行的标记类型,--html生成报告指定位置
addopts = -vs -m="smoke or usermanager" --html ./static/a.html
# 指定测试用例位置
testpaths = ./
# 测试模块文件名称
python_files = test*.py
# 测试类名
python_classes = Test*
# 测试函数名
python_functions = test
# 定义标记
markers =
    smoke: 冒烟用例
    usermanage: 用户管理

test_01.py

import pytest


@pytest.mark.run(order=4)
def test_01():
    print("测试 test_01")


class TestO1:

    @pytest.mark.run(order=5)
    @pytest.mark.usermanager
    def test_01(self):
        print("测试Test01中的test_01")

    @pytest.mark.run(order=3)
    @pytest.mark.smoke
    @pytest.mark.skipif(False, reason="哈哈哈")
    def test_02(self):
        print("测试Test01中的test_02")
2.3 前后置夹具
class TestO2:

    def test_01(self):
        print("测试Test02中的test_01")

    def test_02(self):
        print("测试Test02中的test_02")

    def setup(self):
        print("每个测试用例执行之前")

    def teardown(self):
        print("每个测试用例执行之后")

    def setup_class(self):
        print("类执行初始化工作, 如开启连接等")

    def teardown_class(self):
        print("类关闭资源的操作")
2.4 @pytest.fixture实现部分用例前后置
# @pytest.fixture(scope='', params='', autouse='', ids='', name='')
# scope表示被@pytest.fixture标记的方法作用域,function(默认), class, module, package/session
# params: 参数化(支持列表,元组,字典元组,字典列表)
# autouse: 自动使用,默认False
# name: 别名


import pytest


@pytest.fixture(scope='function', params=['a', 'b', 'c'])
def my_fixture(request):
    print("前置")
    yield request.param
    print("后置")


class TestO2:

    def test_01(self):
        print("测试Test02中的test_01")

    def test_02(self, my_fixture):
        print("测试Test02中的test_02")
        print(f"==========={my_fixture}==")
2.5 @pytest.mark.parametrize参数化
# @pytest.mark.parametrize(args_name, args_value)
# args_name 参数名
# args_value 参数值,有多少组值就会执行多少次

import pytest


class Test03:

    @pytest.mark.parametrize('a, b', [['a', 'a'], ['b', 'b'], ['c', 'c']])
    def test_01(self, a, b):
        print(f"---{a}--{b}---")
2.6 yaml格式
# map
info:
  name: a
  age: b
# info: {name: a, age: b}
  
# list[map]
infos:
  - a: a
  - b: b
2.7 python读取yaml成字典

pip install pyyaml

import yaml


def read_yaml(path):
    with open(path) as f:
        value = yaml.load(f, Loader=yaml.FullLoader)
    print(value)


if __name__ == '__main__':
    read_yaml("./test_yaml.yaml")
2.8 结合yaml
# @pytest.mark.parametrize(args_name, args_value) 中的args_value根据yaml来获取值

3 pdb

python自带交互式调试模块,无IDE的时候方便调试,比如linux环境下调试

# 使用pdb模块单步运行文件的每一行程序,m表示module
python -m pdb 文件名

# 中断进入调试器,插入以下代码,执行 python 文件名,会停到插入行
import pdb; pdb.set_trace()

# n或者enter运行到下一行

# s 进入函数,不会执行第一行

# c 继续执行,直到下一个断点,pdb.set_trace()设置断点

# l 列出当前文件的源代码,箭头指向正要运行的那一行

# a 输出当前函数的参数列表

class A:
    def show(self):
        print(dir(self))


if __name__ == '__main__':
    import pdb
    pdb.set_trace()
    a = A()
    setattr(a, "a", 1)
    if hasattr(a, "show"):
        show = getattr(a, "show")
        show()
    pdb.set_trace()
    if hasattr(a, "a"):
        print(getattr(a, "a"))

4 responses

4.1 模拟请求预设响应
import unittest
import json
import re

import requests
import responses


# 使用responses.RequestsMock模拟后,所有发到匹配规则上的url,都将不再真是发送,而是改为使用结果直接返回

class TestA(unittest.TestCase):

    def test_api_post_haveibeenpwned_not_reachable(self):
        c = requests
        data = '{"aaaa": "11111"}'

        with responses.RequestsMock() as rsps:
            rsps.add(
                responses.POST,
                re.compile(r"^(http://127.0.0.1:8765/a/).*"),
                json=data)
            # 不会真正发送了
            mock_response = json.loads(c.post("http://127.0.0.1:8765/a/").text)
        print(mock_response)   # data
  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章           查看所有文章
加:2022-09-24 21:24:11  更:2022-09-24 21:25:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/17 22:34:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码