unittest单元测试

news2024/11/16 13:38:09

java的单元测试框架Junit和TestNG,python里面也有单元测试框架-unittest,相当于是一个python版的junit。python里面的单元测试框架除了unittest,还有一个pytest框架,但是用的比较少

unittest注意点:
导入unittest模块
类名的第一个字母大写;
类要继承unittest.TestCase;
测试函数前必须加test,否则不会被当作测试用例来执行;
setUp()和tearDown()方法每个测试用例都会执行;
 

代码示例1:简单用法

#encoding=utf-8

import unittest
import random

class TestSequenceFunctions(unittest.TestCase):
    def setUp(self):
        # 初始化一个递增序列
        self.seq = range(10)
        print ("setup completed!")


    def test_run(self):
        # 从序列seq中随机选取一个元素
        element = random.choice(self.seq)
        # 验证随机元素确实属于列表中
        self.assertTrue(element in self.seq)

    def test_sth(self):
        assert 1==1

    def tearDown(self):
        print ("tearDown completed")


class TestDictValueFormatFunctions(unittest.TestCase):
    def setUp(self):
        self.seq = list(range(10))

    def test_shuffle(self):
        # 随机打乱原seq的顺序
        random.shuffle(self.seq)
        self.seq.sort()
        self.assertEqual(self.seq, list(range(10)))
        # 验证执行函数时抛出了TypeError异常
        self.assertRaises(TypeError, random.shuffle, (1, 2, 3))


if __name__ == '__main__':
unittest.main()


说明:

setUp:做初始化的工作,不是必须有这个函数

tearDown:清理的工作,不是必须有这个函数

unittest.main():将所有继承自unittest.TestCase的子类中的方法都执行

assertRaises();第一个参数表示抛出的异常类型,第二个参数是要执行的函数,第三个参数是函数传入的参数

代码示例2:初始化只执行一次的方法

#encoding=utf-8
import unittest

# 被测试类
class myclass(object):
    @classmethod
    def sum(self, a, b):
        return a + b #将两个传入参数进行相加操作

    @classmethod
    def sub(self, a, b):
        return a - b #将两个传入参数进行相减操作


class mytest(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        "初始化类固件"
        print ("----setUpClass")

    @classmethod
    def tearDownClass(cls):
        "重构类固件"
        print ("----tearDownClass")

    # 初始化工作
    def setUp(self):
        self.a = 3
        self.b = 1
        print ("--setUp")

    # 具体的测试用例,一定要以test开头
    def testsum(self):
        # 断言两数之和的结果是否是4
        self.assertEqual(myclass.sum(self.a, self.b), 4, 'test sum fail')

    def testsub(self):
        # 断言两数之差的结果是否是2
        self.assertEqual(myclass.sub(self.a, self.b), 2, 'test sub fail')


if __name__ == '__main__':
unittest.main() # 启动单元测试



说明:setUpClass()和tearDownClass()在每个类中只执行一次

代码示例3:按数字或字母顺序执行测试case

#encoding=utf-8

import unittest
from Calc import Calc

class MyTest(unittest.TestCase):
    @classmethod
    def setUpClass(self):
        print ("单元测试前,创建Calc类的实例")
        self.c = Calc()

    # 具体的测试用例,一定要以test开头,执行顺序按照字母顺序开头
    def test_0add(self):
        print ("run add()")
        self.assertEqual(self.c.add(1, 2, 12), 15, 'test add fail')

    def test_1sub(self):
        print ("run sub()")
        self.assertEqual(self.c.sub(2, 1, 3), -2, 'test sub fail')

    def test_2mul(self):
        print ("run mul()")
        self.assertEqual(Calc.mul(2, 3, 5), 30, 'test mul fail')

    def test_3div(self):
        print ("run div()")
        self.assertEqual(Calc.div(8, 2, 4), 1, 'test div fail')


    def test4(self):
        print('not start with test')

if __name__ == '__main__':
unittest.main()# 启动单元测试

说明:

测试用例(test_*)的执行顺序是根据1-2-3执行的,也就是说根据用例名称来顺序执行的,如果是字母开头的话同理
test4这个方法没有执行,说明测试用例只能以test开头
代码示例4:根据实际需要有跳过某些测试case

#encoding=utf-8

import random,sys,unittest

class TestSeqFunctions(unittest.TestCase):

      a = 1
      def setUp(self):
            self.seq = list(range(20)) 

      @unittest.skip("skipping")#无条件忽略此测试方法
      def test_shuffle(self):
            random.shuffle(self.seq)
            self.seq.sort()
            self.assertEqual(self.seq,list(range(20)))
            self.assertRaises(TypeError,random.shuffle,(1,2,3))

      @unittest.skipIf(a>5,"condition is not satisfied!")#如果a>5忽略此测试方法
      def test_choice(self):
            element = random.choice(self.seq)
            self.assertTrue(element in self.seq)

      #除非是linux平台,否则忽略此方法,win32是windows平台
      @unittest.skipUnless(sys.platform.startswith("linux"),"requires Linux")
      def test_sample(self):
            with self.assertRaises(ValueError):
                  random.sample(self.seq, 20)
            for element in random.sample(self.seq, 5):
                  self.assertTrue(element in self.seq)

if __name__=="__main__":
# unittest.main()
suite = unittest.TestLoader().loadTestsFromTestCase(TestSeqFunctions)
    suite = unittest.TestSuite(suite)
    unittest.TextTestRunner(verbosity = 2).run(suite)

说明:

@unittest.skip("skipping")#无条件忽略此测试方法
@unittest.skipIf(a > 5, "condition is not satisfied!"):满足第1个参数指定的条件,则忽略该测试方法
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux"):除非是第1个参数指定的条件,否则忽略此方法
没有使用unittest.main()是因为此种方式会将所有的测试类都执行,用unittest.TestLoader().loadTestsFromTestCase(TestSeqFunctions)指定执行的测试类
 

代码示例5:测试集组合
 

TestCalc.py:

#encoding=utf-8

import unittest
import random
from Calc import Calc

class TestCalcFunctions(unittest.TestCase):

    def setUp(self):
        self.c=Calc()
        print ("setup completed!")

    def test_sum(self):
        self.assertTrue(self.c.add(1,2,3,4)==10)

    def test_sub(self):
        self.assertTrue(self.c.sub(100,20,30,40)==10)

    def test_mul(self):
        self.assertTrue(self.c.mul(1,2,3,40)==240)

    def test_div(self):
        self.assertTrue(self.c.div(100,10,2)==5)

    def tearDown(self):
        print ("test completed!")

    def tearDown(self):
        print ("tearDown completed")

if __name__ == '__main__':
    unittest.main()

unittest_suite.py

#encoding=utf-8

import random
import unittest
from TestCalc import TestCalcFunctions

class TestSequenceFunctions(unittest.TestCase):
    def setUp(self):
        self.seq = list(range(10))

    def tearDown(self):
        pass

    def test_choice(self):
        # 从序列seq中随机选取一个元素
        element = random.choice(self.seq)
        # 验证随机元素确实属于列表中
        self.assertTrue(element in self.seq)

    def test_sample(self):
        # 验证执行的语句是否抛出了异常
        with self.assertRaises(ValueError):
            random.sample(self.seq, 20)

        for element in random.sample(self.seq, 5):
            self.assertTrue(element in self.seq)

class TestDictValueFormatFunctions(unittest.TestCase):
    def setUp(self):
        self.seq = list(range(10))

    def tearDown(self):
        pass

    def test_shuffle(self):
        # 随机打乱原seq的顺序
        random.shuffle(self.seq)
        self.seq.sort()
        self.assertEqual(self.seq, list(range(10)))
        # 验证执行函数时抛出了TypeError异常
        self.assertRaises(TypeError, random.shuffle, (1, 2, 3))


if __name__ == '__main__':
    # 根据给定的测试类,获取其中所有以“test”开头的测试方法,并返回一个测试套件
    suite1 = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)
    suite2 = unittest.TestLoader().loadTestsFromTestCase(TestDictValueFormatFunctions)
    suite3 = unittest.TestLoader().loadTestsFromTestCase(TestCalcFunctions)


# 将多个测试类加载到测试套件中
#通过调整suit2和suite1的顺序,可以设定执行顺序
suite = unittest.TestSuite([suite2, suite1,suite3])      
# 设置verbosity = 2,可以打印出更详细的执行信息
    unittest.TextTestRunner(verbosity = 2).run(suite)

代码示例6:unittest中的断言方法

#encoding=utf-8

import unittest,random

# 被测试类
class MyClass(object):

    @classmethod
    def sum(self, a, b):
        return a + b

    @classmethod
    def div(self, a, b):
        return a / b

    @classmethod
    def retrun_None(self):
        return None

# 单元测试类
class MyTest(unittest.TestCase):
    # assertEqual()方法实例
    def test_assertEqual(self):
        # 断言两数之和的结果
        try:
            a, b = 1, 2
            sum = 3
            self.assertEqual(a + b, sum, '断言失败,%s + %s != %s' %(a, b, sum))
        except AssertionError as e:
            print (e)

    # assertNotEqual()方法实例
    def test_assertNotEqual(self):
        # 断言两数之差的结果
        try:
            a, b = 5, 2
            res = 1
            self.assertNotEqual(a - b, res, '断言失败,%s - %s != %s' %(a, b, res))
        except AssertionError as e:
            print (e)

    # assertTrue()方法实例
    def test_assertTrue(self):
        # 断言表达式的为真
        try:
            self.assertTrue(1 == 1, "表达式为假")
        except AssertionError as e:
            print (e)

    # assertFalse()方法实例
    def test_assertFalse(self):
        # 断言表达式为假
        try:
            self.assertFalse(3 == 2, "表达式为真")
        except AssertionError as e:
            print (e)

    # assertIs()方法实例
    def test_assertIs(self):
        # 断言两变量类型属于同一对象
        try:
            a = 12
            b = a
            self.assertIs(a, b, "%s与%s不属于同一对象" %(a, b))
        except AssertionError as e:
            print (e)

    # test_assertIsNot()方法实例
    def test_assertIsNot(self):
        # 断言两变量类型不属于同一对象
        try:
            a = 12
            b = "test"
            self.assertIsNot(a, b, "%s与%s属于同一对象" %(a, b))
        except AssertionError as  e:
            print (e)

    # assertIsNone()方法实例
    def test_assertIsNone(self):
        # 断言表达式结果为None
        try:
            result = MyClass.retrun_None()
            self.assertIsNone(result, "not is None")
        except AssertionError as e:
            print (e)

    # assertIsNotNone()方法实例
    def test_assertIsNotNone(self):
        # 断言表达式结果不为None
        try:
            result = MyClass.sum(2, 5)
            self.assertIsNotNone(result, "is None")
        except AssertionError as e:
            print (e)

    # assertIn()方法实例
    def test_assertIn(self):
        # 断言对象A是否包含在对象B中
        try:
            strA = "this is a test"
            strB = "is"
            self.assertIn(strB, strA, "%s不包含在%s中" %(strB, strA))
        except AssertionError as e:
            print (e)

    # assertNotIn()方法实例
    def test_assertNotIn(self):
        # 断言对象A不包含在对象B中
        try:
            strA = "this is a test"
            strB = "Selenium"
            self.assertNotIn(strB, strA, "%s包含在%s中" %(strB, strA))
        except AssertionError as e:
            print (e)

    # assertIsInstance()方法实例
    def test_assertIsInstance(self):
        # 测试对象A的类型是否值指定的类型
        try:
            x = MyClass
            y = object
            self.assertIsInstance(x, y, "%s的类型不是%s" %(x, y))
        except AssertionError as e:
            print (e)

    # assertNotIsInstance()方法实例
    def test_assertNotIsInstance(self):
        # 测试对象A的类型不是指定的类型
        try:
            a = 123
            b = str
            self.assertNotIsInstance(a, b, "%s的类型是%s" %(a, b))
        except AssertionError as e:
            print (e)



    # assertRaises()方法实例
    def test_assertRaises(self):

        # 测试抛出的指定的异常类型
        # assertRaises(exception)
        with self.assertRaises(ValueError) as cm:
            random.sample([1,2,3,4,5], 6)

        # 打印详细的异常信息
        #print ("===", cm.exception)
        # assertRaises(exception, callable, *args, **kwds)
        try:
            self.assertRaises(ZeroDivisionError, MyClass.div, 3, 0)
        except ZeroDivisionError as e:
            print (e)

    # assertRaisesRegexp()方法实例
    def test_assertRaisesRegexp(self):
        # 测试抛出的指定异常类型,并用正则表达式具体验证
        # assertRaisesRegexp(exception, regexp)
        with self.assertRaisesRegexp(ValueError, 'literal') as ar:
            int("xyz")
        # 打印详细的异常信息
        #print (ar.exception)
        # 打印正则表达式
        #print( "re:",ar.expected_regexp)
        # assertRaisesRegexp(exception, regexp, callable, *args, **kwds)
        try:
            self.assertRaisesRegexp(ValueError, "invalid literal for.*XYZ'$", int, 'XYZ')
        except AssertionError as e:
            print (e)

if __name__ == '__main__':
    # 执行单元测试
    unittest.main()


说明:

assertEqual(first, second, msg=None):如果两个对象不相等,返回False,第三个参数个msg是遇到异常后自定义输出信息

常用方法:

assertEqual(first, second, msg=None):判断两个对象相等,first == second
assertNotEqual(first, second, msg=None):判断两个对象不相等,first != second
assertIn(member, container, msg=None):判断字符串是否包含,member in container
assertNotIn(member, container, msg=None):判断字符串不包含,member not in container
assertTrue(expr, msg=None):判断是否为真,expr is True
assertFalse(expr, msg=None):判断是否为假,expr is False
assertIsNone(self, obj, msg=None):判断是否为None, obj is None
assertIsNotNone(self, obj, msg=None):判断不为None, obj is not  None
 

代码示例7:生成HTMLTestRunner测试报告
HTMLTestRunner用来生成HTML测试报告,是对python标准库unittest的一个扩展,使用前需要下载HTMLTestRunner.py文件,下载成功后放到…\python\Lib目录下:

python2下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html 
python3下载地址:http://pan.baidu.com/s/1dEZQ0pz

代码:

# coding=utf-8
import unittest
import HTMLTestRunner
import math

class Calc(object):

def add(self, x, y, *d):
# 加法计算
result = x + y
for i in d:
result += i
return result

def sub(self, x, y, *d):
# 减法计算
result = x - y
for i in d:
result -= i
return result

class SuiteTestCalc(unittest.TestCase):
def setUp(self):
self.c = Calc()

@unittest.skip("skipping")
def test_Sub(self):
print ("sub")
self.assertEqual(self.c.sub(100, 34, 6), 61, u'求差结果错误!')

def testAdd(self):
print ("add")
self.assertEqual(self.c.add(1, 32, 56), 89, u'求和结果错误!')


class SuiteTestPow(unittest.TestCase):
def setUp(self):
self.seq = range(10)

# @unittest.skipIf()
def test_Pow(self):
print ("Pow")
self.assertEqual(pow(6, 3), 2161, u'求幂结果错误!')

def test_hasattr(self):
print ("hasattr")
# 检测math模块是否存在pow属性
self.assertTrue(hasattr(math, 'pow1'), u"检测的属性不存在!")

if __name__ == "__main__":
suite1 = unittest.TestLoader().loadTestsFromTestCase(SuiteTestCalc)
suite2 = unittest.TestLoader().loadTestsFromTestCase(SuiteTestPow)
suite = unittest.TestSuite([suite1, suite2])
#unittest.TextTestRunner(verbosity=2).run(suite)
filename = "test.html" # 定义个报告存放路径,支持相对路径。
# 以二进制方式打开文件,准备写
fp = open(filename, 'wb')
# 使用HTMLTestRunner配置参数,输出报告路径、报告标题、描述,均可以配
runner = HTMLTestRunner.HTMLTestRunner(stream = fp,
title = u'测试报告', description = u'测试报告内容')
# 运行测试集合
runner.run(suite)

说明:

import HTMLTestRunner:将模块导入
HTMLTestRunner.HTMLTestRunner(stream = fp,title = u'测试报告', description = u'测试报告内容'):使用HTMLTestRunner配置参数,输出报告路径、报告标题、描述
runner.run(suite):运行测试集合
 

代码示例8:运行当前目录下所有的测试模块
以文本方式运行:

以文本方式运行:


生成html报告:

#encoding=utf-8
import unittest
import HTMLTestRunner

if __name__ == '__main__' :
# 加载当前目录下所有有效的测试模块(以test开头的文件),“.”表示当前目录
testSuite = unittest.TestLoader().discover('.')
filename = "test.html" # 定义个报告存放路径,支持相对路径。
# 以二进制方式打开文件,准备写
fp = open(filename, 'wb')
# 使用HTMLTestRunner配置参数,输出报告路径、报告标题、描述,均可以配
runner = HTMLTestRunner.HTMLTestRunner(stream = fp,
title = 'Report_title', description = 'Report_description')
# 运行测试集合
runner.run(testSuite)

🎁更多干货


 

完整版文档下载方式:

这些资料,对于从事【软件测试】等相关工作的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享。

在评论区和我互动交流或者私❤我【软件测试学习】领取即可,拿走不谢。


如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “👍点赞” “✍️评论” “💙收藏” 一键三连哦!

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录算法学习心得 40 | 139. 单词拆分、背包问题总结...

一、单词拆分 链接:力扣 描述:给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。 思路如下&…

【Linux | Shell】Linux 安全系统 —— 用户、组、文件权限 - 阅读笔记

目录 一、Linux 的安全性1.1 /etc/passwd 文件1.2 /etc/shadow 文件1.3 添加新用户 —— useradd1.4 删除用户 —— userdel1.5 修改用户 —— usermod、passwd、chpasswd 二、使用 Linux 组2.1 /etc/group 文件2.2 创建新组 —— groupadd2.3 修改组 —— groupmod 三、理解文…

Jenkins可持续集成Python自动化脚本

目录 前言 一、Jenkins搭建在Windows上 二、Jenkins搭建在Linux上 🎁更多干货 完整版文档下载方式: 本文讲解Jenkins如何每次定时的从SVN服务器上拉取最新的代码并执行本地库里的脚本 前言 1、本地代码库目录F:\5i5jautest内有测试文件all_tests.…

Attention,注意力机制

在机器视觉任务中,每一张图片都有重点区域,而非每一个像素对模型理解图片都同等重要。 在自然语言处理任务中,每一段文字都有重点词语,而非每一个字对模型理解语句都同等重要。 如此,在神经网络模型中引入注意力&#…

做投票小程序线上投票制作制作图片投票链接如何做投票小程序

小程序投票活动如何做?很多企业在运营当中,都会通过投票活动来进行推广,从而达到吸粉、增加用户粘度等效果。而此类投票活动,通过小程序就可以实现,操作简单。 我们现在要以“时尚新态度”为主题进行一次投票活动&…

WiFi 时钟+本地温度

[ WiFi 时钟 ] [ WiFi 天气时钟 ] [ WiFi 时钟本地温度 ] 夏天到了,显示器上放一个时钟,顺便实时测量本地室温,看看空调工作是否正常也算是个实用制作。 用到零件共 4 个: 400孔面包板 ( 大号…

docker配置nacos

1 拉取nacos镜像并启动 docker pull nacos/nacos-server 2 启动nacos命令 docker run -d --name nacos -p 8848:8848 -e PREFER_HOST_MODEhostname -e MODEstandalone nacos/nacos-server 至此,我们已经可以使用nacos服务,UI地址:http://:8848/nacos …

计算机体系结构基础知识介绍之高级分支预测(二)

一、标记混合预测器 分支预测的目的是根据历史信息来预测分支指令的跳转方向和目标地址,从而提高流水线的效率。不同的分支预测方法有不同的优缺点,因此有人提出了一种将多种预测方法结合起来的方案,混合预测器。这种方案可以根据不同的分支…

适合Docker的场景以及不适合的场景

文章来自:When to use and when not to use Docker和7 Cases When You Should Not Use Docker,以及互联网网上的一些零散内容。这篇文章只是基于我自己的理解,进行简单的概述。 适合的场景 你的团队不是一成不变的。 当有新的成员加入&#…

写作技巧:如何让你的文章充满生命力?

在写作中,让文章充满生命力是很重要的一点。如果一篇文章缺乏生命力,那么读者很难被吸引,也很难从中获得任何收获。那么,如何让你的文章充满生命力呢? 以下是几个建议: 1.真实感情:写作的时候要…

Django_视图中的request对象详解(八)

目录 Request 属性 方法 QueryDict 源码等资料获取方法 Request 当URLconf文件匹配到用户输入的路径后,会调用对应的view函数,并创建一个包含请求元数据的 HttpRequest 对象 传入该函数的第一个参数,常用request表示。 HttpRequest实…

为什么要学习使用C++软件常用分析工具?学会这些工具都有哪些好处?

目录 1、为什么要学习使用C软件常用分析工具? 2、C常用分析工具有哪些?都能处理哪些具体的问题? 2.1、SPY 2.2、Dependency Walker 2.3、GDIView 2.4、Process Explorer 2.5、Process Monitor 2.6、调试器Windbg 2.7、反汇编工具IDA…

Android 13 startActivity报错ActivityNotFoundException

最近遇到一个问题,就是在google pixel 4(android 13)的手机上startactivity的时候报错activity找不到,其他非13的是好的,这里对问题进行记录: 查阅google官方的文档,有这么一段话, …

前端mock数据的几种方式

前端mock数据的几种方式 前端在开发具体需求前,后端往往只提供接口文档,对于前端来说,最简单的方式就是把想要的数据写死在代码里进行开发,但这样的坏处就是和后端联调前还需要再把写死的数据从代码里删除,最好的方式…

开发中易犯错的事务问题

1.不指定rollbackFor 使用spring的声明式事务(即Transactional注解)时,如果不指定rollbackFor,那么当程序发生Error时,事务将不会回滚!!!显然这将导致数据不一致! 如下述…

spring8-getBean()方法使用

;:getBean使用,要传数据,一个是字符串, 就是文件里的UserService 而这里的UserService就是我们配置文件的id:,第一个API 第二个API可以传入一个字节码类型。 如果某一个容器存在多个&#xff…

windows系统如何部署nacos

1.安装nacos 去nacos github下载nacos最新稳定版本,我用的是nacos-server-2.2.3.zip,下载后解压 2.创建数据库 启动mysql,创建数据库nacos,数据库名字是从conf/application.properties文件获得的 把db这三行取消注释&#xff…

【Hello mysql】 mysql的约束

Mysql专栏:Mysql 本篇博客简介:介绍mysql的约束 mysql的约束 表的约束空属性默认值列描述zerofill主键自增长唯一键外键总结 表的约束 为什么要有约束? 我们在收集一些数据的时候会要求该数据必须存在 比如说像是国家在登记公民信息的时候身…

实验二 常用网络命令

实验目的 了解常用网络命令及其使用方法。通过网络命令了解网络状态,并利用网络命令对网络进行简单的操作。 实验原理 1. 通过 ping 命令检测网络故障 (1)命令格式: ping [-t] [-a] [-n count] [-l size] [-f] [-i TTL] [-v T…

conic-gradient

The conic-gradient() CSS function creates an image consisting of a gradient with color transitions rotated around a center point conic-gradient方法创建了一个由围绕中心点旋转渐变组成的图片 background: conic-gradient( red 6deg, orange 6deg 18deg, yellow…