Python之unittest框架的介绍及使用

unittest介绍

unittest是Python自带的一个单元测试框架, 它可以做单元测试, 也能用于编写和运行重复的测试工作.
它给自动化测试用例开发和执行提供了丰富的断言方法, 判断测试用例是否通过, 并最终生成测试结果.

TestCase编写

  • TestCase指的就是测试用例
  • 测试类必须继承unittest.TestCase
  • 测试方法名称命名必须以test开头
  • 测试方法的执行顺序有Case序号决定, 并非由代码顺序决定

一个简单的例子:

# 1. 导入unittest
import unittest


# 2. 创建类继承unittest.TestCase
class Test(unittest.TestCase):
    # 3. 创建测试用例方法, 方法要以test开头
    # 执行顺序是根据case序号来的, 并非代码的顺序
    def test_add_01(self):
        print(3+2)

    def test_add_02(self):
        print(10+5)

TestSuite与TextTestRunner

在上面提到, 测试用例的执行顺序默认是由case序号决定的,但也可以使用TestSuite控制用例的执行顺序。

  • TestSuite(测试套件)可以组织多个测试用例
  • TextTestRunner测试用例运行器
    • run()方法是测试用例的执行, 入参为suite测试套件

一个简单的例子

# 1. 导入unittest
import unittest


# 2. 创建类继承unittest.TestCase
class Test(unittest.TestCase):
    # 3. 创建测试用例方法, 方法要以test开头
    # 执行顺序是根据case序号来的, 并非代码的顺序
    def test_add_01(self):
        print(3+2)

    def test_add_02(self):
        print(10+5)

if __name__ == '__main__':
    suite = unittest.TestSuite()  # 实例化TestSuite
    suite.addTest(Test("test_add_02"))  # 添加测试用例
    suite.addTest(Test("test_add_01"))
    runner = unittest.TextTestRunner()  # 实例化TextTestRunner
    runner.run(suite)  # 传入suite并执行测试用例

但是要注意, 如果在Pychram中直接右键运行, 它是不会执行main下面的内容, 需要修改pychram的运行方式
在这里插入图片描述
然后重新运行, 就会执行main下面的内容了.

重点,通常测试用例都是多个的,因此测试用例可以存放到列表中一次性添加到测试套件。这里可以使用suite.addTests()

case_list = ['Test("test_add_02")', Test("test_add_01")]
suite.addTests(case_list)

TestLoader

如果有多个测试文件时, 可以使用TestLoader加载测试用例

  • unittest.defaultTestLoader, 使用discover()去加载测试用例
    • 找到指定目录下所有测试模块,并可递归查到子目录下的测试模块,只有匹配到文件名才能被加载
  • discover(start_dir, pattern=‘test*.py’, top_level_dir=None)
    • start_dir:要测试的模块名货测试用例目录
    • pattern=“test*.py”: 表示用例文件名的匹配原则。 此处匹配文件名以“test”开头的“.py”类型的文件,*表示任意字符
    • top_level_dir=None:测试模块的顶层目录, 如果没有顶层目录, 默认为None

一个小例子, 再目录下创建多个test开头的py文件, 并且写入测试方法
在这里插入图片描述
然后使用discover()方法读取测试用例并执行

import unittest
# dicsover方法查找用例
suite = unittest.defaultTestLoader.discover("unittest_test", "test*.py")
# 2.TextTestRunner运行用例
runer = unittest.TextTestRunner()
runer.run(suite)

TestFixture

setUp和tearDown

setUp()方法

  • 主要是用来初始化测试环境, 它在每条测试用例执行前都会调用

tearDown()方法

  • 主要作用是测试用例执行完毕后恢复测试环境, 即使出现异常也会调用此方法,每条用例执行结束后都会运行

一个简单的例子

import unittest

class Test(unittest.TestCase):
    def setUp(self) -> None:  # 调用setUp
        super().setUp()
        print("测试用例执行前操作")

    def test_add_01(self):
        print("num02")

    def test_add_02(self):
        print("num03")

    def tearDown(self) -> None:  # 调用tearDown
        super().tearDown()
        print("测试用例执行后操作")


# 返回结果
测试用例执行前操作
num02
测试用例执行后操作
测试用例执行前操作
num03
测试用例执行后操作

在上面的返回结果中可以明确的看出, 每条用例执行前都会先运行setUp,执行结束后都会运行tearDown

setUpClass和tearDownClass

setUpClass

  • 初始化测试环境且只会执行一次。在类中需要加上@classmethod

tearDownClass

  • 恢复测试环境且只会执行一次。在类中需要加上@classmethod
import unittest

class Test(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        super().setUpClass()
        print("测试前的操作")

    @classmethod
    def tearDownClass(cls) -> None:
        super().tearDownClass()
        print("测试后的操作")

    def test_add_01(self):
        print(3+2)

    def test_add_02(self):
        print(10+5)

# 返回结果
测试前的操作
15
5
测试后的操作

从返回结果可以看到setUpClass和tearDownClass都只是执行了一次,与setUp和tearDown的结果有很明显的区别。

注意,setUpClass和tearDownClass执行一次是针对当前的测试类而言的,如果当前的py文件有多个测试类, 那么它每个测试类都会执行一次。
如下:

# 1. 导入unittest
import unittest


# 2. 创建类继承unittest.TestCase
class Test(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        super().setUpClass()
        print("测试前的操作")

    @classmethod
    def tearDownClass(cls) -> None:
        super().tearDownClass()
        print("测试后的操作")

    # 3. 创建测试用例方法, 方法要以test开头
    # 执行顺序是根据case序号来的, 并非代码的顺序

    def test_add_01(self):
        print(3+2)

    def test_add_02(self):
        print(10+5)


class Test2(unittest.TestCase):

    @classmethod
    def setUpClass(cls) -> None:
        super().setUpClass()
        print("测试前的操作2")

    @classmethod
    def tearDownClass(cls) -> None:
        super().tearDownClass()
        print("测试后的操作2")

    def test_add_03(self):
        print(20)

    def test_add_04(self):
        print(40)

if __name__ == '__main__':
    suite = unittest.TestSuite()  # 实例化TestSuite
    suite.addTests([Test("test_add_02"), Test("test_add_01"), Test2("test_add_03"), Test2("test_add_04")])  # 添加测试用例
    runner = unittest.TextTestRunner()  # 实例化TextTestRunner
    runner.run(suite)  # 传入suite并执行测试用例

断言(重点)

常用的断言

方法检查
assertEqual(a, b)a == b
assertNotEqual(a, b)a != b
assertTrue(x)x的布尔值为真
assertFalse(x)x的布尔值为假
assertIn(a, b)a in b
assertNotIn(a, b)a not in b

assertEqual(a, b) 和 assertNotEqual(a, b)

# 1. 导入unittest
import unittest

# 2. 创建类继承unittest.TestCase
class Test(unittest.TestCase):
    def setUp(self) -> None:
        super().setUp()
        print("测试开始")

    def test_add_01(self):
        print("1 == 1")
        self.assertEqual(1, 1)  # 成功

    def test_add_02(self):
        print("1 == 2")
        self.assertEqual(1, 2)  # 失败

    def test_add_03(self):
        print("1 !=2 ")
        self.assertNotEqual(1, 2)  # 成功

    def test_add_04(self):
        print("1 != 1")
        self.assertNotEqual(1, 1)  # 失败

    def tearDown(self) -> None:
        super().tearDown()
        print("测试结束")

assertTrue(x)和assertFalse(x)

class Test(unittest.TestCase):

    @classmethod
    def setUpClass(cls) -> None:
        super().setUpClass()
        print("测试前的操作2")

    @classmethod
    def tearDownClass(cls) -> None:
        super().tearDownClass()
        print("测试后的操作2")

    def test_05(self):
        self.assertTrue(1 < 2)  # 成功

    def test_06(self):
        self.assertTrue(1 > 2)  # 失败

    def test_07(self):
        self.assertFalse(1 > 2)  # 成功

    def test_08(self):
        self.assertFalse(1 < 2)  # 失败

assertIn(a, b)和assertNotIn(a, b)

import unittest

class Test(unittest.TestCase):

    @classmethod
    def setUpClass(cls) -> None:
        super().setUpClass()
        print("测试前的操作2")

    @classmethod
    def tearDownClass(cls) -> None:
        super().tearDownClass()
        print("测试后的操作2")

    def test_09(self):
        self.assertIn("a", "abc")  # 成功

    def test_10(self):
        self.assertIn("a", "bcd")  # 失败

    def test_11(self):
        self.assertNotIn("a", "bcd")  # 成功

    def test_12(self):
        self.assertNotIn("a", "abc")  # 失败

测试报告

文件方式的测试报告

import unittest
# dicsover方法查找用例
suite = unittest.defaultTestLoader.discover("unittest_test", "test*.py")
# 打开文件对象
with open("test_report.txt", "a") as f:
    # TextTestRunner运行用例
    runer = unittest.TextTestRunner(stream=f, verbosity=2)  # verbosity=2 输出详细日志
    runer.run(suite)

HTML方式的测试报告

HTML报告需要导入HTMLTestRunner.py,这个文件原本只支持python2,python3需要修改部分代码才能使用。
然后我发现CSDN这里已经有人上传过这个资源了, 不过貌似要收费, 我这里也传一个网盘吧, 这是已经修改好支持python的, 直接使用就行。

链接:https://pan.baidu.com/s/171jiRp9lw8Gtrl140g0uJw 
提取码:64db

回到正题,HTMLTestRunner的用法其实和TextTestRunner的差不多, 代码如下:

import unittest
from lib.HTMLTestRunner import HTMLTestRunner
# dicsover方法查找用例
suite = unittest.defaultTestLoader.discover("unittest_test", "test*.py")

with open("test_report.html", "wb") as report:
    runner = HTMLTestRunner(stream=report, verbosity=2, title="HTML测试报告", description="这是练习的测试报告")
    runner.run(suite)

运行结束后在本地就会看到多了一个HTML文件,打开就能看到测试报告了
在这里插入图片描述

skip跳过用例

在遇到不想执行的测试用例时,可以使用skip方法

  • @unittest.skip(reason) :无条件跳过用例, reason是说明原因
  • @unittest.skipIf(condition, reason):condition为true时跳过用例
  • @ unittest.skipUnless(condition, reason):condition为False的时候跳过

实例代码:

# 1. 导入unittest
import unittest

class Test(unittest.TestCase):

    @classmethod
    def setUpClass(cls) -> None:
        super().setUpClass()
        print("测试前的操作2")

    @classmethod
    def tearDownClass(cls) -> None:
        super().tearDownClass()
        print("测试后的操作2")
        
    @unittest.skip("无条件跳过")
    def test_09(self):
        self.assertIn("a", "abc")
        
    @unittest.skipIf(2>1, "因为2>1所以跳过")
    def test_10(self):
        self.assertIn("a", "bcd")
        
    @unittest.skipUnless(1>2, "因为1>2为假,所以跳过")
    def test_11(self):
        self.assertNotIn("a", "bcd")

    def test_12(self):
        self.assertNotIn("a", "abc")

然后执行用例并生成测试报告

import unittest
from lib.HTMLTestRunner import HTMLTestRunner
# dicsover方法查找用例
suite = unittest.defaultTestLoader.discover("unittest_test", "test*.py")

with open("test_report.html", "wb") as report:
    runner = HTMLTestRunner(stream=report, verbosity=2, title="HTML测试报告", description="这是练习的测试报告")
    runner.run(suite)

测试报告,只剩下了一个测试用例了
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值