Python单元测试--unittest测试框架

1. 单元测试

单元测试是对功能/代码的最小单元进行测试

最小单元就是函数或类中的方法

举个栗子,对一个函数进行测试

# 被测函数,被测单元,被测功能
def add(a,b):
    return a + b
# a=1,b=1,expected = 2
# 把自动代测试用例放到一个函数中
def test_demo():
    # 测试用例
    actual = add(1,1)
    expected = 2
    if expected == actual:
        print('测试用例通过')
    else:
        print('测试用例失败')
test_demo()

 运行结果:

测试用例通过

不管测试的是函数,类,还是接口,都是把其放到一个函数里,作为被测内容

在python中进行测试,判断测试结果不会用if,而是用断言assert去判断

# 被测函数,被测单元,被测功能
def add(a,b):
    return a + b
# a=1,b=1,expected = 2
# 把自动代测试用例放到一个函数中
def test_demo():
    # 测试用例
    actual = add(1,2)
    expected = 2
    # if expected == actual:
    #     print('测试用例通过')
    # else:
    #     print('测试用例失败')
    # 用assert代替if判断
    assert expected == actual
test_demo()

运行结果:(预期结果与实际结果一致时不会报错)

 

# 被测函数,被测单元,被测功能
def add(a,b):
    return a + b
# 把自动代测试用例放到一个函数中
def test_demo():
    # 测试用例
    actual = add(1,3)
    expected = 2
    assert expected == actual
test_demo()

运行结果:(预期结果与实际结果不一致时会报错)

总结:当使用assert断言,如果测试通过,程序正常执行。如果测试不通过,报出AssertionError

assert失败,本质上就是一个异常,异常类型AssertionError

当我们没有使用单元测试框架之前,我们确实可以做自动化测试

1、首先要写测试用例函数,手工去调用测试函数

2、当用例失败之后,需要手工去加try...,失败一个加一个,过程太麻烦了

3、怎么收集测试用例,放到一个统一的模块

4、还要手工生成测试报告

这个过程真的是好麻烦,手工处理太慢,所以我们要学习单元测试框架,来简化工作流程,uinttest可以帮我们收集测试用例,运行用例,生成测试的报告,下面就来介绍一下单元测试框架

2. assert介绍

断言:判断测试用例的结果是否成功

assertEqual()断言是否相等,这个用的比较多

assertTrue()断言是否为真,这个是万能的,只要条件为真即可

assertIn()断言是否包含

assert有好多种方法,不用全都记住,只要记住assertEqual(),assertTrue()的用法即可

import unittest


class TestDemo(unittest.TestCase):
    def test_demo_1(self):
        self.assertEqual(1 + 1, 2)

    def test_demo_2(self):
        self.assertTrue(1 + 1 == 2)

    def test_demo_3(self):
        self.assertIn('1', '123')

 运行结果:

3. 单元测试框架unittest

单元测试框架本质是提供一系列工具的集合,一套解决方案,直接拿来使用,代替手工处理的步骤

unittest和pytest都是单元测试框架,unittest是python内置的,不需要安装,而pytest 是第三方库,需要安装。两个功能是一样的,用法差别不大,pytest相对来说更强大,之后我会介绍

3.1 unittest的特点与作用

unittest的特点:1.学习便利,2.学习成本高,需要遵守框架的规则

unittest的作用:1.收集用例,2.处理断言,3.测试报告

3. 2 unittest的几个概念

test case:测试用例

test suite:测试套件/测试集

test loader:测试加载(作用是加载测试用例)

test runner:运行器/执行器

fixture:夹具(作用是前置准备和后置清理)

3.2.1 test case

unittest的用法:

1.继承unittest.TestCase,编写一个test_开头的函数作为测试用例

注意:不是test开头的函数,unittest是不会去运行的,前面没有播放键

2.使用unittest运行用例,也就是点击播放键,一定要是unittest开头的(注意的是点击单条用例前的播放按钮,只运行这一条用例,点击类名前的播放按钮运行的是整个类下的测试用例)

一开始,我的怎么运行都是默认python的运行方式,不显示unittest开头的运行方式,如何去修改呢,如下操作步骤:

第一步:点击File->setting->搜索unittest,然后设置Default test runner,选择unittests

第二步:点击Run->Run...->选择Edit Configurations...(或者直接点击运行下拉框,选择Edit Configurations...)然后查看一下有没有Python tests,有这个通常就没问题,如果没有,把Python这个下的东西都删除,然后关闭pycharm,重新打开pycharm

 

第三步:最后重新启动pychram,如果打开还是不行,那就手工添加一下,如下图

 3. 使用self.assertEqual(expected,actual)对比结

import unittest  # 导入unittest


def login(username=None, password=None):
    if username is None or password is None:
        return {"code": "400", "msg": "用户名或密码为空"}
    if username == 'yuz' and password == '123':
        return {"code": "200", "msg": "登录成功"}
    return {"code": "300", "msg": "用户名或密码错误"}


# 类遵守规则:必须要继承unittest.TestCase
class TestLogin(unittest.TestCase):
    # 测试用例方法
    # 成功用例
    def test_login_1(self):
        username = 'li'
        password = '123'
        expected = {"code": "300", "msg": "用户名或密码错误"}
        actual = login(username, password)
        assert expected == actual
    # 失败用例
    def test_login_2(self):
        username = 'yuz'
        password = '123'
        expected = {"code": "300", "msg": "用户名或密码错误"}
        actual = login(username, password)
        assert expected == actual

运行结果:

使用self.assertEqual(expected,actual)运行结果可以看到的更详细

 3.2.2 收集用例及运行用例

现在我们项目下新建一个包tests,来管理所有的测试用例,test_demo.py和 test_unittest.py下放的是所有的用例,然后再新建一个run.py来收集用例和运行用例

注意:

-- 模块名必须以test开头,不然收集不到

-- 管理用例的必须是要包,因为包中有__init__.py模块,如果不是包可能pychram会报错

-- run.py模块的位置,是跟tests平级的,目的是这样可以收集这个项目下的所有测试用例

具体操作流程如下:

第一步:包和模块分别新建完成,并编写了测试用例

 test_demo.py 模块下代码如下:

import unittest


class TestDemo(unittest.TestCase):
    def test_demo_1(self):
        pass

 test_unittest.py 模块下代码如下:

import unittest  # 导入unittest


def login(username=None, password=None):
    if username is None or password is None:
        return {"code": "400", "msg": "用户名或密码为空"}
    if username == 'yuz' and password == '123':
        return {"code": "200", "msg": "登录成功"}
    return {"code": "300", "msg": "用户名或密码错误"}


# 类遵守规则:必须要继承unittest.TestCase
class TestLogin(unittest.TestCase):
    # 测试用例方法
    # 成功用例
    def test_login_1(self):
        username = 'li'
        password = '123'
        expected = {"code": "300", "msg": "用户名或密码错误"}
        actual = login(username, password)
        # assert expected == actual
        self.assertEqual(expected,actual)
    # 失败用例
    def test_login_2(self):
        username = 'yuz'
        password = '123'
        expected = {"code": "300", "msg": "用户名或密码错误"}
        actual = login(username, password)
        self.assertEqual(expected,actual)

 第二步:收集用例并运行用例

收集用例

suite = unittest.defaultTestLoader.discover('包名') 注意一定要引号包裹起来

运行用例

runner = unittest.TextTestRunner()
runner.run(suite)

都是固定用法,变量名suite,runner可以随便写

run.py模块下代码如下:

import unittest
# 收集用例,suite 只是个变量名,叫什么都可以
suite = unittest.defaultTestLoader.discover('tests')
# 运行用例,runner 也只是个变量名,叫什么都可以
runner = unittest.TextTestRunner()
runner.run(suite)

运行结果:

  3.2.3 夹具(fixture)

夹具又被称为固定装置、测试固件等。作用就是在测试过程中,提前为测试用例准备一个运行环境

比如要测试一个手机游戏是否被安装,那前提就是要准备一台手机,要测试一个数据库是否能操作,那前提就是需要提供数据库的连接环境

夹具的执行过程:每个用例之前,自动执行setUp,每个用例之后,自己执行tearDown

import unittest


class TestAdd(unittest.TestCase):
    # 用例的前置条件
    def setUp(self) -> None:
        print('连接数据库...')

    # 用例的后置清理
    def tearDown(self) -> None:
        print('断开数据库连接...')

    def test_db(self):
        # 测试一个数据库
        print('正在执行测试')
        self.assertTrue(1 + 1 == 2)

    def test_db2(self):
        print('正在执行测试2')
        self.assertEqual(1, 4)

运行结果:

 类的夹具

import unittest


class TestAdd(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        print('每个测试类执行一次')

    @classmethod
    def tearDownClass(cls) -> None:
        print('每个测试类之后执行一次')

    # 用例的前置条件
    def setUp(self) -> None:
        print('连接数据库...')

    # 用例的后置清理
    def tearDown(self) -> None:
        print('断开数据库连接...')

    def test_db(self):
        # 测试一个数据库
        print('正在执行测试')
        self.assertTrue(1 + 1 == 2)

    def test_db2(self):
        print('正在执行测试2')
        self.assertEqual(1, 4)

 运行结果:

每个测试类执行一次连接数据库...
正在执行测试
断开数据库连接...
连接数据库...
正在执行测试2
断开数据库连接...
每个测试类之后执行一次

 从运行结果可以看到,类的夹具只是运行所有用例之前执行一次,运行所有用例之后执行一次

 3.3 测试报告

生成测试报告有两种方法:unittestreport,beautifulreport

3.3.1 unittestreport

unittestrepor 有三种测试报告模板,可以选择,还可以修改测试报告格式filename,生成目录路径report_dir,报告名称title,测试人员tester等,不修改时有默认参数

修改后run.py模块下代码如下:

import unittest  # 导入unittest
import unittestreport  # 导入unittestreport
# 收集用例
suite = unittest.defaultTestLoader.discover('tests')
# 生成报告
runner = unittestreport.TestRunner(suite)
runner.run()

运行结果:

 运行后项目下会自动生成一个叫reports的目录,点击打开report.html文件,选择用浏览器的打开方式查看

修改报告的几个参数来看一下

修改后run.py模块下代码如下:

import unittest  # 导入unittest
import unittestreport  # 导入unittestreport
# 收集用例
suite = unittest.defaultTestLoader.discover('tests')
# 生成报告
runner = unittestreport.TestRunner(suite,
                                   title='py44测试报告',
                                   tester='沫沫',
                                   templates=2) # 只有3种模板,写4,5,6...都是显示第三种模板
runner.run()

测试报告如下:

 可以看到修改的地方,已经成功

 3.3.2 beautifulreport

beautifulreport 只有一种测试报告模板,不能选择,也可以修改文件的路径,报告的名称等,要注意的是descrition必须填写,否则会报错

 修改后run.py模块下代码如下:

import unittest
# 一定要先导入 beautifulreport
from BeautifulReport import BeautifulReport

# 收集用例
suite = unittest.defaultTestLoader.discover('tests')
# 生成报告
br = BeautifulReport(suite)
br.report(description='py44测试报告') # description 参数是必须填写的

 运行结果:

运行后项目下会自动生成一个叫report.html的文件,点击打开,选择用浏览器的打开方式查看

3. 4 安装unittestreport

第一种方法:选择File->Settings->Project->Project Interpreter:点击+号在弹出界面中搜索unittestreport,然后点击底部Install Package按钮

第二种方法:切换到Terminal界面,输入pip install unittestreport,回车即可

 安装beautifaulreport的方法跟unittestreport一样,就不介绍了

 4. pip介绍

pip是python官方的包管理工具。安装、卸载第三方的应用需要商店。如360管家。说白了也就是如果你想用别人写好的代码,就需要用pip安装

安装命令:pip install,安装一个python的软件/第三方库

pip安装应用的官方地址在国外,所以偶尔会出现报错,因此我们可以用国内镜像/国内源

国内源地址:
中国科技大学: https://pypi.mirrors.ustc.edu.cn/simple/

阿里云: http://mirrors.aliyun.com/pypi/simple/

清华大学: https://pypi.tuna.tsinghua.edu.cn/simple/

中国科学技术大学 :http://pypi.mirrors.ustc.edu.cn/simple/

使用国内源安装命令:

pip install -i https://pypi.mirrors.ustc.edu.cn/simple/  --upgrade  包名(需要安装的内容)

猜你喜欢

转载自blog.csdn.net/weixin_40611700/article/details/120506451