unittest框架系列二(代码编写与用例组织)

代码编写与用例组织

欢迎加入测试交流群:夜行者自动化测试(816489363)进行交流学习QAQ

–成都-阿木木


再使用unittest编写你的测试代码时,测试类必须继承TestCase或者FunctionTestCase.

  • TestCase的子类的实例是可以完全运行单个测试方法以及可选的设置和整理代码的对象。
  • TestCase实例的测试代码应完全独立,以使它可以独立运行或与任意数量的其他测试用例任意组合运行。

官网有一段组织测试用例的描述,为什么会衍生出setup/teardown/setUpClass/tearDownClass,用比较直白的话来表述,就是我们不会在每一个test method中去实例化测试对象等公共操作,这些重复的操作会导致代码看起来很难看,所以提供了夹具test fixture来进行设置这一类需要在每个测试类或者测试方法前后进行环境初始化,或者环境清理的对象或公共操作。

当用例执行发现setup/setUpClass方法执行失败时,不会再运行后面的test method,当teardown/tearDownClass执行失败时,test_method方法仍然会运行。

一条测试用例是如何标记为失败呢?使用基类assert*()提供的方法对于用例中的结果进行断言,如果断言失败,就会引发异常。也就是说unittest框架通过识别异常将用例标记为fail。其他不属于assert抛出的异常,都会被识别成ERROR。

#!/user/bin/env python
# -*- coding: utf-8 -*-

"""
------------------------------------
@Project : mysite
@Time    : 2020/8/28 11:32
@Auth    : chineseluo
@Email   : 848257135@qq.com
@File    : unittest_demo.py
@IDE     : PyCharm
------------------------------------
"""
import unittest


class TestStringMethods(unittest.TestCase):
    def setUp(self):
        print("运行于测试方法前,主要用于环境初始化")

    def tearDown(self):
        print("运行于测试方法后,主要用户环境数据清理")

    def test_upper(self):
        print("this is a test_upper method")
        self.assertEqual('foo'.upper(), 'FOO')

    def test_isupper(self):
        print("this is a test_isupper method")
        self.assertTrue('FOO'.isupper())
        self.assertFalse('Foo'.isupper())

    def test_split(self):
        print("this is a test_split method")
        s = 'hello world'
        self.assertEqual(s.split(), ['hello', 'world'])
        # check that s.split fails when the separator is not a string
        with self.assertRaises(TypeError):
            s.split(2)


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

运行结果:
运行于测试方法前,主要用于环境初始化
this is a test_isupper method
运行于测试方法后,主要用户环境数据清理
运行于测试方法前,主要用于环境初始化
this is a test_split method
运行于测试方法后,主要用户环境数据清理
运行于测试方法前,主要用于环境初始化
this is a test_upper method
运行于测试方法后,主要用户环境数据清理
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK

在下面的例子中修改test_upper方法中的self.assertEqual('foo'.upper(), 'FOO')self.assertEqual('foo'.upper(), 'FO'),查看断言异常运行结果,可以看到FAILED(failures=1),属于unittest可识别的断言异常。

import unittest


class TestStringMethods(unittest.TestCase):
    def setUp(self):
        print("运行于测试方法前,主要用于环境初始化")

    def tearDown(self):
        print("运行于测试方法后,主要用户环境数据清理")

    def test_upper(self):
        print("this is a test_upper method")
        self.assertEqual('foo'.upper(), 'FO')

    def test_isupper(self):
        print("this is a test_isupper method")
        self.assertTrue('FOO'.isupper())
        self.assertFalse('Foo'.isupper())

    def test_split(self):
        print("this is a test_split method")
        s = 'hello world'
        self.assertEqual(s.split(), ['hello', 'world'])
        # check that s.split fails when the separator is not a string
        with self.assertRaises(TypeError):
            s.split(2)


if __name__ == '__main__':
    unittest.main()
运行结果为:
C:UsersluozhongwenAppDataLocalProgramsPythonPython38python.exe D:/TestScriptDir/python_web/mysite/unittest_demo.py
..F
======================================================================
FAIL: test_upper (__main__.TestStringMethods)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "D:/TestScriptDir/python_web/mysite/unittest_demo.py", line 26, in test_upper
    self.assertEqual('foo'.upper(), 'FO')
AssertionError: 'FOO' != 'FO'
- FOO
?   -
+ FO


----------------------------------------------------------------------
Ran 3 tests in 0.001s

FAILED (failures=1)
运行于测试方法前,主要用于环境初始化
this is a test_isupper method
运行于测试方法后,主要用户环境数据清理
运行于测试方法前,主要用于环境初始化
this is a test_split method
运行于测试方法后,主要用户环境数据清理
运行于测试方法前,主要用于环境初始化
this is a test_upper method
运行于测试方法后,主要用户环境数据清理

Process finished with exit code 1

在下面的例子的test_isupper中添加一个非断言异常,索引越界异常,查看运行结果,可以看到这是一个非assert的异常,被标记为了error

import unittest


class TestStringMethods(unittest.TestCase):
    def setUp(self):
        print("运行于测试方法前,主要用于环境初始化")

    def tearDown(self):
        print("运行于测试方法后,主要用户环境数据清理")

    def test_upper(self):
        print("this is a test_upper method")
        self.assertEqual('foo'.upper(), 'FOO')

    def test_isupper(self):
        print("this is a test_isupper method")
        a = [1, 2, 3]
        print(a[4])
        self.assertTrue('FOO'.isupper())
        self.assertFalse('Foo'.isupper())

    def test_split(self):
        print("this is a test_split method")
        s = 'hello world'
        self.assertEqual(s.split(), ['hello', 'world'])
        # check that s.split fails when the separator is not a string
        with self.assertRaises(TypeError):
            s.split(2)


if __name__ == '__main__':
    unittest.main()
结果为:
======================================================================
ERROR: test_isupper (__main__.TestStringMethods)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "D:/TestScriptDir/python_web/mysite/unittest_demo.py", line 31, in test_isupper
    print(a[4])
IndexError: list index out of range

----------------------------------------------------------------------
Ran 3 tests in 0.001s

FAILED (errors=1)
运行于测试方法前,主要用于环境初始化
this is a test_isupper method
运行于测试方法后,主要用户环境数据清理
运行于测试方法前,主要用于环境初始化
this is a test_split method
运行于测试方法后,主要用户环境数据清理
运行于测试方法前,主要用于环境初始化
this is a test_upper method
运行于测试方法后,主要用户环境数据清理

Process finished with exit code 1

执行用例:

unittest框架建议在进行测试用例编写时,按照功能进行测试用例分组,unittest提供了一种机制:测试套件,由unittestTestSuite类表示。通常使用unittest.main(),它会自动收集所有模块的测试用例并执行它们。

有时候我们需要自定义测试套件的构建,需要自己进行测试套的添加。

  • 测试套可以放在相同的模块(例如:unittest_demo.py),针对当前测试模块,测试用例,测试方法
  • 测试套也可以放在一个脚本的入口模块中,例如run.py中,进行各个测试模块中细分的方法的执行

放在相同脚本的当中:

#!/user/bin/env python
# -*- coding: utf-8 -*-

"""
------------------------------------
@Project : mysite
@Time    : 2020/8/28 11:32
@Auth    : chineseluo
@Email   : 848257135@qq.com
@File    : unittest_demo.py
@IDE     : PyCharm
------------------------------------
"""
import unittest


class TestStringMethods(unittest.TestCase):
    def setUp(self):
        print("运行于测试方法前,主要用于环境初始化")

    def tearDown(self):
        print("运行于测试方法后,主要用户环境数据清理")

    def test_upper(self):
        print("this is a test_upper method")
        self.assertEqual('foo'.upper(), 'FOO')

    def test_isupper(self):
        self.assertTrue('FOO'.isupper())
        self.assertFalse('Foo'.isupper())

    def test_split(self):
        print("this is a test_split method")
        s = 'hello world'
        self.assertEqual(s.split(), ['hello', 'world'])
        # check that s.split fails when the separator is not a string
        with self.assertRaises(TypeError):
            s.split(2)


def suite():
    suite = unittest.TestSuite()
    suite.addTest(TestStringMethods('test_upper'))
    suite.addTest(TestStringMethods('test_isupper'))
    return suite


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

运行结果:
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK
运行于测试方法前,主要用于环境初始化
this is a test_upper method
运行于测试方法后,主要用户环境数据清理
运行于测试方法前,主要用于环境初始化
运行于测试方法后,主要用户环境数据清理

Process finished with exit code 0

放在不同的脚本中,通过导入需要进行自定义测试套件的模块下的测试类:

#!/user/bin/env python
# -*- coding: utf-8 -*-

"""
------------------------------------
@Project : mysite
@Time    : 2020/8/28 11:32
@Auth    : chineseluo
@Email   : 848257135@qq.com
@File    : unittest_demo.py
@IDE     : PyCharm
------------------------------------
"""
import unittest


class TestStringMethods(unittest.TestCase):
    def setUp(self):
        print("运行于测试方法前,主要用于环境初始化")

    def tearDown(self):
        print("运行于测试方法后,主要用户环境数据清理")

    def test_upper(self):
        print("this is a test_upper method")
        self.assertEqual('foo'.upper(), 'FOO')

    def test_isupper(self):
        self.assertTrue('FOO'.isupper())
        self.assertFalse('Foo'.isupper())

    def test_split(self):
        print("this is a test_split method")
        s = 'hello world'
        self.assertEqual(s.split(), ['hello', 'world'])
        # check that s.split fails when the separator is not a string
        with self.assertRaises(TypeError):
            s.split(2)


run.py

#!/user/bin/env python
# -*- coding: utf-8 -*-

"""
------------------------------------
@Project : mysite
@Time    : 2020/8/31 9:29
@Auth    : chineseluo
@Email   : 848257135@qq.com
@File    : run.py
@IDE     : PyCharm
------------------------------------
"""
import unittest
from unittest_demo import TestStringMethods


def suite():
    suite = unittest.TestSuite()
    suite.addTest(TestStringMethods('test_upper'))
    suite.addTest(TestStringMethods('test_isupper'))
    return suite


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

 

原文地址:https://www.cnblogs.com/chineseluo/p/13710492.html