单元测试与技术探究

    作为面向对象设计的一部分,通常会创建一个类似本节代码中所演示的技术探究模块,我们会把它分为3个部分。首先,是以下这个全局的抽象类。

    import types
    import unittest

    class TestAccess( unittest.TestCase ):
      def test_should_add_and_get_attribute( self ):
        self.object.new_attribute= True
        self.assertTrue( self.object.new_attribute )
      def test_should_fail_on_missing( self ):
        self.assertRaises( AttributeError, lambda: self.object.
    undefined )

    抽象类TestCase的子类中定义了一些希望类可以通过的测试。实际被测试的对象被忽略了。它通过self.object被引用,但是没有提供定义,使得TestCase子类保持抽象。每个具体类都会需要setUp()方法。

    以下是3个具体的TestAccess子类,会包含以下3种不同对象的测试。

    class SomeClass:
      pass
    class Test_EmptyClass( TestAccess ):
      def setUp( self ):
        self.object= SomeClass()
    class Test_Namespace( TestAccess ):
      def setUp( self ):
        self.object= types.SimpleNamespace()
    class Test_Object( TestAccess ):
      def setUp( self ):
        self.object= object()

    TestAccess类的每个子类都提供了所需要的setUp()方法。每个方法创建了一种不同的被测试对象。第1个是空类的实例。第2个是types.SimpleNamespace的实例。第3个是object的实例。

    为了运行这些测试,需要创建一个组件,来阻止我们运行TestAccess抽象类的测试。

    以下是探究的其余部分。

    def suite():
      s= unittest.TestSuite()
      s.addTests( unittest.defaultTestLoader.loadTestsFromTestCase(Test
    EmptyClass) )
      s.addTests( unittest.defaultTestLoader.loadTestsFromTestCase(Test

    Namespace) )
      s.addTests( unittest.defaultTestLoader.loadTestsFromTestCase(Test
    Object) )
      return s

    if name == "_main
    ":
      t= unittest.TextTestRunner()
      t.run( suite() )

    现在我们得到了具体的证据,object类的使用方式与其他类是不同的。进一步说,我们有了一个可以用于演示其他可行(或不可行)设计的测试。例如,用于演示types. SimpleNamespace作为空类行为的测试。

    我们跳过了很多单元测试用例的细节,会在第15章“可测试性的设计”中进行详细介绍。