unittest单元测试框架(unittest框架有什么缺点)
off999 2024-11-03 14:15 24 浏览 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
OKtest 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)相关推荐
- 阿里云国际站ECS:阿里云ECS如何提高网站的访问速度?
-
TG:@yunlaoda360引言:速度即体验,速度即业务在当今数字化的世界中,网站的访问速度已成为决定用户体验、用户留存乃至业务转化率的关键因素。页面加载每延迟一秒,都可能导致用户流失和收入损失。对...
- 高流量大并发Linux TCP性能调优_linux 高并发网络编程
-
其实主要是手里面的跑openvpn服务器。因为并没有明文禁p2p(哎……想想那么多流量好像不跑点p2p也跑不完),所以造成有的时候如果有比较多人跑BT的话,会造成VPN速度急剧下降。本文所面对的情况为...
- 性能测试100集(12)性能指标资源使用率
-
在性能测试中,资源使用率是评估系统硬件效率的关键指标,主要包括以下四类:#性能测试##性能压测策略##软件测试#1.CPU使用率定义:CPU处理任务的时间占比,计算公式为1-空闲时间/总...
- Linux 服务器常见的性能调优_linux高性能服务端编程
-
一、Linux服务器性能调优第一步——先搞懂“看什么”很多人刚接触Linux性能调优时,总想着直接改配置,其实第一步该是“看清楚问题”。就像医生看病要先听诊,调优前得先知道服务器“哪里...
- Nginx性能优化实战:手把手教你提升10倍性能!
-
关注△mikechen△,十余年BAT架构经验倾囊相授!Nginx是大型架构而核心,下面我重点详解Nginx性能@mikechen文章来源:mikechen.cc1.worker_processe...
- 高并发场景下,Spring Cloud Gateway如何抗住百万QPS?
-
关注△mikechen△,十余年BAT架构经验倾囊相授!大家好,我是mikechen。高并发场景下网关作为流量的入口非常重要,下面我重点详解SpringCloudGateway如何抗住百万性能@m...
- Kubernetes 高并发处理实战(可落地案例 + 源码)
-
目标场景:对外提供HTTPAPI的微服务在短时间内收到大量请求(例如每秒数千至数万RPS),要求系统可弹性扩容、限流降级、缓存减压、稳定运行并能自动恢复。总体思路(多层防护):边缘层:云LB...
- 高并发场景下,Nginx如何扛住千万级请求?
-
Nginx是大型架构的必备中间件,下面我重点详解Nginx如何实现高并发@mikechen文章来源:mikechen.cc事件驱动模型Nginx采用事件驱动模型,这是Nginx高并发性能的基石。传统...
- Spring Boot+Vue全栈开发实战,中文版高清PDF资源
-
SpringBoot+Vue全栈开发实战,中文高清PDF资源,需要的可以私我:)SpringBoot致力于简化开发配置并为企业级开发提供一系列非业务性功能,而Vue则采用数据驱动视图的方式将程序...
- Docker-基础操作_docker基础实战教程二
-
一、镜像1、从仓库获取镜像搜索镜像:dockersearchimage_name搜索结果过滤:是否官方:dockersearch--filter="is-offical=true...
- 你有空吗?跟我一起搭个服务器好不好?
-
来人人都是产品经理【起点学院】,BAT实战派产品总监手把手系统带你学产品、学运营。昨天闲的没事的时候,随手翻了翻写过的文章,发现一个很严重的问题。就是大多数时间我都在滔滔不绝的讲理论,却很少有涉及动手...
- 部署你自己的 SaaS_saas如何部署
-
部署你自己的VPNOpenVPN——功能齐全的开源VPN解决方案。(DigitalOcean教程)dockovpn.io—无状态OpenVPNdockerized服务器,不需要持久存储。...
- Docker Compose_dockercompose安装
-
DockerCompose概述DockerCompose是一个用来定义和管理多容器应用的工具,通过一个docker-compose.yml文件,用YAML格式描述服务、网络、卷等内容,...
- 京东T7架构师推出的电子版SpringBoot,从构建小系统到架构大系统
-
前言:Java的各种开发框架发展了很多年,影响了一代又一代的程序员,现在无论是程序员,还是架构师,使用这些开发框架都面临着两方面的挑战。一方面是要快速开发出系统,这就要求使用的开发框架尽量简单,无论...
- Kubernetes (k8s) 入门学习指南_k8s kubeproxy
-
Kubernetes(k8s)入门学习指南一、什么是Kubernetes?为什么需要它?Kubernetes(k8s)是一个开源的容器编排系统,用于自动化部署、扩展和管理容器化应用程序。它...
欢迎 你 发表评论:
- 一周热门
-
-
抖音上好看的小姐姐,Python给你都下载了
-
全网最简单易懂!495页Python漫画教程,高清PDF版免费下载
-
Python 3.14 的 UUIDv6/v7/v8 上新,别再用 uuid4 () 啦!
-
python入门到脱坑 输入与输出—str()函数
-
宝塔面板如何添加免费waf防火墙?(宝塔面板开启https)
-
Python三目运算基础与进阶_python三目运算符判断三个变量
-
(新版)Python 分布式爬虫与 JS 逆向进阶实战吾爱分享
-
飞牛NAS部署TVGate Docker项目,实现内网一键转发、代理、jx
-
慕ke 前端工程师2024「完整」
-
失业程序员复习python笔记——条件与循环
-
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python进度条 (67)
- python吧 (67)
- python的for循环 (65)
- python格式化字符串 (61)
- python静态方法 (57)
- python列表切片 (59)
- python面向对象编程 (60)
- python 代码加密 (65)
- python串口编程 (77)
- python封装 (57)
- python写入txt (66)
- python读取文件夹下所有文件 (59)
- python操作mysql数据库 (66)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python多态 (60)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)
