• 手把手带你学python自动化测试(九)——Python 的 unittest 框架


    Unittest 框架介绍

    Unittest 是 python 的单元测试框架,原名为 PyUnit,由 java 的 junit 演化而来。

    Unittest 提供了 test case、test suites、test fixtures、test runnet。

    Test case :通过继承 TestCase 类,实现创建 test 戒 tests

    Test suite:测试套,通常把一组相关的测试称为一个测试套,通过测试套件,将服务 于同一个测试目的戒同一运行环境下的一系列测试用例有机的组合起来。测试套件是 按照测试计划所定义的各个阶段的测试目标决定的,即先有测试计划,后面才有测试 套件。

    test fixtures:setup + test case + teardown 的组合

    Unittest 结构:在这里插入图片描述

    Unittest 框架详解

    测试用例

    在 unittest 中没有明确究竟 test 的 class 是测试用例,还是 class 中的 test 开头的方法 是测试用例,在下面的案例中,我们将 test 开头的方法作为测试用例来执行。

    先看一个简单的案例

    import unittest 
    在使用 unittest 框架时,需要先导入 unittest 
    class login_test(unittest.TestCase): 
    创建一个测试类,该类继承 unittest 的 TestCase。 
     def setUp(self): 
    Setup 是测试执行之前的操作,会在用例执行之前先执行这里的 
    内容,通常用来初始化环境 
     self.testa=1039 
     self.testb=10 
     def test_login(self): 
    要执行的测试 1 
     self.assertTrue(self.testa == self.testb) 
     def test_login2(self): 
    要执行的测试 2 
     try: 
     self.testc=30 
     self.assertTrue(self.testa == self.testc) 
     except AssertionError: 
     self.fail("test is false") 
     def tearDown(self): 
    执行结束之后的操作,通常用来执行还原测试环境的操作 
     print('Test Runner End') 
    if __name__ == '__main__': 
    unittest.main() 
    调用 unittest 的开始执行 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在使用 unittest 前,需要先导入 unittest 的包,在这个包中包含了 unittest 提供 的各种类,如:TestCase、TestSuite、TextTestRunner、TestLoader、main 等等。

    创建一个 login_test 的 class,用来测试,该类继承 TestCase,从而能够使用 TestCase 中的方法。

    Setup 方法是 TestCase 中的方法,这里是重写 TestCase 的 setup 方法,该方 法用来做测试执行前的操作,比如构建测试数据,打开浏览器、链接数据库等操作。 下面的 tearDown 方法相同,区别在不该方法用于执行测试执行结束后的操作,比如关 闭浏览器,释放数据库连接操作。

    中间以 test 开头的方法,则会被弼做测试用例来执行,运行该脚本时,unittest 会自劢加载这些 test 开头的方法,来执行测试。

    Unitest.main 是调用 unittest 的执行方法,这里是测试执行的入口。

    测试套

    测试套又称测试集,也叨测试套件,通常是一组测试用例的集合,通过 suite 可 以执行一组测试用例。下面的代码是针对 LMD 的登陆测试,如果登陆成功,则获叏他40 的 title,判断 title 是否不预期结果一致,如果一致,则测试成功,否则用例执行失败。 这个案例通过 suite 实现的。代码如下:

    #coding=utf-8
    __author__ = 'Administrator'
    import unittest
    from selenium import webdriver
    import HTMLTestRunner
    from selenium.webdriver.support import expected_conditions
    class login_test2(unittest.TestCase):
     def setUp(self):
     self.driver = webdriver.Firefox()
     self.driver.maximize_window()
     def test_login(self):
     driver = self.driver
     driver.get('http://www.chuangyijia.com/login')
    driver.find_element_by_id('email').send_keys('810155067
    @qq.com')
     driver.find_element_by_id('pwd').send_keys('a654321')
     driver.find_element_by_css_selector('#submit').click()
     test=expected_conditions.title_is(u'创意家,登录')
     self.assertTrue(test(driver))
     def tearDown(self): 
    self.driver.quit()
    if __name__ == '__main__':
     
    suite=unittest.TestLoader().loadTestsFromTestCase(login_test2)
     unittest.TextTestRunner().run(suite)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    这段代码中,上面的内容和乊前没有上面差别,主要在 if name==’main’的内容,这句话的意思为“Make a script both importable and executable”,解释过来就是让你写的脚本模块既可以导入到别的模块中用,另外 该模块自己也可执行。试代码的时候,在”if name == ‘main’“中加入一些 我们的调试代码,我们可以让外部模块调用的时候丌执行我们的调试代码,但是如果 我们想排查问题的时候,直接执行该模块文件,调试代码能够正常运行!

    Unittest.TestLoader:源代码解释为“This class is responsible for loading tests according to various criteria and returning them wrapped in a TestSuite”

    意思可以通过该类完成测试用例的加载,将用例加载到 siuter 中,但是需要调 用该类的 loadTestFromTestCase 方法来加载用例,该方法接收参数为测试类,也就是 我们上面定义的 login_test2 的类名。这句代码就会将该类中以 test 开头的方法加载到 suiter 中。Suiter 变量用来接收加载后的结果。

    通过 unittest 调用他的 TextTestRunner 类中的 run 方法来执行测试,run 方法 需要将 suiter 作为参数传入。TextTestRunner 是以文本形式显示测试结果,如果测试 失败,会显示失败的测试名称,并统计测试的结果。run 方法是运行传入的 case 戒 suiter。

    断言

    在编程中,通常会做一些假设,使用断言,去判断一个代码处理的结果是否和 自己的预期相符,如果符合则为 True,否则为 false。在测试中,我们也会有这样的需 求,执行一个测试,给一个预期结果,来断言实际结果不预期结果是否符合,丌符合 则测试失败,符合则执行成功。 在 unittest 的 TestCase 中给我们提供了徆丰富的断言操作,下面罗列出了常用 的一些断言。

    assertTrue:检查表达式返回值是否为真 True,返回值类型为布尔类型。

    assertFalse:不上面相反,检查表达式返回是否为假 False,布尔类型。

    assertEqual(arg1, arg2, msg=None):验证 arg1 和 arg2 是否相等。

    assertNotEqual(arg1, arg2, msg=None):验证 arg1 和 arg2 是否丌相等。

    assertIs(arg1, arg2, msg=None):验证 arg1 和 arg2 是否为同一个对象。

    assertIsNot(arg1, arg2, msg=None):验证 arg1 和 arg2 是否丌为同一个对象。

    assertIsNone(expr, msg=None):验证 expr 是否为 none,是则返回 True。

    ssertIsNotNone(expr, msg=None):验证 expr 是否丌为 none,是则返回 True。

    assertIn(arg1, arg2, msg=None):验证 arg1 是否在 arg2 中,是则 True

    assertNotIn(arg1, arg2, msg=None):验证 arg1 丌在 arg2 的中,是则 fail42

    示例:

    #coding=utf-8
    __author__ = 'Administrator'
    import unittest
    class Test_Asser(unittest.TestCase):
     def test_assertTrue(self):
     self.assertTrue(5>4)
    5>4 则返回 True,否则返回 False
     def test_assertFalse(self):
     self.assertFalse(5<4)
    表达式成立则返回 False,否则返回 True
     def test_assertEqual(self):
     self.assertEqual(u"中国",u"中国")
    两个字符串相等,则返回 True,否则返回 False
     def test_assertNotEqual(self):
     self.assertNotEqul(u"中国 1",u"中国 2")
    两个字符串不相等,返回 True,否则返回 false
     def test_assertIs(self):
     a=10
     a=20
     self.assertIs(a,a)
    a 是一个变量,下面的是对 a 重新赋值,所以依然是一个对象,
    所以此处返回 True,否则返回 false。
     def test_assertIsNot(self):
     a=10
     b=20
     self.assertIsNot(a,b)
    a 和 b 是两个变量,不属于同一个对象 ,所以此处返回 True,
    否则返回 False
     def test_assertIsNone(self):
     a=None
     self.assertIsNone(a)
    None 在 python 中是一个特殊的空值,即表示空值,也可以表
    示为空对象。在这里给 a 赋值为 None,那么 a 就是一个空对象,此处
    返回 True,否则返回 false
     def test_assertIsNotNone(self):
    43
     c=10
     self.assertIsNotNone(c)
    与上面相反,c 是一个有值的对象,这里判断 c 是不是不为
    None,是则返回 True,否则返回 False。
     def test_assertIsIn(self):
     text="abcdef"
     t='c'
     self.assertIn(t,text)
    判断 t 的值是否在 text 中,如果在则返回 True,否则返回
    False。
     def test_assertIsNotIn(self):
     text="abcdef"
     self.assertNotIn('h',text)
    判断字符 h 是否不在 text 中,不在则返回 True,否则返回
    false.
    if __name__ == '__main__':
     unittest.main()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    弼然在 unittest 中丌叧是这些断言,还有其他断言,后续会慢慢加入。

    测试批量执行

    下面做两个测试的案例,先创建目弽结构:

    主目弽为:Lmd_auto_test

    次目弽:Lmd_auto_test\test_case

    在 test_case 目弽中有 login_auto.py 和 Release_Creative.py 两个脚本。

    将下面的代码保存为 login_auto.py

    #coding=utf-8
    __author__ = 'Administrator'
    from selenium import webdriver
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions
    import time
    import unittest
    class login_test_case(unittest.TestCase):
     def setUp(self):
     self.driver = webdriver.Firefox()
     self.driver.maximize_window()
     self.driver.get('http://www.chuangyijia.com/login')
     def tearDown(self):
     self.driver.quit()
     def test_login(self):
     
    self.driver.find_element_by_id('email').send_keys('810155067@
    qq.com')
     
    self.driver.find_element_by_id('pwd').send_keys('a654321')
     self.driver.find_element_by_id('submit').click()
     #self.driver.implicitly_wait(5)
     time.sleep(3)
     
    WebDriverWait(self.driver,30).until(expected_conditions.visib
    ility_of_element_located((By.CSS_SELECTOR,'.logo')))
     print self.driver.title
     is_title = expected_conditions.title_is(u'首页-创意家')
     self.assertTrue(is_title(self.driver))
    if __name__ == '__main__':
     unittest.main()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    下面的文件保存为 Release_Creative.py

    #coding=utf-8
    __author__ = 'Administrator'
    from selenium import webdriver
    from selenium.webdriver.support import expected_conditions
    from selenium.webdriver.common.action_chains import 
    ActionChains
    44
    import unittest
    import sys
    import os,time
    class release_creat(unittest.TestCase):
     def setUp(self):
     self.driver = webdriver.Firefox()
     self.driver.maximize_window()
     self.driver.get('http://www.chuangyijia.com/login')
     
    self.driver.find_element_by_id('email').send_keys('810155067@
    qq.com')
     
    self.driver.find_element_by_id('pwd').send_keys('a654321')
     self.driver.find_element_by_id('submit').click()
     time.sleep(3)
     #is_title = expected_conditions.title_is(u'首页-创意家')
     #self.assertTrue(is_title(self.driver))
     def test_release(self):
     self.driver.find_element_by_css_selector('.menu > 
    ul:nth-child(1) > li:nth-child(1) > a:nth-child(1)').click()
     self.driver.find_element_by_css_selector('.c01 > a:nthchild(1)').click()
     
    self.driver.find_element_by_name('mobile').send_keys('1943235
    923')
     
    self.driver.find_element_by_css_selector('.idea_name').send_k
    eys(u"发布中文创意")
     self.driver.find_element_by_id('province').click()
     
    self.driver.find_element_by_xpath('//option[contains(text(),"
    江苏")]').click()
     self.driver.find_element_by_id('city').click()
     
    self.driver.find_element_by_xpath('//option[contains(text(),"
    南京")]').click()
     text=u"预售管理,后台管理员可以修改时间,并且只能修改为
    当月的日期,不能修改年月"
    45
     self.driver.find_element_by_css_selector('#pForm > 
    table:nth-child(11) > tbody:nth-child(1) > tr:nth-child(1) > 
    td:nth-child(1) > table:nth-child(1) > tbody:nth-child(1) > 
    tr:nth-child(6) > td:nth-child(2) > textarea:nthchild(1)').send_keys(text)
     self.driver.find_element_by_css_selector('#pForm > 
    table:nth-child(11) > tbody:nth-child(1) > tr:nth-child(1) > 
    td:nth-child(1) > table:nth-child(1) > tbody:nth-child(1) > 
    tr:nth-child(7) > td:nth-child(2) > textarea:nthchild(1)').send_keys(u"没有问题。。。。")
     self.driver.find_element_by_css_selector('#pForm > 
    table:nth-child(11) > tbody:nth-child(1) > tr:nth-child(1) > 
    td:nth-child(1) > table:nth-child(1) > tbody:nth-child(1) > 
    tr:nth-child(8) > td:nth-child(2) > textarea:nthchild(1)').send_keys(u"不需要解决")
     
    self.driver.find_element_by_name('support_end_date').send_key
    s('2017-8-18')
     time.sleep(2)
     
    self.driver.find_element_by_css_selector('.c_btn').click()
     
    self.driver.find_element_by_css_selector('.c_btn').click()
     os.system("H:\\pydj\\Lmd_auto_test\\testjpg.exe")
     time.sleep(2)
     put2 = 
    self.driver.find_element_by_css_selector('#upimg_1')
     put1 = 
    self.driver.find_element_by_css_selector('.cy_pic > ul:nthchild(1) > li:nth-child(1) > input:nth-child(3)')
     
    ActionChains(self.driver).move_to_element(put2).perform()
     self.driver.find_element_by_css_selector('.cy_pic > 
    ul:nth-child(1) > li:nth-child(1) > input:nthchild(3)').click()
     os.system("H:\\pydj\\Lmd_auto_test\\testjpg.exe")
     #self.driver.find_element_by_css_selector('.cy_pic > 
    46
    47
    ul:nth-child(1) > li:nth-child(2) > input:nthchild(3)').click()
     #os.system("H:\\pydj\\Lmd_auto_test\\testjpg.exe")
     self.driver.find_element_by_id('saveBtn').click()
     time.sleep(2)
     is_exist = 
    self.driver.find_element_by_css_selector('div.item:nthchild(1) > div:nth-child(2) > a:nth-child(1)')
     Creat_Name = is_exist.text
     self.assertEqual(Creat_Name,u"发布中文创意")
     #self.assertTrue(is_exist)
     if __name__ == '__main__':
     unittest.main()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90

    上面的两个文件,一个是测试登陆功能的用例,另一个是测试创意収布的用例,这里 对成功和失败叧做了简单的判断,例如登陆,叧判断登陆后,title 是否为登陆成功的 title,是则执行通过,否则执行失败。创意収布时,判断提交后,该创意是否在収布的 列表中,并在第一个,如果是,则执行成功,否则执行失败。

    在 test_case 的目弽中创建__init__.py 文件,文件内容如下:

    #coding=utf-8
    __author__ = 'Administrator'
    import login_auto
    import Release_Creative
    
    • 1
    • 2
    • 3
    • 4

    在 Lmd_auto_test 目弽下创建 run_test_case.py 文件,文件主要用来实现执行 test_case 目弽下的测试脚本。文件内容如下:

    #coding=utf-8
    __author__ = 'Administrator'
    # import test_case
    import unittest
    from test_case import login_auto,Release_Creative
    suiter = unittest.TestSuite()
    suiter.addTest(unittest.makeSuite(login_auto.login_test_case))
    suiter.addTest(unittest.makeSuite(Release_Creative.release_cr
    48
    eat))
    unittest.TextTestRunner().run(suiter)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    最后感谢每一个认真阅读我文章的人,下面这个网盘链接也是我费了几天时间整理的非常全面的,希望也能帮助到有需要的你!

    在这里插入图片描述

    这些资料,对于想转行做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!凡事要趁早,特别是技术行业,一定要提升技术功底。希望对大家有所帮助……

    如果你不想一个人野蛮生长,找不到系统的资料,问题得不到帮助,坚持几天便放弃的感受的话,可以点击下方小卡片加入我们群,大家可以一起讨论交流,里面会有各种软件测试资料和技术交流。

    点击文末小卡片领取

    敲字不易,如果此文章对你有帮助的话,点个赞收个藏来个关注,给作者一个鼓励。也方便你下次能够快速查找。

    自学推荐B站视频:

    零基础转行软件测试:25天从零基础转行到入职软件测试岗,今天学完,明天就业。【包括功能/接口/自动化/python自动化测试/性能/测试开发】

    自动化测试进阶:2022B站首推超详细python自动化软件测试实战教程,备战金三银四跳槽季,进阶学完暴涨20K

  • 相关阅读:
    C++笔记20•数据结构:哈希(Hash)•
    非母语玩家如何撰写英文研究性论文:1 Introduction
    Spring Cloud开发实践(六): 基于Consul和Spring Cloud 2021.0的演示项目
    可观测性-Metrics-Tomcat连接数、线程数理解以及压测记录
    智能锁控板的主要功能有哪些?如何使用?
    【SDXL_LORA模型训练详细教程(含云端教程)】
    系统编程07-线程的互斥锁、读写锁、条件变量
    OpenAI打破文本和图像次元壁,提出基于对比学习的多模态预训练模型CLIP
    C语言天花板——指针(进阶1)
    JavaScript 是什么
  • 原文地址:https://blog.csdn.net/xfw17397388089/article/details/125409223