51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

测试开发精英班,通向高级软件测试工程师【好消息】企业内训服务上线啦!项目为王,自动化测试提升加速器 !横扫BAT,Python全栈测试开发技能大全
【第122期】:如何入门接口自动化测试!参与调查问卷 缔造行业趋势 月薪15K+的测试开发必备技能? 【活动】为视频UP主打CALL,互动领福利!
查看: 363|回复: 0

[原创] 如何使用Unittest编写自动化测试用例

[复制链接]
  • TA的每日心情

    2021-9-6 09:30
  • 签到天数: 537 天

    连续签到: 1 天

    [LV.9]测试副司令

    发表于 2021-3-24 09:45:12 | 显示全部楼层 |阅读模式
    前言  我们编写自动化的测试用例,通常会编写在单元测试框架中。python的单元测试有自带的unittest和第三方的pytest,今天主要介绍下我们在python中如何通过unittest编写自动化测试用例。

      unittest介绍
      unittest属于python自带的单元测试框架,类似与java的junit。unittest支持编写测试自动化用例,多个用例中共享一个前置和后置内容,有多种执行测试用例的方法,支持生成独立的测试报告内容。
      官方文档:https://docs.python.org/2/library/unittest.html

      unittest常用方法
      无论是什么单元测试框架,都会有一些常用的方法,安静先介绍下unittest框架中一些常用的方法。

      Test Case
      Test Case通常用来创建测试用例,编写的测试用例标准是以test进行开头的(当然这个是官方定义的,其实可以通过修改unittest的源码进行修改的。)测试用例的执行顺序是通过ASCII值排序来执行的。

      Test Suite
      Test Suite属于一个测试套件,可以把我们的测试用例进行都放在这个里面进行执行。

      Test Fixture
      Test Fixture表示编写的测试用例的初始化准备及环境还原,主要是setUp() 和 setDown()方法。

      Test Runner
      TestRunner通常用来执行测试用例,会把我们执行的测试的结果通过HTMLTestRunner的形式展现在测试报告中。

      unittest简单使用
      前面介绍了unittest的常用方法,介绍下unittest的简单使用。这里需要先导入unittest库,需要在类中继承unittest中的TestCase方法,编写用例时用例名需要已test开头。
    import unittest
    class Test(unittest.TestCase):

        def test_01(self):
            print('---用例01---')

        def test_02(self):
            print('---用例02---')

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


      通过执行可以看到,一共编写了2条用例都全部执行完成了,其中如果执行程序则用"."表示,失败的话会用"F"表示。



      前置和后置
      功能测试中执行用例有前置条件,那么我们编写自动化用例的时候也有前置和后置,其中前置通过setup后置通过teardown进行操作。
    import unittest
    class Test(unittest.TestCase):

        def setUp(self):
            print('执行前置操作--->打开浏览器。')

        def tearDown(self):
            print('执行后置操作--->关闭浏览器。')

        def test_01(self):
            print('---用例01---')

        def test_02(self):
            print('---用例02---')

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



      通过执行结果发现每条用例都会进行执行前置操作和后置操作。如果我们的用例顺序是固定的,那么就不需要多次进行前置操作,那么我们就可以通过另一种方法进行使用。

      classmethod
      classmethod是unittest的一个装饰器方法,通常和setupclass,teardownclass进行结合使用,多数用来执行一个class中只执行一次测试用例前置和后置操作。
    import unittest
    class Test(unittest.TestCase):

        @classmethod
        def setUpClass(cls):
            print('执行前置操作--->打开浏览器。')

        @classmethod
        def tearDownClass(cls):
            print('执行后置操作--->关闭浏览器。')

        def test_01(self):
            print('---用例01---')

        def test_02(self):
            print('---用例02---')

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




      通过执行结果可以看出来,用例01和用例02都只执行了一次操作。


      unittest断言
      每条测试用例都需要一个断言来判断是否成功,在unittest中有特定的断言方法,其实和python自带的类似,只是有一点改动。安静给大家距离介绍。
    import unittest
    class Test(unittest.TestCase):
        def test_01(self):
            print('判断a是否存在b中')
            a = '安静'
            b = '测试安静'
            self.assertIn(a, b)

        def test_02(self):
            print('判断a是否等于b')
            a = '111'
            b = '111'
            self.assertEqual(a, b)

        def test_03(self):
            print('a是否等于为True')
            a = True
            self.assertTrue(a)

        def test_04(self):
            print('失败用例')
            a = '测试安静'
            b = '测试-安静'
            self.assertIs(a, b)

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


      通过执行操作会发现,前3个测试用例都通过了,第4个执行失败,并提示错误出现在哪里。方便我们查看错误信息。


      断言方法
      其实unittest的断言方法不仅仅只有这几种,安静给大家列举了一些常用的。


      verbosity
      肯定有小伙伴们会问什么是verbosity?这个和unittest有什么关系,其实这个也是属于unittest的中一个参数,通常用来表示我们的用例的执行情况和详细信息,其中verbosity一共有3个值分别是0,1和2。

      verbosity=0
      当verbosity等于0时表示:执行用例的时候,只能获取用例的测试结果和测试用例数量。当然用例中的打印,肯定是会显示的
    import unittest
    class Test(unittest.TestCase):
        def test_01(self):
            print('---用例01---')

        def test_02(self):
            print('---用例02---')

        def test_03(self):
            print('---用例03---')
    if __name__ == '__main__':
        unittest.main(verbosity=0)




      通过执行结果发现,当我们把verbosity=0设置在main函数中,执行后就会进行只打印一些简单的内容,执行了多少个用例,用例的打印内容,已经测试结果。


      verbosity=1
      verbosity=1时表示:在0的基础上,每个成功的用例前面有个".",失败的用例前面有个"F"(是不是很熟悉?其实这个就是默认操作。verbosity默认为1)。
    import unittest
    class Test(unittest.TestCase):
        def test_01(self):
            print('---用例01---')

        def test_02(self):
            print('---用例02---')

        def test_03(self):
            print('---用例03---')
    if __name__ == '__main__':
        unittest.main(verbosity=1)



      执行结果发现,用例的前面都存在一个"."表示执行成功。


      verbosity=2
      verbosity=2表示:每条用例都会输出详细的相关信息。
    import unittest
    class Test(unittest.TestCase):
        def test_01(self):
            print('---用例01---')

        def test_02(self):
            print('---用例02---')

        def test_03(self):
            print('---用例03---')
    if __name__ == '__main__':
        unittest.main(verbosity=2)




      通过执行结果可以看出来,这个比前面2个都详细。


      参数值具体什么时候使用,这个就要看大家在项目中的需求了。

      加载用例的方法
      在unittest中执行测试用例的方法有很多种。比如:想要执行特定的用例,想要批量执行某模块的用例,这个时候就会有不同的方法来执行更加方便。

      TestCase
      用例测试集合,将相同模块下的用例可以都写在一起,执行的时候直接通过main方法或者当前方法的文件名执行。
    import unittest
    class Test(unittest.TestCase):

        def test_01(self):
            print('---用例01---')

        def test_02(self):
            print('---用例02---')

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




      testsuite
      testsuite简称测试套件,就是可以将不同的用例都添加到这个套件中,然后通过执行套件,然后完成执行测试用例。
    import unittest

    class Test(unittest.TestCase):
        def test_01(self):
            print('---用例01---')

        def test_02(self):
            print('---用例02---')

        def test_03(self):
            print('---用例03---')

    if __name__ == '__main__':
        #创建测试套件
        suite = unittest.TestSuite()
        # 测试用例加入到测试套件中
        suite.addTests([Test('test_01'), Test('test_03')])
        # 执行测试用例
        run = unittest.TextTestRunner()
        run.run(suite)




      通过执行结果可以看出来,我们的test_02没有执行,只执行了用例1和用例3。


      discover
      discover可以通过文件夹的形式进行执行,在实际项目中,测试用例都会存放在测试用例对应的目录下,用例量比较多,我们就可以通过discover的方法进行执行。
      其中discover有3个参数:
      ·start_dir:表示用例路径
      ·pattern:用例匹配规则
      ·top_level_dir:项目目录名称
    import unittest

    class Test(unittest.TestCase):
        def test_01(self):
            print('---用例01---')

        def test_02(self):
            print('---用例02---')

        def test_03(self):
            print('---用例03---')

    if __name__ == '__main__':
        # 用例路径
        case_path = 'E:\\web'
        # 批量执行当前文件夹下的执行文件
        discover = unittest.defaultTestLoader.discover(case_path,
                                                       pattern='w5.py',
                                                       top_level_dir=None)
        run = unittest.TextTestRunner()
        run.run(discover)




      通过执行结果,我么的文件夹w5.py下的用例已经全部执行完了,当我们在真是项目中,可以将pattern的参数改成“t*.py”这样就可以将当前文件下的所有t开通的文件全部执行。


      跳过用例
      当我们执行用例时候,知道该用例存在bug,再bug没修改前不想要执行,我们可以通过unittest中的skip方法进行跳过,跳过分为两种,强制跳过和条件跳过。

      无条件跳过skip
      skip为无条件跳过。需要给一个跳过的理由reason参数。
    import unittest

    class Test(unittest.TestCase):

        @unittest.skip(reason='该功能存在bug跳过')
        def test_01(self):
            print('---用例01---')

        def test_02(self):
            print('---用例02---')

        def test_03(self):
            print('---用例03---')

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




      通过执行结果发现,用例01已经跳过了。只执行了2和3。


      有条件跳过skipif
      skipif表示条件为True的时候进行跳过,条件如果为False就会继续执行。
    import unittest
    import sys
    class Test(unittest.TestCase):

        @unittest.skipIf(True, reason='该功能存在bug跳过')
        def test_01(self):
            print('---用例01---')

        @unittest.skipIf(sys.platform=='win32', reason='只能在mac上进行运行')
        def test_02(self):
            print('---用例02---')

        def test_03(self):
            print('---用例03---')

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



      通过执行用例,会发现用例1和用例2都跳过了,因为判断的条件为True,所以进行了跳过。



      有条件跳过skipunless
      上面介绍了条件为True的时候跳过,那么肯定会有条件为False的时候进行跳过,刚好skipunless就是属于这个需求了,当条件为False的时候进行跳过。
    import unittest
    import sys
    class Test(unittest.TestCase):

        @unittest.skipUnless(False, reason='该功能存在bug跳过')
        def test_01(self):
            print('---用例01---')

        @unittest.skipUnless(sys.platform=='Linux', reason='只能在Windows上执行')
        def test_02(self):
            print('---用例02---')

        def test_03(self):
            print('---用例03---')
    if __name__ == '__main__':
        unittest.main(verbosity=2)




      通过执行结果发现,同样条件为False的用例1和2都已经跳过了。


      测试报告
      无论是功能测试还是自动化测试还是接口测试,做完测试后肯定想编写一份完整的测试报告,unittest中没有自带的报告生成,需要通过导入unittest的扩展库HTMLTestRunner。
      下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html
      使用方法:下载完成后,直接放到执行的目录中,需要的时候进行导入即可。其中在源码中也详细的介绍了调用方法。
    # output to a file
        fp = file('my_report.html', 'wb')
        runner = HTMLTestRunner.HTMLTestRunner(
                    stream=fp,
                    title='My unit test',
                    description='This demonstrates the report output by HTMLTestRunner.'
                    )
        # Use an external stylesheet.
        # See the Template_mixin class for more customizable options
        runner.STYLESHEET_TMPL = '<link rel="stylesheet" href="my_stylesheet.css" type="text/css">'
        # run the test
        runner.run(my_test_suite)




      其中上面的三个参数分别表示意思:
      ·stream:表示生成报告的路径
      ·title:表示报告的标题
      ·description:表示用例执行情况说明
    import unittest
    import HTMLTestRunner
    class Test(unittest.TestCase):
        def test_01(self):
            print('---用例01---')

        def test_02(self):
            print('---用例02---')

        def test_03(self):
            print('---用例03---')

    if __name__ == '__main__':
        # 创建测试套件
        suite = unittest.TestSuite()
        # 测试用例加入到测试套件中
        suite.addTests([Test('test_01'), Test('test_02'),Test('test_03')])
        report_path = 'report.html'
        # 打开报告
        fp = open(report_path, 'wb')
        runner = HTMLTestRunner.HTMLTestRunner(stream=fp,
                                               title=u'自动化测试报告,测试结果如下:',
                                               description=u'用例执行情况:')
        # 执行用例
        runner.run(suite)
        # 关闭报告
        fp.close()



      通过执行会发现在当前目录已经生成了测试报告。点击查看会出现下图的报告内容。



      这里会看到报告还是不完美,没有详细的用例详情,我们只要在每条用例下加入函数注释即可。


      再次执行后,就会发现,我们每条用例中已经有详细的用例详情。


      总结
      通过这么长的阅读,肯定对unittest有所认识和了解。安静简单的介绍了unittest的一些功能,希望可以帮助读者运用到实际的工作中。

    回复

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2021-10-25 06:16 , Processed in 0.057372 second(s), 25 queries .

    Powered by Discuz! X3.2

    © 2001-2021 Comsenz Inc.

    快速回复 返回顶部 返回列表