百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

unittest单元测试框架(unittest框架有什么缺点)

off999 2024-11-03 14:15 31 浏览 0 评论

一、测试模型

线性测试

1.概念:通过录制或编写对应应用程序的操作步骤产生的线性脚本。单纯的来模拟用户完整的操作场景。(操作,重复操作,数据)都混合在一起。

2.优点:每个脚本相对独立,且不产生其他依赖和调用。任何一个测试用例脚本拿出来都可以单独执行。

3.缺点:开发成本高,用例之间存在重复的操作。比如重复的用户登录和退出。维护成本高,由于重复的操作,当重复的操作发生改变时,则需要逐一进行脚本的修改。

4.线性测试实例:用户登录

模块化驱动测试

1.概念:将重复的操作独立成功共模块,当用例执行过程中需要用到这一模块操作时则被调用。操作+(重复操作,数据)混合在一起。例如,自动化测试的执行需要保持测试用例的独立性和完整性,所以每一条用例在执行时都需要登录和退出操作,so可以把登录和退出的操作封装为公共函数。

2.优点:由于最大限度消除了重复,从而提高了开发效率和提高测试用例的可维护性。

3.缺点:虽然模块化的步骤相同,但是测试数据不同。比如说重复的登录模块,如果登录用户不同,依旧要重复编写登录脚本。

4.实例:对公共模块,例如登陆和退出进行模块化封装

数据驱动测试

1.概念:它将测试中的测试数据和操作分离,数据存放在另外一个文件中单独维护。通过数据的改变从而驱动自动化测试的执行,最终引起测试结果的改变。 操作+重复操作+数据分开。

2.优点:通过这种方式,将数据和重复操作分开,可以快速增加相似测试,完成不同数据情况下的测试。

3.实例:从excel表格读取用户名密码,登录邮箱。

二、unittest框架

用Python搭建自动化测试框架,需要组织用例以及测试执行,大部分推荐的是unittest。 附上官方文档地址: https://docs.python.org/3/library/unittest.html

unittest是Python自带的单元测试框,可以用来作自动化测试框架的用例组织执行框架。优点:提供用例组织与执行方法;提供比较方法;提供丰富的日志、清晰的报告。 大致流程:

  • 写好TestCase
  • 由TestLoader加载TestCase到TestSuite
  • 然后由TextTestRunner来运行TestSuite,运行的结果保存在TextTestResult中。 通过命令行或者unittest.main()执行时,main会调用TextTestRunner中的run()来执行,或者可以直接通过TextTestRunner来执行用例。 在Runner执行时,默认将执行结果输出到控制台,我们可以设置其输出到文件,在文件中查看结果。

unittest中最核心的部分是:test fixture、test case、test suite、test runner。

test fixture

用于一个测试环境的准备和销毁还原。 当测试用例每次执行之前需要准备测试环境,每次测试完成后还原测试环境,比如执行前连接数据库、打开浏览器等,执行完成后需要还原数据库、关闭浏览器等操作。这时候就可以启用testfixture。

  • setUp():准备环境,执行每个测试用例的前置条件;
  • tearDown():环境还原,执行每个测试用例的后置条件;
  • tearDown():环境还原,执行每个测试用例的后置条件;
  • tearDown():环境还原,执行每个测试用例的后置条件;
# 访问数据库可以用此方法
@classmethod
def setUpClass(self):
    print('this is setupclass')

#打开浏览器时用此方法
def setUp(self):
    print('this is setup')

#测试用例(testCase)
............................

#截屏可以用此方法
def tearDown(self):
    print('this is teardown')

#关闭浏览器可以用此方法
@classmethod
def tearDownClass(self):
    print('this is teardownclass')

test case

类,unittest.TestCase 一个类class继承 unittest.TestCase,就是一个测试用例。一个TestCase的实例就是一个测试用例,就是一个完整的测试流程。 包括测试前环境准备setUp()|setUpClass()、执行代码run()、测试环境后的还原tearDown()|tearDownClass()。 继承自unittest.TestCase的类中,测试方法的名称要以test开头。且只会执行以test开头定义的方法(测试用例)。

例如:【先准备待测试的方法function.py】

def test_01register(self):
    print('****test_01register')

def test_02login(self):
    print('****test_02login')

测试脚本:

import unittest
from A_UnitTest_basicDemo_ok.function import *

# 定义一个加法的函数
def add(x,y):
    return x+y

# 定义一个减法函数
def minus(x,y):
    return x-y

# 定义一个乘法函数
def multi(x,y):
    return x*y

# 定义一个除法函数
def divide(x,y):
    return x/y

class TestFunc(unittest.TestCase):
    # 继承自unittest.TestCase
    # 重写TestCase的setUp()、tearDown()方法:在每个测试方法执行前以及执行后各执行一次
    def setUp(self):
        print("do something before test : prepare environment")

    def tearDown(self):
        print("do something after test : clean up ")
    
    # 测试方法均已test开头,否则是不被unittest识别的
    def test_add(self):
        print("add:")
        self.assertEqual(3,add(1,2))

    def test_minus(self):
        print("minus")
        self.assertEqual(3,minus(5,2))

    def test_multi(self):
        print("multi")
        self.assertEqual(6,multi(2 ,3))

    def test_divide(self):
        print("divide")
        self.assertEqual(2,divide(4,2))
        

if __name__ == '__main__':
# 在main()中加verbosity参数,可以控制输出的错误报告的详细程度
# verbosity=*:默认是1;设为0,则不输出每一个用例的执行结果;2-输出详细的执行结果
    unittest.main(verbosity=2)

【执行结果】:输出到控制台

test_add (__main__.TestFunc) ... do something before test : prepare environment
add:
do something after test : clean up
ok
test_divide (__main__.TestFunc) ... do something before test : prepare environment
divide
do something after test : clean up
ok
test_minus (__main__.TestFunc) ... do something before test : prepare environment
minus
do something after test : clean up
ok
test_multi (__main__.TestFunc) ... do something before test : prepare environment
multi
do something after test : clean up
ok

----------------------------------------------------------------------
Ran 4 tests in 0.006s

OK

test suite

上述简单的测试会产生两个问题,可不可以控制test测试用例的执行顺序?若不想执行某个测试用例,有没有办法可以跳过? 对于执行顺序,默认按照test的 A-Z、a-z的方法执行。若要按自己编写的用例的先后关系执行,需要用到testSuite。 把多个测试用例集合起来,一起执行,就是testSuite。testsuite还可以包含testsuite。 一般通过addTest()或者addTests()向suite中添加。case的执行顺序与添加到Suite中的顺序是一致的。 例如:run_main.py

if __name__ == "__main__":
    suite = unittest.TestSuite()
# 定义list,按照list里的顺序执行测试用例
    tests=[TestFunc("test_add"),TestFunc("test_minus"),TestFunc("test_multi"),TestFunc("test_divide")]
    suite.addTests(tests)
    runner = unittest.TextTestRunner(verbosity=2)
    runner.run(suite)

TestSuite可以再包含testsuite,示例如下:

suite1 = module.TheTestSuite()
suite2=module.TheTestSuite()
alltests=unittest.TestSuite([suite1],[suite2])

跳过某个case:skip装饰器

若想让某个测试用例不执行,有没有办法呢?当然是有的,可以使用skip装饰器。 例如:

@unittest.skip("i don't want to run this case -> test_minus() ... ")
def test_minus(self):
    print("minus")
    self.assertEqual(3,minus(5,2))

执行结果:

test_minus (__main__.TestFunc) ... skipped "i don't want to run this case -> test_minus() ... "

----------------------------------------------------------------------
Ran 4 tests in 0.005s

OK (skipped=1)

加上“@unittest.skip()”后,执行看看,对比控制台的输出结果就可以明显看出区别了。 Skip装饰器有如下几种情况: (1)skip():无条件跳过 @unittest.skip("i don't want to run this case. ") (2)skipIf(condition,reason):如果condition为true,则 skip @unittest.skipIf(condition,reason) (3)skipUnless(condition,reason):如果condition为False,则skip @unittest.skipUnless(condition,reason)

(4)还可以使用TestCase.skipTest(reason)。例如:

def test_divide(self):
    self.skipTest('do not run  test_divide()')
    print("divide")
    self.assertEqual(2,divide(4,2))

执行结果:

test_divide (__main__.TestFunc) ... do something before test : prepare environment
do something after test : clean up
skipped 'do not run  test_divide()'

----------------------------------------------------------------------
Ran 4 tests in 0.003s

OK (skipped=1)

test loader

TestLoadder用来加载TestCase到TestSuite中。 loadTestsFrom*()方法从各个地方寻找testcase,创建实例,然后addTestSuite,再返回一个TestSuite实例。 该类提供以下方法:

unittest.TestLoader().loadTestsFromTestCase(testCaseClass)
unittest.TestLoader().loadTestsFromModule(module)
unittest.TestLoader().loadTestsFromName(name,module=None)
unittest.TestLoader().loadTestsFromNames(names,module=None)
unittest.TestLoader().getTestCaseNames(testCaseclass)
unittest.TestLoader().discover()

TestLoader 之discover: 用discover()来加载测试多个测试用例,再用TextRunner类的run()方法去一次执行多个脚本的用例,达到批量执行的效果。 discover方法里面有三个参数: -case_dir:这个是待执行用例的目录。 -pattern:这个是匹配脚本名称的规则,test*.py意思是匹配test开头的所有脚本。 -top_level_dir:这个是顶层目录的名称,一般默认等于None就行了。


TextTestRunner():执行测试用例。runner.run(test)会执行TestSuite、TestCase中的run(result)方法。 如下:run_main.py示例

import unittest
import os
# 用例的路径
case_path = os.path.join(os.getcwd(),"case")
# 报告存放的路径
report_path = os.path.join(os.getcwd(),"report")
def all_cases():
    discover= unittest.defaultTestLoader.discover(case_path,pattern="test*.py",top_level_dir=None)
    print(discover)
    return discover
if __name__ == "__main__":
    runner = unittest.TextTestRunner(verbosity=2)
    runner.run(all_cases())

生成测试报告

  • 生成TXT测试报告

代码示例:

if __name__ == "__main__":
    suite = unittest.TestSuite()
    # 生成.txt的测试报告(控制台的输出写入到文件中)
    suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestFunc))
    with open('UnittestTextReport.txt','a') as f:
        runner = unittest.TextTestRunner(stream=f,verbosity=2)
        runner.run(suite)

可以看到在目录下,生成了UnittestTextReport.txt文件。 但是txt格式的文件太过于简陋。我们可以借助与第三方提供的库来输出更加形象的html报告,也可以自定义输出自己想要格式的html格式的报告。

  • 生成HTML测试报告
  • 先下载HTMLTestRunner.py(注意Python的版本), http://tungwaiyip.info/softwa... 。然后放在Python的Lib目录下;
  • 在run_main.py文件中加入:from HTMLTestRunner import HTMLTestRunner

HTMLTestRunner()方法有三个参数: --stream:测试报告写入文件的存储区域 --title:测试报告的主题 --description:测试报告的描述

代码示例:

if __name__ == "__main__":
    suite = unittest.TestSuite()
    # 生成HTML格式的具体测试报告
    with open('HtmlReport.html','wb') as f:  # 在python3,要写成'wb' or 'wr'
        runner = HTMLTestRunner(stream=f,title='function test   
report',description='generated by HTMLTestRunner',verbosity=2)
        runner.run(suite)

代码示例

  • function.py
#!/usr/bin/python3
# -*- coding:utf-8 -*-
def add(a,b):
    return a+b
def minus(a,b):
    return a-b
def multi(a,b):
    return a*b
def divide(a,b):
    return a/b
  • function.py
#!/usr/bin/python3
# -*- coding:utf-8 -*-
import unittest
from UnitTest_1.function import *  # from..import ... :要指定文件的路径

class TestFunc(unittest.TestCase): # unittest.TestCase
# 如果想在所有case执行之前准备一次测试环境,并在所有case执行结束后再清理环境
    @classmethod
    def setUpClass(cls):
        print("this setupclass() method only called once")
    @classmethod
    def tearDownClass(cls):
        print("this teardownclass() method only called once too")

    # 测试方法均已test开头,否则是不被unittest识别的
    def test_add(self):
        print("add:")
        self.assertEqual(3,add(1,2))
    def test_minus(self):
        print("minus")
        self.assertEqual(3,minus(5,2))
    # 如果想临时跳过某个case:skip装饰器
    @unittest.skip("i don't want to run this case. ")
    def test_multi(self):
        print("multi")
        self.assertEqual(6,multi(2,3))
    def test_divide(self):
        print("divide")
        self.assertEqual(2,divide(5,2))

if __name__ == "__main__":
    # 在main()中加verbosity参数,可以控制输出的错误报告的详细程度
    # verbosity=*:默认是1;设为0,则不输出每一个用例的执行结果;2-输出详细的执行结果
    unittest.main(verbosity=2)

执行结果:

this setupclass() method only called once
test_add (__main__.TestFunc) ... add:
ok
test_divide (__main__.TestFunc) ... divide
FAIL
test_minus (__main__.TestFunc) ... minus
ok
test_multi (__main__.TestFunc) ... skipped "i don't want to run this case. "
this teardownclass() method only called once too

======================================================================
FAIL: test_divide (__main__.TestFunc)
----------------------------------------------------------------------
Traceback (most recent call last):
  File ".\test6.py", line 45, in test_divide
    self.assertEqual(2,divide(5,2))
AssertionError: 2 != 2.5

----------------------------------------------------------------------
Ran 4 tests in 0.007s

FAILED (failures=1, skipped=1)

相关推荐

网络电视在线观看高清(网络电视在线电视直播大全)

如果网站已建好,可以嵌套一些现成的加密sdk小程序,实现对视频的保护,防止下载、恶意传播、播放等;1做防盗链处理,防止下载;2视频加密sdk,对视频本身进行加密处理,即使被下载,也无法播放!;3...

cad提供的激活码16组(autocad2014永久激活码16个)

1.断开网络,拔除网线或禁用网卡;2.安装时输入序列号“666-69696969”,产品密钥“001H1”;3.安装完毕后启动AutoCAD2017,点击“激活”,然后选择“使用脱机方法申请激活码...

163com免费邮箱(163邮箱网页版入口)

163邮箱官网首页入口为http://mail.163.com/网易163免费邮箱--中文邮箱第一品牌.容量自动翻倍,支持50兆附件,免费开通手机号码邮箱赠送3G超大附件服务.支持各种客户端软件收发,...

三国老款经典单机游戏(老版的三国单机游戏)

《三国战记》;《三国群英传》;《三国志》;《三国杀》。游戏介绍:《三国战记》:《三国战纪:风云再起》游戏背景为东汉末年,异象四起:连年天灾、作物欠收、民不聊生,连带影响税收。以张角为首的黄...

视频转换器哪个好(视频转换器排行榜)

建议使用狸窝转换器,它功能齐全,界面简洁,体积小,速度快。嗨格式视频转换器是一款非常实用的视频文件转换工具,它可以将各种视频格式之间进行转换,例如将MP4、AVI、MOV等视频格式转换成其他常见的视频...

自动算税软件(自动算税软件怎么用)
自动算税软件(自动算税软件怎么用)

1、首先,打开手机,找到appstore,在appstore内输入个人所得税。点击获取之后会在页面底部出现如下弹框,点击安装。2、之后会出现如下弹框,显示获取个人所得税app需要进行一个简短的验证才可以,点击继续按钮。在输入框内输入上面...

2026-01-18 18:03 off999

农场类模拟经营游戏(一款很老的农场游戏)

个人觉得《真实模拟农场3D》好玩!这是一款以经营农场为主题的模拟类游戏,你会马上成为一个农场主人。负责一块开阔农场的日常运营,把自己的农场运作的蒸蒸日上,成为最富有的农场主。玩家可以驾驶拖拉机,收割机...

手机腾讯游戏中心(手机腾讯游戏中心在哪)
  • 手机腾讯游戏中心(手机腾讯游戏中心在哪)
  • 手机腾讯游戏中心(手机腾讯游戏中心在哪)
  • 手机腾讯游戏中心(手机腾讯游戏中心在哪)
  • 手机腾讯游戏中心(手机腾讯游戏中心在哪)
做图片的软件(做图片的软件app)
做图片的软件(做图片的软件app)

有手机版的p图大神可以制作好玩的图片此软件专门进行图片恶搞的,手机用美图秀秀,电脑上用ps推荐7个冷门APP吧,以上APP都是朋友推荐或自己无意间发现的,如有雷同,纯属意外。1.马卡龙玩图:马卡龙玩图是一款非常有趣的修图APP,强大的抠图功...

2026-01-18 17:15 off999

德国vs日本视频直播(德国vs日本视频直播回放)
德国vs日本视频直播(德国vs日本视频直播回放)

世界杯直播德国与日本的比赛是在北京时间的11月23日21点这个时间段举行,这场比赛在卡塔尔世时间则是为16:00点。历史上德国和日本曾经有过2次交手,在2004年12月(日本0-3德国)和2006年5月(德国2-2日本)两队分别进行过2场友...

2026-01-18 17:03 off999

卡牌类手游排行榜第一名(卡牌类手游排行榜第一名是谁)

阴阳师忘川风华录神将三国姬斗无双天地劫:幽成再临月圆之夜阿比斯之旅黑潮之上山海镜花斗罗大陆:武魂觉醒以下是一拳超人手游中常见的卡牌排名:S级卡牌:1.一拳超人(变身)2.童帝(变身)3.杰诺斯A...

英雄联盟手游内测申请(英雄联盟手游内测申请地址)

要申请英雄联盟手游内测资格,您需要先安装好游戏并创建账号。然后根据游戏官方发布的内测申请指南,在指定时间内填写相应的申请表格。一般来说,申请表格会要求您填写以下信息:1.基本个人信息:包括姓名、年龄...

金色影视影视剧(金色影视 tv)

电影《金色池塘》拍摄地是英国南部新汉普郡。《金色池塘》是由马克·雷戴尔执导,凯瑟琳·赫本、亨利·方达等主演的剧情片。该片根据欧内斯特·汤普森的同名戏剧改编而成,讲述了年老的诺曼与女儿之间出现了感情危机...

下载全民k歌免费安装(找回《全民k歌》)

打开全民k歌网页版,打开想要下载的歌曲按F12,点击Network的选项,再按ctrl+R找到里面最大的文件,右键openlinkinnewtab新的页面中右键另存为,就可以下载了1.确保您的手机支...

oa软件排行榜前十名(oa软件下载)

OA办公软件有很多,例如泛微、致远、蓝凌、华天动力、索昂、通达、飞企、微宏、万户、金和、今目标、协众、云之家、泛普、明道、天翎、手册类、安创安全OA、小熊OA等相对大型企业来说,中小型企业的管理规范...

取消回复欢迎 发表评论: