当前位置: 首页 > 工具软件 > testRunner > 使用案例 >

使用Unittest测试框架testcase、testsuite、testloader、testrunner做测试

楚建柏
2023-12-01

以下内容B站千峰软件测试训练营内容

 引入例子使用简单的例子进行测试脚本的开发:

#开发实现功能myMath.py
class mymath():
    def jia(self,a,b):
        return a+b
    def jian(self,a,b):
        return a-b
    def chengfa(self,a,b):
        return a*b
    def chufa (self,a,b):
        if b==0:
            return 'ee'
        else:
            return a/b
if __name__=="__main__":
    mm=mymath()
    #测试用例一:验证数字的加法
    actualValue=mm.jia(2,3)
    exceptValue=5
    if actualValue==exceptValue:
        print("该加法功能实现正确",exceptValue)
    # 测试用例2:异常用例
    try :
        actualValue=mm.jia("a",3)
        exceptValue = "a3"
        if actualValue == exceptValue:
            print("该加法功能实现正确",exceptValue)
    except Exception as e:
        print("该方法实现不正确",e)
    #验证字符串的加法
    try :
        actualValue=mm.jia("a","b")
        exceptValue ="ab"
        if actualValue == exceptValue:
            print("该加法功能实现正确",exceptValue)
    except Exception as e:
        print("该方法实现正确",e)
输出:

该加法功能实现正确 5
该方法实现不正确 can only concatenate str (not "int") to str
该加法功能实现正确 ab

这种方法的特点:

1.断言方式太low,需要使用if-else进行判断;

2.测试结果在控制台输出,看不到测试报告的效果。

于是引入Unittest框架,其优势在于:

1.提供了用例的组织与形式;

2.提供了丰富的日志和报告;

3.提供了丰富的断言方法,如表1所示.

表1 unittest框架TestCase类提供的断言方法

方法 描述 方法 描述 assertEqual(a,b) a==b assertIn(a,b) a in b assertTrue(x) bool(x) isTrue assertNone(x) x is None assertIs(a,b) a is b assertIsInstance(a,b) isInstance(a,b)

以下将通过unnittest 框架来实现mytest

引入unittest框架来设计mymath单元测试用例
TestCase步骤:
        1.导包 unittest是自导的框架,不需要安装;
        2.创建一个单元测试类(其实就是类,只不过他继承了单元测试框架单元测试用例的类);
        3.单元测试类中的5个方法的使用,包括使用场景及执行顺序;
                 setUp():测试用例的资源初始化,一般写入测试用例的前提条件;
                 test_add_1():测试用例,把测试用例步骤写在这个方法中;
                 tearDown()用于测试用例的资源释放。
                 @classmethod注解的是类方法,不用创建对象也能用,在对象创建之前就已经存在
                              的方法随着类进入内存。
                 setUpClass给当前所有的测试类进行初始化
                 tearDownClass给所有的单元测试用例进行资源释放
        4.创建测试用例:test开头的方法,与代码顺序无关
        5.测试用例的执行:
                 main():所有的测试用例执行一遍,测试用例的执行顺序按照测试用例方法名的字母序执行的。
import  unittest
from myMath import mymath
#创建一个单元测试类(继承自unittest.testcase)
class myMathTest(unittest.TestCase):

    #测试用例资源初始化方法
    def setUp(self):
        self.mm=mymath()
    #测试用例方法
    def test_add_1(self):
        actualValue=self.mm.jia(2,1)
        exceptValue=3
        #断言
        self.assertEqual(actualValue,exceptValue,"预期结果与实际结果不一致")
    #测试用例方法
    def test_add_2(self):
        actualValue=self.mm.jia("ab","cd")
        exceptValue="abcd"
        #断言
        self.assertEqual(actualValue,exceptValue,"预期结果与实际结果不一致")
    def test_jian_1(self):
        actualValue=self.mm.jian(2,1)
        exceptValue=1
        #断言
        self.assertEqual(actualValue,exceptValue,"预期结果与实际结果不一致")
    def test_cheng_1(self):
        actualValue=self.mm.chengfa(2,5)
        exceptValue=10
        #断言
        self.assertEqual(actualValue,exceptValue,"预期结果与实际结果不一致")
    def test_cheng_2(self):
        actualValue=self.mm.chengfa("a",2)
        exceptValue="aa"
        #断言
        self.assertEqual(actualValue,exceptValue,"预期结果与实际结果不一致")
    def test_chu_1(self):
        actualValue=self.mm.chufa(4,2)
        exceptValue=2
        #断言
        self.assertEqual(actualValue,exceptValue,"预期结果与实际结果不一致")
    def test_chu_2(self):
        actualValue=self.mm.chufa(4,0)
        exceptValue=2
        #断言
        self.assertEqual(actualValue,exceptValue,"预期结果与实际结果不一致")
    #测试用例的资源
    def tearDown(self) -> None:
        pass

if __name__ == '__main__':
    unittest.main()#运行所有的测试用例
控制台输出:
C:\Users\beauty\AppData\Local\Programs\Python\Python38\python.exe C:/Users/beauty/Desktop/test_project/venv/run_test_unittest_2py.py
F.
======================================================================
FAIL: test_add_1 (__main__.unitMymath)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:/Users/beauty/Desktop/test_project/venv/run_test_unittest_2py.py", line 26, in test_add_1
    self.assertEqual(actualValue,exceptValue,"预期结果与实际结果不一致")
AssertionError: 22 != 24 : 预期结果与实际结果不一致

----------------------------------------------------------------------
Ran 2 tests in 0.001s

FAILED (failures=1)
我是setUpClass方法
我是setup方法
我是第一条测试用例
我是teardown方法
我是setup方法
我是第二条测试用例
我是teardown方法
我是tearDownClass方法

Process finished with exit code 1

使用测试集合概念(testsuit)的方法解决存在的问题:1.运行所有测试用例,2.执行顺序;

testsuite:        

        1.调用testsuite的对象

        2.调用testsuite中的方法addtest()、addtests()将测试用例加入集合中

        3.testsuite的run()方法运行测试集合

                注意run方法的参数是testresult的对象:re = unittest.TestResult()

        4.使用print(re.__dict__)可显示测试运行的结果

if __name__=="__main__":
    #1.创建testsuite的方法
    suitt=unittest.TestSuite()
    #测试集合对象有一个方法"test_add_1"。
    # addtest单次追加测试用例到测试集合;addtsets追加多个测试用例,且对象为可迭代的
    #格式:类名(用例名)
    suitt.addTest(unitMymath("test_add_2"))#测试集合对象有一个方法"test_add_2先执行"。
    suitt.addTest(unitMymath("test_add_1"))
    re = unittest.TestResult()
    suitt.run(re)

if __name__=="__main__":
    #1.创建testsuite的方法
    suitt=unittest.TestSuite()
    suitt.addTests(map(unitMymath,["test_add_2","test_add_1"]))#创建一个组合
    re = unittest.TestResult()
    suitt.run(re)

两种方法运行结果相同:
C:\Users\beauty\AppData\Local\Programs\Python\Python38\python.exe C:/Users/beauty/Desktop/test_project/venv/run_test_unittest_2py.py
我是setUpClass方法
我是setup方法
我是第二条测试用例
我是teardown方法
我是setup方法
我是第一条测试用例
我是teardown方法
我是tearDownClass方法

Process finished with exit code 0
实际的测试中会有大量的测试用例,使用testsuite自带的方法加载到集合很麻烦,可使用unittest模块提供的testloader模块,可以将测试用例加载到测试集合中

TestLoader:

        1.创建TestLoader对象:loader=unittest.TestLoader()

        2.loadtestsfromName通过添加的模块名、类名、测试用例名,将其中的的用例直接加载到测试集合,返回给测试对象
    # suitt=loader.loadTestsFromName("run_test_unittest_2py")模块名
    # suitt=loader.loadTestsFromName("run_test_unittest_2py.unitMymath")#类名
    suitt=loader.loadTestsFromName("run_test_unittest_2py.unitMymath.test_add_2")#测试用例名

        3.使用loader的discover方法,将指定文件(模块)中的测试用例一次性加载。使用的方法suitt=unittest.defaultTestLoader.discover(filename,pattern="run_test_unittest_1.py"):

        path:指定存放测试用例的目录即可(单元测试用例,使用unitest框架写的)

        pattern:只当匹配规则,run_test*.py

#testsuite:
# 创建testsuite的对象
# 调用testsuite的方法addtess、addtests()将测试用例加入测试集合
# 3.testsuite的run方法运行测试集合
import unittest
import myMath
class unitMymath(unittest.TestCase):
    #使用@给方法指定了特殊的含义
    @classmethod
    def setUpClass(cls) -> None:
        print("我是setUpClass方法")
    @classmethod
    def tearDownClass(cls) -> None:
        print("我是tearDownClass方法")#释放资源
    #方法名不能该
    def setUp(self) -> None:
        self.mm = myMath.mymath()#共同测试用例的方法
        print("我是setup方法")
    #必须test开头的方法,即测试用例
    def test_add_1(self):
        print("我是第一条测试用例")
        #mm=myMath.mymath()
        actualValue=self.mm.jia(10,12)
        exceptValue=22
        self.assertEqual(actualValue,exceptValue,"预期结果与实际结果不一致")
    def test_add_2(self):
        print("我是第二条测试用例")
        #mm=myMath.mymath()
        actualValue=self.mm.jia('a','b')
        exceptValue='ab'
        self.assertEqual(actualValue,exceptValue,"预期结果与实际结果不一致")
    # 方法名不能该
    def tearDown(self) -> None:
        print("我是teardown方法")
if __name__=="__main__":
    #1.创建testsuite的方法创建测试集合对象
    suitt=unittest.TestSuite()
    # 1.创建testloader的对象
    loader=unittest.TestLoader()
    suitt=loader.loadTestsFromName("run_test_unittest_2py.unitMymath.test_add_2")#测试用例名

     # #测试结果
    re=unittest.TestResult()
    # #测试集合中有run方法,直接运行即可
    suitt.run(re)
    print(re.__dict__)#测试运行的结果



控制台输出:
C:\Users\beauty\AppData\Local\Programs\Python\Python38\python.exe C:/Users/beauty/Desktop/test_project/venv/run_test_unittest_2py.py
我是setUpClass方法
我是setup方法
我是第二条测试用例
我是teardown方法
我是tearDownClass方法
{'failfast': False, 'failures': [], 'errors': [], 'testsRun': 1, 'skipped': [], 'expectedFailures': [], 'unexpectedSuccesses': [], 'shouldStop': False, 'buffer': False, 'tb_locals': False, '_stdout_buffer': None, '_stderr_buffer': None, '_original_stdout': <_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>, '_original_stderr': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'>, '_mirrorOutput': False, '_testRunEntered': False, '_moduleSetUpFailed': False, '_previousTestClass': <class 'run_test_unittest_2py.unitMymath'>}

Process finished with exit code 0

以下需要导入import os

测试用例为run_test_unittest_1

if __name__=="__main__":
   
    #1.创建testsuite的方法创建测试集合对象
    suitt=unittest.TestSuite()
    
    loader=unittest.TestLoader()
   
    filename = os.path.dirname(__file__)
    # # #使用testloader对象的discover方法加载测试用例,第一个参数是一个目录,这个目录下可以由单元测试用例的文件unittest_1文件
    suitt=unittest.defaultTestLoader.discover(filename,pattern="run_test_unittest_1.py")
    #
    # #测试结果
    re=unittest.TestResult()
    # #测试集合中有run方法,直接运行即可
    suitt.run(re)
    print(re.__dict__)#测试运行的结果

TestRunner:

        前面测试结果都是使用testsuite()的run方法,suitt.run(re),运行的结果是在控制台输出。

        TextTestRunner()将结果以text的形式展示。

'''
run_test_unittest_4.py
使用unittest框架测试mymath类中的加减乘除
使用步骤:
1.导模块(unittest模块、mymath模块)
2.创建一个单元测试类(继承自unittest.testcase)
3.定义三个测试用例的方法
    def setUp()
    def test_xx()
    def tearDown()
'''
#
import os
import  unittest
from myMath import mymath
#创建一个单元测试类(继承自unittest.testcase)
class myMathTest(unittest.TestCase):

    #测试用例资源初始化方法
    def setUp(self):
        self.mm=mymath()
    #测试用例方法
    def test_add_1(self):
        actualValue=self.mm.jia(2,1)
        exceptValue=3
        #断言
        self.assertEqual(actualValue,exceptValue,"预期结果与实际结果不一致")
    #测试用例方法
    def test_add_2(self):
        actualValue=self.mm.jia("ab","cd")
        exceptValue="abcd"
        #断言
        self.assertEqual(actualValue,exceptValue,"预期结果与实际结果不一致")
    def test_jian_1(self):
        actualValue=self.mm.jian(2,1)
        exceptValue=1
        #断言
        self.assertEqual(actualValue,exceptValue,"预期结果与实际结果不一致")
    def test_cheng_1(self):
        actualValue=self.mm.chengfa(2,5)
        exceptValue=10
        #断言
        self.assertEqual(actualValue,exceptValue,"预期结果与实际结果不一致")
    def test_cheng_2(self):
        actualValue=self.mm.chengfa("a",2)
        exceptValue="aa"
        #断言
        self.assertEqual(actualValue,exceptValue,"预期结果与实际结果不一致")
    def test_chu_1(self):
        actualValue=self.mm.chufa(4,2)
        exceptValue=2
        #断言
        self.assertEqual(actualValue,exceptValue,"预期结果与实际结果不一致")
    def test_chu_2(self):
        actualValue=self.mm.chufa(4,0)
        exceptValue=2
        #断言
        self.assertEqual(actualValue,exceptValue,"预期结果与实际结果不一致")
    #测试用例的资源
    def tearDown(self) -> None:
        pass
if __name__ == '__main__':
    #创建一个测试集合
    suitt=unittest.TestSuite()
    #直接使用TestLoader的discover方法返回测试集
    discover=unittest.defaultTestLoader.discover(r"./",pattern="run_test_unittest_4.py")
    #使用TextTestRunner()运行器提供的run()行测试集,a为写模式
    #创建一个文件流对象,打开文件进行写数据
    with open (r"./re.txt","w",encoding="utf-8") as f:
        runner=unittest.TextTestRunner(f,descriptions="用于测试math类的用例测试",verbosity=2)
        runner.run(discover)#测试集合

运行结果

re.txt文件的内容:

test_add_1 (run_test_unittest_4.myMathTest) ... ok
test_add_2 (run_test_unittest_4.myMathTest) ... ok
test_cheng_1 (run_test_unittest_4.myMathTest) ... ok
test_cheng_2 (run_test_unittest_4.myMathTest) ... ok
test_chu_1 (run_test_unittest_4.myMathTest) ... ok
test_chu_2 (run_test_unittest_4.myMathTest) ... FAIL
test_jian_1 (run_test_unittest_4.myMathTest) ... ok

======================================================================
FAIL: test_chu_2 (run_test_unittest_4.myMathTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Users\beauty\Desktop\test_project\venv\run_test_unittest_4.py", line 57, in test_chu_2
    self.assertEqual(actualValue,exceptValue,"预期结果与实际结果不一致")
AssertionError: 'ee' != 2 : 预期结果与实际结果不一致

----------------------------------------------------------------------
Ran 7 tests in 0.003s

FAILED (failures=1)s




 类似资料: