【Python】单元测试框架unitest及其高级应用

目录

Unittest

简单使用示例

重要概念

断言方法

深入

高级应用

认识Page Object

 资料获取方法


Unittest

Unittest是python的一个单元测试框架,但是它不仅适用于单元测试,还适用自动化测试用例的开发与执行。我们可以很方便的使用它组织执行测试用例,使用它提供的丰富的断言方法进行测试结果比对,并最终结合HTMLTestRunner生成测试报告完成整个自动化测试流程。

简单使用示例

创建被测类calculator.py

class count:def _init_(self,a,b)self.a = int(a)self.b = int(b)#计算加法def add(self):return self.a + self.b

通过unittest单元测试框架编写单元测试用例 test.py

from calculator import count
import unitest
class TestCount(unitest.TestCase):def setUp(self):print("test start")def test_add(self):j = count(2,3)self.assertEqual(j.add(),5)def tearDown(self):print("test end") 
if _name_ == '_main_':unittest.main()

说明:

  1. 首先引入unitest模块,创建testcount类继承unitest的testcase类。
  2. setUp():用于测试用例执行前的初始化工作,与tearDown()相呼应,用于执行后的善后工作。
  3. test_add中调用count类并传入要计算的数,通过调用add()方法得到两数相加的返回值,这里不再使用繁琐的异常处理,而是调用unitest框架所提供的assertEqual()对add()的返回值进行断言判断两者是否相等。assertEqual()方法是由testcase类继承而来的。
  4. main():unitest提供了全局的main()方法,使用它可以方便的将一个单元测试模块变成可以直接运行的测试脚本。main()方法使用Testloader类来搜索所有包含在该模块中以“test”命名开头的测试方法。
  5. name:作为模块的内置属性,简单地说就是.py文件的调用方式。.py文件有两种使用方式作为模块调用和直接使用,如果它等于“main”就表示是直接使用

重要概念

  1. TestCase:一个TestCase的实例就是一个测试用例,是一个完整的测试流程,包括测试前准备环境的搭建(setUp),实现测试过程的代码(run),测试后环境的还原(tearDown).
  2. Test Suite:把多个测试用例集合在一起来执行。可以通过addTest加载TestCase到Test Suite中,从而返回一个TestSuite实例。
  3. Test Runner:测试的执行,通过TextTestRunner类提供的run()方法来执行Test Suite/TestCase。Test Runner可以使用图形界面,文本界面,或者返回一个特殊的值的方式来表示测试执行的结果。
  4. Test Fixture:对一个测试用例环境的搭建和销毁。通过覆盖TestCase的setUp()和tearDown()方法来实现。tearDown()为下一个测试用例提供一个干净的环境。
from calculator import count
import unitest
class TestCount(unitest.TestCase):def setUp(self):print("test start")def test_add(self):j = count(2,3)self.assertEqual(j.add(),5)def test_add2(self):j = count(7,8)self.assertEqual(j.add(),15)def tearDown(self):print("test end") 
if _name_ == '_main_':unittest.main()
#构建测试集
suite = unittest.TestSuite()
suite.addTest(TestCount("test_add2"))
#执行测试
runner = unittest.TextTestRunner()
runner.run(suite)

本例只执行第二个测试用例,

  1. 调用unittest框架的TestSuite()来创建测试套件。
  2. 通过它所提供的addTest()方法来添加测试用例test_add2。
  3. 调用unitest框架的TextTestRunner().
  4. 通过它下面的run()方法来运行suite所组装的测试用例。

断言方法

unittest框架的TestCase类提供的断言方法用于测试结果的判断

判断第一个参数和第二个参数是否相等

-assertEqual(first,second,msg=None)
# 如果不相等则测试失败,msg为可选参数,用于定义测试失败时打印的信息。
self.assertEqual(j.add(),15,msg="测试结果不等于15")

格式:-assertNotEqual(first,second,msg=None)则与之相反

判断表达式是true(或false)

-assertTrue(expr,msg=None)
-assertFalse(expr,msg=None)

创建count.py用于判断质数的

def is_prime(n):if n<=1:return Falsefor i in range(2,n):if n % i = = 0:return Falseretun True

测试用例:调用is_prime()函数和unittest

self.assertTrue(is_prime(7),msg="is not prime")

判断第一个参数是否在第二个参数中,就是第二个参数是否包含第一个参数。

-assertIn(first,second,msg=None)  
-assertNotIn(first,second,msg=None)

测试用例(部分):

def test_case(self):a = "hello"b = "hello world"self.assertIn(a,b,msg="a is not in b")

判断第一个参数和第二个参数是否为同一对象

-assertIs(first,second,msg=None)
-assertIsNot(first,second,msg=None)

判断表达式是否为None对象

-assertIsNone(expr,msg=None)
-assertIsNotNone(expr,msg=None)

判断obj是否为cls的一个实例格式:

-assertIsInstance(obj,cls,msg=None)
-assertNotIsInstance(obj,cls,msg=None)

深入

组织单元测试用例

  • 方法1.setUp()和setDown方法分别作用于每个测试用例的开始和结束
  • 方法2.如果每个类中的setUp()和setDown方法所做的事情是一样的,那么可以封装成一个自己的测试类

discover更多测试用例

如果单元测试用例达到成百上千个,可以将这些用例按照所测试的功能进行拆分,分散到不同的测试文件中
最后再创建用于执行所有测试用例的runtest.py文件。

  • 方法1:可以通过addTest()加载TestCase到TestSuite中。用于少量的测试用例
  • 方法2:使用TestLoader类提供的discover()方法来加载所有的测试用例。正常情况下,不需要创建这个类的实例,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.

用例执行的原则

unittest框架默认根据ASCII码的顺序加载测试用例,数字与字母的顺序为:0-9,A-Z,a-z。所以TestAdd会优于TestBdd类被执行,test_aaa()方法会优于test_ccc被执行,因而它并没有按照用例从上到下的顺序执行。

对于测试目录和测试文件来说,unittest框架同样是按照这个规则来加载测试用例的。
如果按照指定的顺序执行,可以通过TestSuite类的addTest()方法按照一定的顺序加载。不能默认main()方法了。需要构造测试集,然后通过run()方法执行测试。

注意:discover()的加载测试用例的规则与main()方法相同,所以只能通过测试用例的命名来提高被执行的优先级。

执行多级的用例

discover()方法中的start_dir只能加载当前目录下的.py文件,如果加载子目录下的.py文件,需在每个子目录下放一个_init_.py文件。

跳过测试和预期失败

unittest提供了实现某些需求的装饰器,在执行测试用例时每个装饰前面加@符号。

  • unittest.skip(reason):无条件的跳过装饰的测试,说明跳过测试的原因
  • unittest.skipIf(condition,reason):跳过装饰的测试,如果条件为真。
  • unittest.skipUnless(condition,reason):跳过装饰的测试,除非条件为真。
  • unittest.expectedFailure():测试标记为失败,不管执行结果是否失败,统一标记为失败,但不会抛出错误信息。

fixtures

fixtures可以形象的把他看作是夹心饼干外层的两片饼干,这两片饼干就是setUp/tearDown,中间的心就是测试用例,除此以外,unittest还提供了更大范围的fixtures,例如对于测试类和模块的fixtures。

  • setUpModule/tearDownModule:在整个模块的开始和结束时被执行。
  • setUpClass/tearDownClass: 在测试类的开始和结束时被执行。
  • setUp/tearDown:在测试用例的开始与结束时被执行
    注意:setUpClass/tearDownClass的写法稍有不同,首先通过@classmethod进行装饰,其次方法的参数为cls,也可以是别的。每一个上面都要进行装饰

高级应用

HTMLTestRunner

HTMLTestRunner是python标准库unittest单元测试框架的一个拓展,它生成易于使用的HTML测试报告。
HTMLTestRunner下载地址:HTMLTestRunner - tungwaiyip's software
这个拓展只有一个HTMLTestRunner.py文件,选中后单击鼠标右键,在弹出的快捷菜单中选择目标另存为,将它保存到本地。安装方法是将其复制到python安装目录下即可。

  • windows:将下载的文件保存到...\python35\Lib目录下
  • Ubuntu:以root身份将HTMLTestRunner.py文件复制到/usr/local/python3.4/dist-packages/目录下。

HTMLTestRunner.py文件是基于python2开发的,若要支持python3环境需要对其中的部分内容进行修改。

生成HTML测试报告

  1. 将HTMLTestRunner模块用import导入进来
  2. 通过open()方法以二进制写模式打开当前目录下的result.html,如果没有,则自动创建该文件。
  3. 调用HTMLTestRunner模块下的HTMLTestRunner类,stream指定测试报告文件,title用于定义测试报告的标题,
    description用于定义测试报告的副标题。
  4. 最后,通过HTMLTestRunner的run()方法来运行测试套件中所组装的测试用例。
  5. 通过close()关闭测试报告文件。

更易读的测试报告

方法:加注释并用一种方法读取
在类和方法的下方,通过三引号(""" """或''' ''')来添加docstring类型的注释,这类注释在平时调用的时候
不显示,可以通过help()方法来查看类或方法的这种注释。

HTMLTestRunner可以读取docstring类型的注释,所以只需给测试类或方法添加这种类型的注释即可。

测试报告名称建议

在每次运行测试之前,都要手动修改报告的名称,如果忘记修改,就会把之前的报告覆盖,为了使每次生成的报告名称都不重复并且有意义,最好的方法是在报告名称中加入当前时间,这样生成的报告既不会重叠,又能更清晰的知道报告的生成时间。

  • time.time():获取当前时间戳 比如:1445694559.2290168
  • time.ctime():当前时间的字符串形式 比如:'sat oct 24 21:49:29 2015'
  • time.localtime():当前时间的struct_time形式 比如:tm_year=2015,tm_mon=10,tm_mday=24,..........等等。
  • time.strftime("%Y_%m_%d %H:%M:%s"):用来获得当前时间,可以将时间格式化为字符串。比如:'2015_10_24 21:50:15'

方法:通过时间操作的方法以指定的格式获取当前时间,将当前时间的字符串赋值给now变量,将now通过加号(+)拼接到生成的测试报告的文件名中,再次运行测试用例,生成测试报告文件名。

项目集成测试报告

目前HTMLTestRunner只是针对单个测试文件生成测试报告,若要使其作用于整个测试项目,
要将它集成到runtest.py文件中,对其文件进行修改。

认识Page Object

Page Object设计模式的优点

  1. 减少代码的重复性
  2. 提高测试用例的可读性
  3. 提高测试用例的可维护性,特别是针对UI频繁变化的项目

为web页面编写测试时,需要操作该web页面上的元素,如果在测试代码中直接操作HTML元素,那么你的代码是极其脆弱的,因为UI经常变动。我们可以将一个page对象封装成一个HTML页面,然后通过提供的应用程序特定的API来操作页面元素,而不是在HTML中四处搜寻。
page对象应当将在GUI控件上所有查询和操作数据的行为封装为方法,即使改变具体的控件,page对象的接口也不应当发生变化。

“页面”对象不仅是针对每个页面建立一个这样的对象,对由重要意义的元素也可以独立为一个page对象。

Page Object实例

  1. 创建page类
  2. 创建LoginPage类
  3. 创建test_user_login()函数
  4. 创建main()函数

 资料获取方法

【留言777】

各位想获取源码等教程资料的朋友请点赞 + 评论 + 收藏,三连!

三连之后我会在评论区挨个私信发给你们~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/59775.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于arcFace+faiss开发构建人脸识别系统

在上一篇博文《基于facenetfaiss开发构建人脸识别系统》中&#xff0c;我们实践了基于facenet和faiss的人脸识别系统开发&#xff0c;基于facenet后续提出来很多新的改进的网络模型&#xff0c;arcFace就是其中一款优秀的网络模型&#xff0c;本文的整体开发实现流程与前文相同…

04-2_Qt 5.9 C++开发指南_SpinBox使用

文章目录 1. SpinBox简介2. SpinBox使用2.1 可视化UI设计2.2 widget.h2.3 widget.cpp 1. SpinBox简介 QSpinBox 用于整数的显示和输入&#xff0c;一般显示十进制数&#xff0c;也可以显示二进制、十六进制的数&#xff0c;而且可以在显示框中增加前缀或后缀。 QDoubleSpinBox…

(MVC)SpringBoot+Mybatis+Mapper.xml

前言&#xff1a;本篇博客主要对MVC架构、Mybatis工程加深下理解&#xff0c;前面写过一篇博客&#xff1a;SprintBoothtml/css/jsmybatis的demo&#xff0c;里面涉及到了Mybatis的应用&#xff0c;此篇博客主要介绍一种将sql语句写到了配置文件里的方法&#xff0c;即Mybatis里…

IP路由基础+OSPF 基础

IP路由 RIB与FIB RIB&#xff1a;Routing Information Base&#xff0c;路由信息库 &#xff0c;路由器的控制平面 FIB&#xff1a;Forwarding Information Base&#xff0c;转发信息库&#xff0c;路由器的数据平面 路由信息库主要是记录直连路由以及协议宣告的路由信息&am…

有哪些简单的AI绘画软件?

随着人工智能技术的不断发展&#xff0c;越来越多的人工智能绘画软件出现了。人工智能绘画软件利用人工智能技术&#xff0c;通过计算机自动生成或辅助生成艺术作品。人工智能绘画软件通常集成了深度学习、计算机视觉和自然语言处理技术&#xff0c;可以模拟人类的创作过程&…

Openlayers实战:fill,stroke,icon,text应用范例

Openlayers中加载或者绘制的数据,在layer上以矢量的形式展示,通过设置style,可以赋值填充色,边框大小颜色,文字,图片等。在本示例中,将这些基础的内容汇集在一起,做一个演示。 效果图 源代码 /* * @Author: 大剑师兰特(xiaozhuanlan),还是大剑师兰特(CSDN) * @此…

SolidUI社区-提示词链式思考(CoT)

背景 随着文本生成图像的语言模型兴起&#xff0c;SolidUI想帮人们快速构建可视化工具&#xff0c;可视化内容包括2D,3D,3D场景&#xff0c;从而快速构三维数据演示场景。SolidUI 是一个创新的项目&#xff0c;旨在将自然语言处理&#xff08;NLP&#xff09;与计算机图形学相…

缓解针对LLM应用程序的存储提示注入攻击

推荐&#xff1a;使用 NSDT场景编辑器 助你快速搭建可编辑的3D应用场景 LLM提供提示文本&#xff0c;并根据其已训练和访问的所有数据进行响应。为了用有用的上下文补充提示&#xff0c;一些 AI 应用程序捕获来自用户的输入&#xff0c;并在将最终提示发送到 LLM 之前将用户看不…

Cortex-M3的双堆栈MSP和PSP(学习)

M3的栈&#xff0c;先进后出。 是局部变量内存的开销&#xff0c;函数的调用都离不开栈。 Cortex-M3内核使用了双堆栈&#xff0c;即MSP和PSP。 MSP&#xff1a;Main_Stack_Pointer&#xff0c;即主栈。 PSP&#xff1a;Process_Stack_Pointer&#xff0c;即任务栈。 SP&#…

[信号与系统系列] 正弦振幅调制之差拍信号

当将具有不同频率的两个正弦曲线相乘时&#xff0c;可以创建一个有趣的音频效果&#xff0c;称为差拍音符。这种现象听起来像颤音&#xff0c;最好通过选择一个频率非常小的信号与和另一个频率大约1KHz的信号&#xff0c;把二者混合从而听到。一些乐器能够自然产生差拍音符。使…

【2.2】Java微服务:Hystrix的详解与使用

目录 分布式系统面临问题 Hystrix概念 Hystrix作用 降级 什么是降级 order服务导入Hystrix依赖&#xff08;简单判断原则&#xff1a;谁调用远程谁加&#xff09; 启动类添加注解 业务方法添加注解&#xff08;冒号里填回调方法名&#xff0c;回调方法返回兜底数据&…

1077 Kuchiguse

PTA | 程序设计类实验辅助教学平台 一个测试点没过&#xff0c;不知道哪的原因 #include<bits/stdc.h> using namespace std; const int N210; int n; string s[N]; string str[N]; string ans; int main() {int len300;scanf("%d",&n);getchar();for(int…