UnitTest2

TestLoader(测试加载)

TestLoader(测试加载),作用和TestSuite的作用一样的,对Testsuite功能的补充,用来组装测试用例的

比如:如果TestCase的代码文件有很多,(10,20,30)

-使用步骤
1.导包
2.实例化测试加载对象并添加用例 ---> 得到的是 suite 对象
3.实例化 运行对象
4.运行对象执行套件对象
  • 代码实现
在一个项目中,TestCase测试用例代码,一般放在一个单独的目录当中(case
  • 测试用例1
"""
代码的目的:学习TestCase(测试用例)模块的书写方法
"""
# 导包
import unittest


# 自定义测试类,需要继承 unittest 模块中的 TestCase 类即可
class TestDemo1(unittest.TestCase):
    # 书写测试方法,即用例代码。目前没有真正的用例代码,使用print代替
    # 书写要求:测试方法必须以 test_ 开头(本质是以 test 开头)
    def test_method1(self):
        print('测试方法1-1')

    def test_method2(self):
        print('测试方法1-2')
# 执行测试方法
# 将光标放在 类名的后边 运行
# 将光变放在方法名的后边执行
  • 测试用例2
"""
代码的目的:学习TestCase(测试用例)模块的书写方法
"""
# 导包
import unittest


# 自定义测试类,需要继承 unittest 模块中的 TestCase 类即可
class TestDemo2(unittest.TestCase):
    # 书写测试方法,即用例代码。目前没有真正的用例代码,使用print代替
    # 书写要求:测试方法必须以 test_ 开头(本质是以 test 开头)
    def test_method1(self):
        print('测试方法2-1')

    def test_method2(self):
        print('测试方法2-2')
# 执行测试方法
# 将光标放在 类名的后边 运行
# 将光变放在方法名的后边执行

测试用例3

"""
代码的目的:学习TestCase(测试用例)模块的书写方法
"""
# 导包
import unittest


# 自定义测试类,需要继承 unittest 模块中的 TestCase 类即可
class TestDemo3(unittest.TestCase):
    # 书写测试方法,即用例代码。目前没有真正的用例代码,使用print代替
    # 书写要求:测试方法必须以 test_ 开头(本质是以 test 开头)
    def test_method1(self):
        print('测试方法3-1')

    def test_method2(self):
        print('测试方法3-2')
# 执行测试方法
# 将光标放在 类名的后边 运行
# 将光变放在方法名的后边执行
  • TestLoader
# 1.导包
import unittest

# 2.实例化测试加载对象
# unittest.TestLoader().discover('用例所在的路径','用例的代码文件名')
# 用例所在的路径,建议使用相对路径,用例的代码文件名可使用 *(任意多个任意字符) 通配符
suite = unittest.TestLoader().discover('C:/Users/fighting!/Desktop/py_leaning/UnitTest/case', '*.py')   # 查找测试用例

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

# 执行
runner.run(suite)

Fixture(测试夹具)

Fixture(测试夹具)是一种代码结构
在某些特定的情况下 会自动执行

方法级别

在每个测试方法(用例代码)执行前后都会自动调用的结构
# 方法执行之前
def setUp(self):
    每个测试方法执行之前都会执行
    pass

# 方法执行之后
def tearDown(self):
    每个测试方法执行之后都会执行
    pass

类级别的【掌握】

在每个测试类中所有方法执行前后 都会自动调用的结构(在整个类中 执行之前执行之后各一次)
# 类级别的方法,是一个 类方法
# 类中所有方法之前
@classmethod
def setUpClass(cls):
    pass

# 类中所有方法之后
def tearDownClass(cls):
    pass

模块级别【了解】

模块:代码文件
在每个代码文件执行前后执行的代码结构
# 模块级别的需要写在类的外边,直接定义函数即可
# 代码文件之前
def setUpModle():
    pass

# 代码文件之后
def tearDownModule():
    pass
方法级别的和类级别的 前后的方法,不需要同时出现,根据用例代码的需要自行的选择使用

案例

1.打开浏览器(整个测试过程中打开一次浏览器) 类级别
2.输入网址(每个测试方法都需要一次) 方法级别
3.输入用户名密码验证码点击登录(不同的测试数据) 测试方法
3.输入用户名密码验证码点击登录(不同的测试数据) 测试方法
3.输入用户名密码验证码点击登录(不同的测试数据) 测试方法
3.输入用户名密码验证码点击登录(不同的测试数据) 测试方法
3.输入用户名密码验证码点击登录(不同的测试数据) 测试方法
4.关闭当前页面 (每个测试方法都需要一次)方法级别
5.关闭浏览器(整个测试过程中关闭一次浏览器) 类级别
-----
1.打开浏览器(整个测试过程中打开一次浏览器) 类级别
2.输入网址(每个测试方法都需要一次) 方法级别
3.输入用户名密码验证码点击登录(不同的测试数据) 测试方法
4.关闭当前页面 (每个测试方法都需要一次)方法级别
2.输入网址(每个测试方法都需要一次) 方法级别
3.输入用户名密码验证码点击登录(不同的测试数据) 测试方法
4.关闭当前页面 (每个测试方法都需要一次)方法级别
2.输入网址(每个测试方法都需要一次) 方法级别
3.输入用户名密码验证码点击登录(不同的测试数据) 测试方法
4.关闭当前页面 (每个测试方法都需要一次)方法级别
5.关闭浏览器(整个测试过程中关闭一次浏览器) 类级别
import unittest


class TestLogin(unittest.TestCase):
    def setUp(self) -> None:
        """每个测试方法执行之前都会先调用的方法"""
        print('输入网址..........')

    def tearDown(self) -> None:
        """每个测试方法执行之后都会调用的方法"""
        print('关闭当前页面。。。。。。。')

    @classmethod
    def setUpClass(cls) -> None:
        print('1.-----------打开浏览器')

    @classmethod
    def tearDownClass(cls) -> None:
        print('5.-----------关闭浏览器')

    def test_1(self):
        print('输入用户名密码验证码,点击登录 1')

    def test_2(self):
        print('输入用户名密码验证码,点击登录 2')
  • 运行结果
1.-----------打开浏览器
输入网址..........
输入用户名密码验证码,点击登录 1
关闭当前页面。。。。。。。
输入网址..........
输入用户名密码验证码,点击登录 2
关闭当前页面。。。。。。。
5.-----------关闭浏览器

断言

让程序代替人工自动判断预期结果和实际结果是否相等。

断言结果:Ture(用力通过)  False(抛出异常)
在unitest中使用断言,都需要通过self.断言方法  来试验

assertEqual

assertEqual(预期结果,实际结果)  # 判断预期结果和实际结果是否相等
1.如果相等,用例通过
2.如果不相等,用例不通过,抛出异常

assertIn

assertIn(预期结果,实际结果)   # 判断预期结果是否包含在实际结果中
1.包含:用例通过
2.不包含:用例不通过,抛出异常

asserIn('admin','admin')  # 包含
asserIn('admin','aaaaaaaadmin')  # 包含
asserIn('admin','addddddmin')  # 不是包含
import unittest

from P192_work.practice4.practice4 import login


class TestLogin(unittest.TestCase):

    def test_login(self):
        self.assertEqual('登陆成功!', login('admin', '123456'))

    def test_username(self):
        self.assertEqual('登陆失败!', login('root', '123456'))

    def test_password(self):
        self.assertEqual('登陆失败!', login('root', '123123'))

    def test_username_password(self):
        # self.assertEqual('登陆失败!', login('aaa', '123123'))
        self.assertIn('失败', login('aaa', '123123'))

参数化

参数化  在测试方法中,使用 变量 来代替具体的测试数据,然后使用传参的方法将测试数据传递给方法的变量
好处:相似的代码不需要多次书写

工作中的场景:
1.测试的数据一般放在json文件中
2.使用代码读取json文件,提取我们想要的数据 ---->  [(),()] or [[],[]]

安装插件

unittest 框架本身是不支持 参数化,想要使用参数化,需要安装插件来完成

- 联网安装
pip install parameterized

---------
pip 是 Python中包(插件)的管理工具,使用这个工具下载安装插件

验证

pip list 查看是否安装成功

新建一个 python 代码文件,导包查看

参数化代码

1.导包unittest/pa
2.定义测试类
3.书写测试方法(用到的测试数据使用变量代替)
4.组织测试数据并传参
# 1.导包unittest/pa
import unittest

from P192_work.practice4.practice4 import login
from parameterized import parameterized

# 组织测试数据并传参 [(),()]
data = [('admin', '123456', '登陆成功'), ('root', '123456', '登陆失败!'), ('root', '123123', '登陆失败!'),
        ('aaa', '123123', '登陆失败!')]


# 2.定义测试类
class TestLogin(unittest.TestCase):    # 必须在这里运行

    # 3.书写测试方法(用到的测试数据使用变量代替)
    @parameterized.expand(data)   # 4.组织测试数据并传参(装饰器 @)
    def test_login(self, username, password, excpect):
        self.assertEqual(excpect, login(username, password))

参数化2

[
  {
    "desc": "正确的用户名和密码",
    "username": "admin",
    "password": "123456",
    "expect": "登陆成功"
  }
]
  • json文件
[
  {
    "desc": "正确的用户名和密码",
    "username": "admin",
    "password": "123456",
    "expect": "登陆成功"
  },
  {
    "desc": "错误的的用户名和密码",
    "username": "root",
    "password": "123456",
    "expect": "登陆失败"
  }
]
  • 测试代码
import json
import unittest
from parameterized import parameterized

from P192_work.practice4.practice4 import login


def build_data():
    with open('data.json', encoding='utf-8') as f:
        result = json.load(f)  # [{},{}]
        data1 = []
        for i in result:  # i {}
            data1.append((i.get('username'), i.get('password'), i.get('expect')))

    return data1


# 定义测试类
class TestLogin(unittest.TestCase):
    @parameterized.expand(build_data())
    def test_login(self, username, password, expect):
        self.assertEqual(expect, login(username, password))

跳过

对于一些未完成的或者不满足测试条件的测试函数和测试类,不想执行,可以使用跳过
使用方法,装饰器完成
代码书写在TestCase文件中
  • 代码案例
# 直接将测试函数标记成跳过
@unittest.skip('跳过的原因')
# 根据条件判断测试函数是否跳过,判断条件是否成立, 跳过
@unittest.skipIF(判断条件,'跳过原因')

- 代码

import unittest

# version = 30
version = 29


class TestDemo(unittest.TestCase):
    def test_1(self):
        print('测试方法1')

    @unittest.skip('没有原因,就是不想执行')
    def test_2(self):
        print('测试方法2')

    @unittest.skipIf(version >= 30, '版本号大于等于30,不用测试')
    def test_3(self):
        print('测试方法3')

    def test_4(self):
        print('测试方法4')

        
        
- 结果
Ran 4 tests in 0.003s

测试方法1

Skipped: 没有原因,就是不想执行
测试方法3
测试方法4

Process finished with exit code 0

测试报告

自带的测试报告

只有单独运行 TestCase的代码,才会生成测试报告

生成第三方的测试报告

1.获取第三方的测试运行类,将其放在代码的目录当中
2.导包
3.使用 套件对象, 加载对象 去添加用例方法
4.实例化 使用第三方的运行对象 并运行 套件对象
# 1.获取第三方的测试运行类,将其放在代码的目录当中

# 2.导包
import unittest
from HTMLTestRunner import HTMLTestRunner

# 3.使用 套件对象, 加载对象 去添加用例方法
suite = unittest.defaultTestLoader.discover('.', 'py_pa2.py')
# 4.实例化 使用第三方的运行对象 并运行 套件对象

# stream=sys.stdout, 测试报告的文件对象(open),要使用 wb 打开
# verbosity=1, 可选,报告的详细程度,默认 1 简略,2 详细
# title=None, 必填,测试报告的标题
# description=None , 可选, 描述信息, Python的版本, pycharm版本
file = 'report1.html'  # 报告的后缀是.html
with open(file, 'wb') as f:
    # runner = HTMLTestRunner(f)
    runner = HTMLTestRunner(f, 2, '测试报告', 'python 3.8')

    # 运行对象执行套件,要写在缩进中
    runner.run(suite)
1.组织用例文件(TestCase里边),书写参数化,书写断言,书写Fixture, 书写 跳过,如果单个测试文件,直接运行, 得到测试报告, 如果多个测试文件, 需要组装 运行,生成测试报告

2.使用 套件对象组装,或者使用 加载对象组装

3.运行对象
3.1 运行对象 = 第三方的运行类(文件对象)(打开文件需要使用wb方式)
3.2 运行对象.run(套件对象)
  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值