Python unittest 学习

Python unittest 学习


[[toc]]

前言

由于目前项目需要做接口测试,故特意去学习了Python中的unittest测试框架,以下是个人的一些学习经验,如有错误之处,请不吝指出。

一、什么是unittest

unittest翻译过来就是“单元测试”,单元测试负责对最小的软件设计单元(模块)进行验证。而引用python官方文档

unittest是python自带的单元测试框架,有时候又被称为”PyUnit”,是 python版本的JUint实现。该框架的作者是 Kent Beck和Erich Gamma。

二、基本概念

在开始运用unittest框架进行测试前,我们需要先学习unittest框架中4个重要的概念:test fixture、test case、test suite、test runner。
官方文档

1. test fixture :表示执行一个或多个测试所需的准备, 以及任何关联的清理操作。例如, 这可能涉及创建临时或代理数据库、目录或启动服务器进程。
2. test case :测试用例是最小的测试单元。它检查特定的输入集的响应。单元测试提供了一个基类测试用例, 可用于创建新的测试用例。
3. test suite :测试套件是测试用例、测试套件或两者的集合。它用于聚合应一起执行的测试。
4. test runner :测试运行程序是协调测试执行并向用户提供结果的组件。运行程序可以使用图形界面、文本界面或返回特殊值来指示执行测试的结果。

而我们可以这样简单的去理解这4个概念:

  • test fixture:是初始化和清理测试数据及环境,通过覆盖TestCase的setUp()和tearDown()方法来实现
  • test case:是测试用例
  • test suite:是用例集合,即测试套件,通过addTest加载TestCase到TestSuite中,从而返回一个TestSuite实例。
  • test runner:的作用是运行用例并返回结果,通过TextTestRunner类提供的run()方法来执行test suite/test case。

三、基本用法

在理解了4个基本概念(test fixture、test case、test suite、test runner)之后,我们通过以下的“加法”例子学习:
首先建立一个加法类: 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



接着写test.py去测试“加法类:calculator.py”:

from testpro.calculator import Count
import unittest


class TestAdd(unittest.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__':
    # 构造测试集
     suite = unittest.TestSuite()
     suite.addTest(TestAdd('test_add'))

     # 执行测试集合
     runner = unittest.TextTestRunner()
     runner.run(suite)

test.py 中,首先引入unittest模块,创建TestAdd类继承unittest的TestCase类。
setUp()方法用于测试用例执行前的初始化工作,而这里用来打印“test start”信息。
tearDow()方法与setUp()相对应,用于测试用例之后的工作,这里打印“test end”信息。
asserEqual()方法对add()的返回值进行断言,判断两者是否相等,assertEqual()方法由TestCase类继承而来。
TestSuite()类来创建测试套件,通过它提供的addTest()方法来添加测试用例test_add()。
TextTestRunner()类的run()方法来运行suite所组装的测试用例。

四、执行用例的方法

目前学习中,发现有3种执行项目中测试用例的方法(ps:应该还有很多方法):

  • main() :unittest提供的全局方法,可以方便地将一个单元测试模块变成可以直接运行的测试脚本。main()方法使用TestLoader类来搜索所有包含在该模块中以“test”命名开头的测试方法,并自动执行它们。
  • run() :是unittest的TextTestRunner()类的方法,用来运行suite套件中的测试用例集。
  • discover() :TestLoader类中提供的方法,用来自动识别项目中的测试用例

例子:

from testpro.calculator import Count
import unittest


class TestAdd(unittest.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__':
    # main()方法
     unittest.main()

    # run()方法
    # 构造测试集
    #suite = unittest.TestSuite()
    # suite.addTest(TestAdd('test_add'))
     
     # 执行测试集合
     #runner = unittest.TextTestRunner()
     #runner.run(suite)

# discover方法
#test_dir = './test_case'
#discover = unittest.defaultTestLoader.discover(test_dir, pattern='test*.py')

#if __name__ == '__main__':
#    runner = unittest.TextTestRunner()
#    runner.run(discover)

五、断言的方法

在执行用例的过程中,最终用例是否执行通过,是通过判断测试得到的实际结果与预期结果是否相等决定的。unittest框架的TestCase类提供下面这些方法用于测试结果的判断。
常用的:

  • assertEqual(first, second, msg=None):断言第一个参数和第二个参数是否相等,如果不相等则测试失败。msg为可选参数,用于定义测试时打印想信息。
  • assertTure(expr, msg=None):判断测试表达式是true或false
  • assertIN(first, second, msg=None):断言第一个参数是否在第二个参数中,反过来讲,第二个参数是否包含在第一个参数。
方法 检查点
assertEqual(a, b) a == b
assertNotEqual(a, b) a != b
assertTrue(x) bool(x) is True
assertFalse(x) bool(x) is False
assertIs(a, b) a is b
assertIsNot(a, b) a is not b
assertIsNone(x) x is None
assertIsNotNone(x) x is not None
assertIn(a, b) a in b
assertNotIn(a, b) a not in b

官方文档

六、用例失败如何重跑

目前在unittest中并没有可以用来失败用例重跑的方法或插件,只能自己去封装一个方法。但通过资料查找,发现python下另一个测试框架pytest中就有2个方法可以进行失败用例重跑的,分别是flaky和rerunfailures。目前没有去深入学习pytest框架,就不详写了。

七、知识点补充

1. 测试用例分类
通过前面对unittest单元测试框架的学习,我们来用它运行web自动化测试脚本。在 开始之前,需要规划好测试目录,因为一旦测试用例多起来之后,后期维护就很麻烦。所以用例需要按照所测试的功能进行拆分,分散到不同的测试文件中。但通过addTest()添加/删除测试用例变得很麻烦,所以我们要用TestLoder类中提供的discover()方法解决:

discover(start_dir, pattern='test*.py, top_level_dir=None)

  • start_dir:要测试的模块名称或测试用例目录。
  • pattern='test.py':表示用例文件名的匹配原则。以“test”开头的 ‘,py’类型的文件,星号“”表示任意多个字符。
  • top_level_dir=None:测试模块的顶层目录,如果没有顶层目录,默认为None。

让unittest框架查找到子目录中的测试文件,需要在每个子目录下放一个“\__init__.py”文件,文件可以为空。


2.if _name_ == '_main_'语句说明
if代表此句子为条件语句。_name_作为模块的内置属性,即是.py文件的调用方式。如果_name_ 等于 '_main_'就表示可以直接调用。


3.用例执行的顺序
unittest框架默认根据ASCII码的顺序加载测试用例的,数字与字母的顺序为:“0-9”,“A-Z”,“a-z”。而想要用例按顺序执行,需要通过TestSuite类的addTest()方法按照一定的顺序来加载。


4.跳过测试和预期失败
在运行测试时,有时需要直接跳过某些测试用例,或者当用例符合某个条件跳过测试,又或者直接将测试用例设置为失败。unittest提供了实现这些需求的装饰器

  • unittest.skip(reason):无条件跳过装饰的测试,说明跳过的原因
  • unittest.skipIf(condition, reason):跳过装饰的测试,如果条件为真
  • unittest.skipUnless(condition, reason):跳过装饰的测试,除非条件为真
  • unittest.expectedFailure():测试标记为失败。不管执行结果是否失败,同意标记失败。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,919评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,567评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,316评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,294评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,318评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,245评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,120评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,964评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,376评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,592评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,764评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,460评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,070评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,697评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,846评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,819评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,665评论 2 354

推荐阅读更多精彩内容