unittest框架的学习心得

本文深入讲解unittest框架中的跳过测试和预期失败功能,并介绍如何通过测试套件控制测试用例的执行顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import unittest
class MyTest(unittest.TestCase):
    @unittest.skip("直接跳过测试")
    def test_skip(self):
        print("test aaa")
    @unittest.skipIf(3>2,"当条件为真时跳过测试")
    def test_skip_if(self):
        print('test bbb')
    @unittest.skipUnless(3>2,"当条件为真时执行测试")
    def test_skip_unless(self):
        print('test ccc')
    @unittest.expectedFailure
    def test_expected_failure(self):
        self.assertEqual(2,3)
if __name__ == '__main__':
    unittest.main()
  • 跳过测试和预期失败

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

    • 无条件地跳过装饰的测试,需要说明跳过测试的原因。

      unittest.skip(reason)

    • 如果条件为真,则跳过装饰的测试

      unittest.skipIF(condition,reason)

    • 当条件为真时,执行装饰的测试

      @unittest.skipUnless(3>2,"当条件为真时执行测试")

    • 不管执行结果是否失败,都将测试标记为失败。

      unittest.expectedFailure

  • 测试用例的执行顺序 

unittest提供了可以共享的defaultTestLoader类,可以使用其子类或方法创建实例,discover()方法就是其中之一。

unittest.defaultTestLoader.discover(start_dir,pattern='test*.py',top_level_dir=None)

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

  • start_dir:待测试的模块名或测试用例目录。
  • pattern='test.py':测试用例文件名的匹配原则。此处匹配文件名以“test”开头的“.py”类型的文件,星号“”表示任意多个字符。
  • top_level_dir=None:测试模块的顶层目录,如果没有顶层目录,则默认为None。

测试用例的执行顺序涉及多个层级:多个测试目录>多个测试文件>多个测试方法(测试用例)。unittest提供的main()方法和discover()方法是按照什么顺序查找测试用例的呢?

其实,unittest默认根据ASCII码的顺序加载测试用例的(数字与字母的顺序为0~9,A~Z,a~z),所以TestAdd类会优先于TestBdd类被执行,testaaa()方法会优先于test_ccc()方法被执行,也就是说,它并不是按照测试用例的创建顺序从上到下执行的

discover()方法和main()方法的执行顺序是一样的。对于测试目录与测试文件来说,上面的规律同样适用。test_aaa.py文件会优先于test_bbb.py文件被执行。所以,如果想让某个测试文件先执行,可以在命名上加以控制

当然,也可以用到前面介绍过的测试套件TestSuite,通过addTest()方法将测试用例加入测试套件,则会按照套件里的添加顺序去加载测试用例。

不过,当测试用例非常多时,不推荐用这种方法创建测试套件,最好的方法是通过命名控制执行顺序。如果测试用例在设计时不产生相互依赖,那么测试用例的执行顺序就没那么重要了。

以下抛弃了unittest提供的main()方法,调用TestSuite类下面的addTest()来添加测试用例。然后将Testsuite放入TestRunner里面进行启动。

import unittest
import Calculator

class TestCalculator(unittest.TestCase):

    def setUp(self):    #Test Fixture-每条用例开始执行前,执行该方法
        print("开始执行测试")

    def tearDown(self):  #Test Fixture-每条用例结束执行后,执行该方法
        print("执行测试结束")

    def test_add(self):
        result = Calculator.Add(1, 2)
        self.assertEqual(result, 3)


    def test_sub(self):
        result = Calculator.Substract(5, 1)
        self.assertEqual(result, 4)

    def test_mul(self):

        result = Calculator.Multiply(5, 1)
        self.assertEqual(result, 6)

    def test_div(self):
        result = Calculator.Divide(6, 2)
        self.assertEqual(result, 3)

if __name__ == '__main__':
    #创建测试套件TestSuite
    suit = unittest.TestSuite()
    suit.addTest(TestCalculator("test_add"))
    suit.addTest(TestCalculator("test_sub"))
    suit.addTest(TestCalculator("test_mul"))
    suit.addTest(TestCalculator("test_div"))

    #创建测试运行期TestRunner
    runner = unittest.TextTestRunner()
    runner.run(suit)

这样做比直接使用main()方法要麻烦得多,但也有优点,可灵活的控制用例的执行顺序。

  • 首先,测试用例的执行顺序可以由测试套件的添加顺序控制,而main()方法只能按照测试类、方法的名称来执行测试用例。例如,TestA类比TestB类先执行,test_add()用例比test_div()用例先执行。

  • 其次,当一个测试文件中有很多测试用例时,并不是每次都要执行所有的测试用例,尤其是比较耗时的U自动化测试。因而通过测试套件和测试运行器可以灵活地控制要执行的测试用例。

不过一个一个地添加测试用例到测试套件中,有点麻烦,所以可以把要执行的测试用例用个列表来管理,然后再把这个列表添加到测试套件中

import unittest
import Calculator

class TestCalculator(unittest.TestCase):

    def setUp(self):    #Test Fixture-每条用例开始执行前,执行该方法
        print("开始执行测试")

    def tearDown(self):  #Test Fixture-每条用例结束执行后,执行该方法
        print("执行测试结束")

    def test_add(self):
        result = Calculator.Add(1, 2)
        self.assertEqual(result, 3)


    def test_sub(self):
        result = Calculator.Substract(5, 1)
        self.assertEqual(result, 4)

    def test_mul(self):

        result = Calculator.Multiply(5, 1)
        self.assertEqual(result, 6)

    def test_div(self):
        result = Calculator.Divide(6, 2)
        self.assertEqual(result, 3)

if __name__ == '__main__':
    # 构造测试套件
    suite = unittest.TestSuite()
    test_cases = [TestCalculator("test_add"), TestCalculator("test_sub"), TestCalculator("test_div")]
    suite.addTests(test_cases)
    # 执行测试
    runner = unittest.TextTestRunner(
        verbosity=2)  # verbosity 参数可以控制输出的错误报告的详细程度,默认是 1;如果设为 0,则不输出每一用例的执行结果;如果设为 2,则输出详细的执行结果
    runner.run(suite)
unittest的setup、teardown会在每个用例执行前后执行一次,如上面测试用例类中有4个测试用例,
那么每个用例执行前会执行setup,执行后会执行teardown,即setup、teardown总共会调用4次,
但考虑实际自动化测试场景,多个用例只需执行一次setup,全部用例执行完成后,执行一次teardown,
针对该种场景,unittest的处理方法是使用setupclass、teardownclass,注意@classmethod的使用,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值