zoukankan      html  css  js  c++  java
  • Python单元测试框架unittest

    学习接口自动化测试时接触了unittest单元测试框架,学习时参照了虫师编写的《selenium2自动化测试实战》,个人觉得里面讲的例子还比较容易理解的。

    一、基础

    1main()和框架的简单使用,例:

     1 import unittest   #导包
     2 import calculator import Count
     3 class TestCount(unittest.TestCase):  #继承unittest
     4   def setUp(self):
     5     print("test start")
     6   def test_add(self):
     7     i = Count(2,3)
     8     self,assertEqual(j.add(),5)
     9   def tearDown(self):
    10     print("test end")
    11 if __name__=='__main__':
    12   unittets.main()

     上面的代码,先引入unittest模块,创建TestCout类继承unittestTestCase

    assertEqual()unittest框架提供的断言方法,判断两者是否相等

    unittest提供了全局的main()方法。可以将一个单元测试模块变成可以直接运行的测试脚本。

    main()方法使用testLoader类来搜索所有包含在该模块总以“test”命名开头的测试方法,并自动执行他们

    备注:setupteardownobotframework里的初始化清除类似。

    2、执行测试集

    1 if    __name__ == '__main__':
    2 #构造测试集
    3   suite=unittest(TestAdd("test_add"))
    4   suite.addTest(TestAdd("test_add2"))
    5   suite.addTest(TestSub("test_sub"))  #TestSub是要被执行测试用例的类名,test_sub方法名
    6 
    7 #运行测试集合
    8   runner = unittest.TestTestRunner()
    9   runner.run(suite)

    通过TestSuite类的addTest()方法把不同测试类中的测试方法组装到测试套件中

    3、常用断言方法

    assertEqual(a,b)   #a==b
    assertNotEqual(a,b)     #a!=b
    asserTrue(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
    assertIn(a,b)        #a in b 
    assertNotIn(a,b)    #a not in b
    assertIsInstance(a,b)    #isinstance(a,b)
    assertNotIsInstance(a,b)    #not isinstance(a,b)

    4、跳过测试

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

    unittest.skip(reason)    #无条件地跳过装饰的测试,说明跳过的原因
    unittest.skipIf(condition,reason)   #如果条件为真,跳过装饰的测试
    unittest.skipUnless(condition,reason)   #除非条件为真,跳过装饰的测试
    unittest.expectedFailure()    #不管执行直接是否失败,都标记为失败

    例:

     1 @unittest.skip("直接跳过测试")
     2 def test_skip(self):
     3   print("test")
     4 
     5 @unittest.skip(3>2,“当条件为True时跳过测试”)
     6 def test_skip_if(self):
     7   print("test111")
     8 
     9 @unittest.skipUnless(3>2,"当条件为True时,执行测试")
    10 def    test_skip_unless(self):
    11   print("test22")
    12 
    13 @unittest.expected_Failure
    14 def    test_expected_failure(self):
    15   assertEqual(2,3)
    16 
    17 if __name__=='__main__':
    18   unittest.main()

    5discover()

    aTestLoader()

    该类负责根据各自标准加载测试用例,并将他们返回给测试套件。unittest提供了可以共享的defaultTestLoader类,可以使用其子类和方法创建实例,比如discover()

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

    作用:找到指定目录下所有测试模块,并可递归查到子目录下的测试模块,只有匹配到文件名才能被加载。如果启动的不是顶层目录,那么顶层目录必须单独指定 

    start_dir:要测试的模块名或测试用例目录

    pattern='test*.py':匹配文件名以“test"开头的”.py"类型的文件,“*”表示任意多个字符

    top_level_dir=None:测试模块的顶层目录,如果没有顶层目录,默认为None

    示例:

    1 import unittest
    2 
    3 #定义测试用例的目录为当前目录
    4 test_dir='./'
    5 discover=unittest.defaultTestLoader.discover(test_dir,pattern='test*.py')
    6 
    7 if __name__=='__main__':
    8   runner=unittest.TextTestRunner()
    9   runner.run(discover)

    discover()方法会自动根据测试目录(test_dir)匹配查找测试用例(test*.py),并将查找到的测试用例组装到测试条件中。

    二、unittest数据参数化

    unittest本身不支持参数化,但是可以借助其他方法

    1、unittest中使用第3方插件parameterized进行参数化

    首先在DOS中键入以下命令安装parameterized
    python -m pip install parameterized

    导包:
    from parameterized import parameterized

    例:

     1 import unittest
     2 from pylibrary.PyLib import *
     3 
     4 class   Interface_Report2(unittest.TestCase):
     5 
     6 #开始使用parameterized
     7     @parameterized.expand([   #引用装饰器,准备参数,传入下方的函数
     8         ("2018-09-26", '2018-09-26', "测试", "2001",49,'TotalCallNum'),
     9         ("2018-09-26", '2018-09-26', "测试", "2001",60,'TotalCallAnsweredNum'),
    10         ("2018-09-26", '2018-09-26', "测试", "2001",60,'RingNum'),
    11         ("2018-09-13", '2018-09-13', "测试", "2001",4,'TotalCallNum_Transfer'),
    12     ])
    13 
    14 
    15     def test_Agreport1(self,start_time,end_time,template_name,ag_num,testData,reportData):   #当执行到此会自动接收上面传入的参数
    16         self.num = testData
    17         self.report_num1 = PyLib().getAgReport(start_time,end_time,template_name,ag_num)
    18         self.report_num=self.report_num1[0][reportData]
    19         self.assertEqual(self.num,self.report_num)
    20 
    21 if  __name__ == '__main__':
    22 
    23     unittest.main(verbosity=2)
    24 
    25 #verbosity表示测试结果的信息复杂度,分别使用0,1,2,其具体的含义如下:
    26 #0(静默模式):仅仅获取总的测试用例数以及总的结果
    27 #1(默认模式):此时在每个成功的用例前面有个’.’,每个失败的用例前面有个’F’
    28 #2(详细模式):测试结果会显示每个测试用例的所有相关信息

    2、unittest的ddt库

    pip install ddt

    首先创建一个数据文件:test_ddt_file.json

     1 {
     2     "test_Agreport1_01":{
     3         "start_time":"2018-09-26",
     4         "end_time":"2018-09-26",
     5         "template_name": "测试",
     6         "ag_num":"2001",
     7         "testData":49,
     8         "reportData":"TotalCallNum"
     9     },
    10     "test_Agreport1_02":{
    11         "start_time":"2018-09-26",
    12         "end_time":"2018-09-26",
    13         "template_name": "测试",
    14         "ag_num":"2001",
    15         "testData":60,
    16         "reportData":"TotalCallAnsweredNum"
    17     },
    18     "test_Agreport1_03":{
    19         "start_time":"2018-09-26",
    20         "end_time":"2018-09-26",
    21         "template_name": "测试",
    22         "ag_num":"2001",
    23         "testData":60,
    24         "reportData":"RingNum"
    25     },
    26     "test_Agreport1_04":{
    27         "start_time":"2018-09-13",
    28         "end_time":"2018-09-13",
    29         "template_name": "测试",
    30         "ag_num":"2001",
    31         "testData":4,
    32         "reportData":"TotalCallNum_Transfer"
    33     }
    34 }

    创建测试用例:

     1 import unittest
     2 from pylibrary.PyLib import *
     3 from ddt import ddt, file_data
     4 
     5 
     6 @ddt
     7 class   Interface_Report2(unittest.TestCase):
     8 
     9     @file_data("D:\Python_code\test_ddt_file.json")
    10     def test_Agreport1(self,start_time,end_time,template_name,ag_num,testData,reportData):
    11         self.num = testData
    12         self.report_num1 = PyLib().getAgReport(start_time,end_time,template_name,ag_num)
    13         self.report_num=self.report_num1[0][reportData]
    14         self.assertEqual(self.num,self.report_num)
    15 
    16 
    17 
    18 if  __name__ == '__main__':
    19 
    20     unittest.main(verbosity=2)

     三、命令行运行

    命令行运行我使用的比较少,一般用pycharm直接就运行了。以下作为以后参考使用吧

    通过命令行运行:模块、类、或者单个测试方法,具体的操作是如下:

    运行测试模块:python -m unittest test_module1 test_module2

    运行测试类:python -m unittest test_module.TestClass

    运行测试方法:python -m unittest test_module.TestClass.test_method

    可以在一个列表中添加需要运行的模块名、类名、方法名。

    可以通过使用-v参数获取更详细的测试信息:python -m unittest -v test_module

    可以通过-h参数查看命令行所有参数:python -m unittest -h

    命令行参数:

    -b --buffer

    在测试运行期间标准输出流和标准错误流被缓存。输出通过测试信息。

    输出在测试失败或错误时正常回显,并添加到失败消息中。

    -c --catch

    Ctrl+C在测试运行期间等待当前测试结束,然后报告到目前为止的所有结果。

    第二个Ctrl+C会引发KeyboardInterrupt异常。

    -f --failfast

    在第一个错误或故障时停止测试运行。

    命令行也可用于测试发现(Test Discovery),用于运行项目中的所有测试或仅用于子集。

    Unittest支持简单的测试发现(Test Discovery)。为了与测试发现兼容,

    所有测试文件必须是可从项目的根目录导入的模块或包(这意味着它们的文件名必须是有效的标识符)。

    Test Discovery是通过TestLoader.discover()实现,也可以通过命令行实现。

    基本的命令行用法:

    cd project_directory #进入项目目录根目录

    python -m unittest discover #执行命令

    discover子命令的参数如下:

    -v , --verbose

    详细输出

    -s , --start-directory directory

    执行发现的起始目录(directory),默认是当前目录(.)

    -p, --pattern pattern

    匹配测试文件的模式(pattern),默认是test*.py

    -t, --top-level-directory directory

    项目(directory)的目的的根目录(默认是起始目录)

    -s-p-t命令可以在一个命令行中联合使用。下面两个命令是等价的:

    python -m unittest discover -s project_directory -p "*_test.py"

    python -m unittest discover project_directory "*_test.py"

    作为一个路径,可以传递一个包名称,例如myproject.subpackage.test作为开始目录。

    然后将导入提供的软件包名称,并将其在文件系统上的位置用作开始目录。

    注意:测试发现通过导入来加载测试。一旦测试发现已经从指定的开始目录中找到所有测试文件,

    它将路径转换为要导入的包名称。例如foo / bar / baz.py将导入为foo.bar.baz

    如果有全局安装的软件包,并尝试在软件包的不同副本上进行测试发现,

    那么导入可能发生在错误的位置。如果发生这种情况,测试发现将警告并退出。

    如果提供开始目录作为包名称而不是目录的路径,则发现假定它从其导入的任何位置是想要的位置,因此不会得到警告。

    测试模块和包可以通过load_tests协议自定义测试加载和发现。

    '''

    import os

    #进入到TestHello.py路径下

    os.chdir(".//TestSuit_01")

    print os.getcwd()

    print '''可以通过命令行测试信息'''

    #运行测试模块TestHello.py

    os.system("python -m unittest TestHello")

    #运行测试类TestHello

    os.system("python -m unittest TestHello.TestHello")

    #运行测试方法

    os.system("python -m unittest TestHello.TestHello.test_Hello")

    print "#"*50

    print

    print '''可以通过使用-v参数获取更详细的测试信息'''

    #运行测试模块TestHello.py

    os.system("python -m unittest -v TestHello")

    #运行测试类TestHello

    os.system("python -m unittest -v TestHello.TestHello")

    #运行测试方法

    os.system("python -m unittest -v TestHello.TestHello.test_Hello")

    print "#"*50

    print

    print '''可以通过-h参数查看命令行所有参数:python -m unittest -h'''

    os.system("python -m unittest -h")

    print "#"*50

    print

    print "命令行参数:-b -c -f"

    #运行测试模块TestHello.py

    os.system("python -m unittest -b TestHello")

    #运行测试类TestHello

    os.system("python -m unittest -c TestHello.TestHello")

    #运行测试方法

    os.system("python -m unittest -f TestHello.TestHello.test_HelloType")

    print "#"*50

    print

    #使用测试发现命令执行所有测试

    print "使用测试发现执行项目中的所有测试"

    #进入到UnttestPro

    os.chdir("../")

    print "The current path:",os.getcwd()

    #全部使用默认的参数

  • 相关阅读:
    POJ1185:炮兵阵地(状压dp)
    POJ3254:Corn Fields(状压dp第一发)
    二进制x&(x-1);
    子集和问题(应用--换零钱)POJ2229:Sumsets
    JAVA math包
    UVA+POJ中大数实现的题目,持续更新(JAVA实现)
    HDU中大数实现的题目,持续更新(JAVA实现)
    SDUT中大数实现的题目,持续更新(JAVA实现)
    JAVA与ACM
    HDU3123:GCC(同余模简单题)
  • 原文地址:https://www.cnblogs.com/Mollylin/p/9765430.html
Copyright © 2011-2022 走看看