Unittest框架的从零到壹(三)

1.测试用例的组织与discover方法

一个功能对应一条测试用例显然是不够的,要写多少测试用例取决于你对功能需求与测试方法的理解。

其次,是测试用例的划分,建议一个测试类对应一个被测试功能。

例如这样

class TestAdd(unittest.TestCase):
    """add()方法测试"""
    
    def test_add1(self):
        """整数相加测试"""
        c= Calculator(1,2)
        result = c.add()
        self.assertEqual(result,3)
    
    def test_add2(self):
        """小数相加测试"""
        c= Calculator(1.1,2.3)
        result = c.add()
        self.assertEqual(result,3)
        
    def test_add3(self):
        """字符串整数相加测试"""
        c= Calculator("1","2")
        result = c.add()
        self.assertEqual(result,3)

我们可以在一个测试文件中定义多个测试类,只要它们遵循测试用例的“规则”,main0方法就可以找到并执行它们。但是,我们要测试的类或方法可能有很多。

下面假设开发了一个登录功能,创建login.py文件。创建对应的测试文件test_login.py。

当前目录结构如下

![image-20191015150101430](/Users/x1you/Library/Application Support/typora-user-images/image-20191015150101430.png)

如何执行多个测试文件呢?unittest中的TestLoader类提供的discover()方法可以从多个文件中查找测试用该类根据各种标准加载测试用例,并将它们返回给测试套件。正常情况下,不需要创建这个类的实例。

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。

现在通过discover0方法重新实现run_tests.py文件的功能。

discover()方法会自动根据测试用例目录(test_dir)查找测试用例文件(test*.py),并将找到的测试用例添加到测试套件中,因此,可以直接通过run()方法执行测试套件suits。这种方式极大地简化了测试用例的查找,我们需要做的就是按照文件的匹配规则创建测试文件即可。

2.关于unittest还需要知道的

  • 测试用例的执行顺序

    测试用例的执行顺序涉及多个层级:多个测试目录>多个测试文件>多个测试方法(测试用例)。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()方法将测试用例加入测试套件,则会按照套件里的添加顺序去加载测试用例。

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

  • 执行多级目录的测试用例

    ![image-20191018094430243](/Users/x1you/Library/Application Support/typora-user-images/image-20191018094430243.png)

    对于上面的目录结构,如果将discove()方法中的start_dir参数定义为"/test_case”目录,那么只能加载test_logout.py文件中的测试用例。如何让unittest查找test case/下子目录中的测试文件呢?方法很简单,就是在每个子目录下放一个__init__.py文件。__init__.py文件的作用是将一个目录标记成一个标准的Python模块。

  • 跳过测试和预期失败

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

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

      unittest.skip(reason)

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

      unittest.skipIF(condition,reason)

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

      unittest.expecteFailure()

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

      unittest.expectedFailure

如下:

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')
    
  @unitest.expectedFailure
  def test_expected_failure(self):
    self.assertEqual(2,3)
    
if__name__ == '__main__':
  unittest.main()
原文地址:https://www.cnblogs.com/x1you/p/11989253.html