Python UnitTest 文档中文翻译-4(渣翻自娱)

来源:互联网 发布:玩网络棋牌游戏犯法吗 编辑:程序博客网 时间:2024/05/16 12:56

25.3.4测试代码组织

单元测试的基本构建块是测试用例 – 必须设置和检查正确性的单个场景。在unittest中,测试用例由unittest的TestCase类的实例来表示。要创建自己的测试用例,必须编写TestCase的子类或者使用FunctionTestCase。

TestCase派生类的实例是一个可以完全运行单个测试方法的对象,并且可选的设置setup 和 tidyup代码。

TestCase实例的测试代码应该是完全自我包含的,这样它就可以独立运行,也可以与其它任意测试用例组合使用。

最简单的TestCase子类将简单的覆盖runTest()方法,以执行特定的测试代码:

class DefaultWidgetSizeTestCase(unittest.TestCase):    def runTest(self):        widget = Widget('The widget')        self.assertEqual(widget.size(), (50, 50), 'incorrect default size')

注意,为了测试某些东西,我们使用TestCase基类提供的assert*()方法之一。如果测试失败了,将会抛出一个异常,unittest将认定该测试用例为失败。任何其他的异常也会被视为错误。这可以帮助你确定失败原因 。

运行测试用例的方法稍后描述。现在,请注意,要构造一个测试用例的实例,我们不用参数的调用构造器。

testCase = DefaultWidgetSizeTestCase()

现在,这种测试可以是无穷多的,并且他们的setup可以是重复的。上述示例中,在每一百个 Widget 测试用例子类中构建一个 Widget 意味着会有一百个看不下去的重复==

幸运的是,我们可以通过实现setup()来提取这种设置代码,测试框架将在运行测试时自动
调用。

import unittestclass SimpleWidgetTestCase(unittest.TestCase):    def setUp(self):        self.widget = Widget('The widget')class DefaultWidgetSizeTestCase(SimpleWidgetTestCase):    def runTest(self):        self.assertEqual(self.widget.size(), (50,50),                         'incorrect default size')class WidgetResizeTestCase(SimpleWidgetTestCase):    def runTest(self):        self.widget.resize(100,150)        self.assertEqual(self.widget.size(), (100,150),                         'wrong size after resize')

如果setup() 方法抛出了异常,而测试还在运行, 框架会认为测试出错误了,然后runTest()方法就不会被执行。

相似的,我们提供一个tearUp()方法,该方法会在运行runTest()方法后会被清理掉。

import unittestclass SimpleWidgetTestCase(unittest.TestCase):    def setUp(self):        self.widget = Widget('The widget')    def tearDown(self):        self.widget.dispose()        self.widget = None

如果setUp()成功了,tearDown()方法会执行下去 无论runTest()成功运行与否。

这样的一个测试代码工作环境称为一个 fixture

通常,许多小的测试用例会使用相同的fixture。在这种情况下,我们最终将子类化SimpleWidgetTestCase 生成许多只有一个方法的小类例如DefaultWidgetSizeTestCase 。这样做很耗时,并不鼓励这样做,所以和JUnit一样,unittest 提供了一个更简单的机制。

import unittestclass WidgetTestCase(unittest.TestCase):    def setUp(self):        self.widget = Widget('The widget')    def tearDown(self):        self.widget.dispose()        self.widget = None    def test_default_size(self):        self.assertEqual(self.widget.size(), (50,50),                         'incorrect default size')    def test_resize(self):        self.widget.resize(100,150)        self.assertEqual(self.widget.size(), (100,150),                         'wrong size after resize')

这里我们没有提供runTest()方法,而是提供了两种不同的测试方法。
这样现在类实例就会和self一起运行test_*() 方法中的一个,并且会为每一个实例创建和销毁 self.widget 。

在创建实例时,我们必须指定测试要运行的测试方法。我们通过在构造函数中传递 方法名称来做到这一点。

defaultSizeTestCase = WidgetTestCase('test_default_size')resizeTestCase = WidgetTestCase('test_resize')

测试用例实例根据测试的特性组合在一起。unittest 提供了一种机制:suite 测试,由TestSuite类来表示。

widgetTestSuite = unittest.TestSuite()widgetTestSuite.addTest(WidgetTestCase('test_default_size'))widgetTestSuite.addTest(WidgetTestCase('test_resize'))

为了便于运行测试,我们稍后将看到,在每个测试模块中提供一个可调用的对象(返回一个预构建的suite测试)是一个很好的想法。

def suite():    suite = unittest.TestSuite()    suite.addTest(WidgetTestCase('test_default_size'))    suite.addTest(WidgetTestCase('test_resize'))    return suite

或者甚至:

def suite():    tests = ['test_default_size', 'test_resize']    return unittest.TestSuite(map(WidgetTestCase, tests))

由于创建一个具有许多类似命名的测试函数的 TestCase子类是一种常见的模式, unittest 提供了一个TestLoader类,可以用来自动化创建 测试Suite 的过程,并通过单独的测试来构成它。

suite = unittest.TestLoader().loadTestsFromTestCase(WidgetTestCase)

上述将创建一个测试 Suite,它将运行WidgetTestCase.test_default_size()和WidgetTestCase.test_resize。

TestLoader使用名称前缀(test*)来自动识别测试方法。

注意,不同测试用例运行的顺序是通过第字符串的内建排序来排序测试函数名确定的。

通常,将测试用例组合在一起是可取的,这样就可以一次运行整个系统的测试。

这很容易,因为TestSuite实例可以添加到TestSuite中,就像可以将TestCase实例添加到TestSuite中一样。

suite1 = module1.TheTestSuite()suite2 = module2.TheTestSuite()alltests = unittest.TestSuite([suite1, suite2])

你可以将测试用例和测试suite的定义放置在于测试代码相同的模块中,但是将测试代码方指定在单独测模块中有几个优势:

模块测试可以独立于命令行运行测试代码可以更容易的从已发布的代码中分离出来在没有充分理由的情况下,更改测试代码以符合其测试代码的 趋势 更小测试代码的修改要比它测试的代码少得多。测试代码可以更容易的重构
原创粉丝点击