There are two ways unit tests can be written in Zope 3. The first one is through special TestCase classes using the unittest package, which was modeled after JUnit. The second technique is writing tests inside doc strings, which are commonly known as doc tests.

Zope 3中有两种方式进行单元测试的编写。第一种是通过专门的使用unittest包的TestCase类,这是借鉴JUnit构建的测试模型。第二种技术是在doc strings中编写单元测试,这种方式常被称为 doc tests。

Late in the development of Zope 3 doc tests became the standard way of writing tests. For philosophical and technical differences between the two approaches, see the section on “Writing Tests”, especially the “Writing Basic Unit Tests” and “Doctests: Example-driven Unit Tests” chapters.

在今后的Zope3 的开发中,文档测试将成为编写单元测试的编著方法。要了解这两种技术的详细信息,常见“编写测试”章节,特别是“编写基础单元测试”和“Doctests:案例驱动的单元测试”章节。

Common unit tests, however, are of advantage when it is desirable to reuse abstract tests, as it is the case for various container tests. Therefore, we will use unit tests for the container tests and doc tests for everything else.

通用的单元测试,在需要重用抽象测试时具有优点,因为这是各种容器测试需要的情形。因此,我们将为容器测试采用单元测试,而对任何其他东西采用文档测试。

First, create a package called tests inside the messageboard package. Note that calling the test module tests (file-based test modules would be called tests.py) is a convention throughout Zope 3 and will allow the automated test runner to pick up the tests.

首先,在messageboard包中创建一个名为tests的包。注意:Zope3中将此测试模块预定称为tests(基于文件的测试模块应当命名为tests.py),这样自动测试运行器会运行该测试。

Next, start to edit a file called test_messageboard.py and insert:

下一步,开始编辑名为test_messageboard.py的文件,并插入以下代码:

10 11 def makeTestObject(self): 12 return MessageBoard() 13 14 def test_suite(): 15 return unittest.TestSuite(( 16 DocTestSuite('book.messageboard.messageboard'), 17 unittest.makeSuite(Test), 18 )) 19 20 if name == 'main': 21 unittest.main(defaultTest='test_suite')

A lot of cool stuff just happened here. You just got your first 12 unit tests. Let’s have a closer look:

在此有许多很酷的东西第一次遇到。你只要看你的前12行的单元测试。让我们仔细看看这些代码:

  • Line 1: The unittest module comes with stock Python and is used to create the test suite.
  • 第一行:Python自带的unittest模块用来创建测试套件。
  • Line 2: Zope provides a specialized DocTestSuite that integrates doc tests into the common unittest framework and allows the doc tests to be run via the test runner.

  • 第二行:Zope提供了一个专用的DocTestSuite,该测试套件把文档测试集成到通用的单元测试框架中,并且使得文档测试可以通过测试运行器来运行。

  • Line 4: There are some basic tests for containers, so we should import them. Freebie tests are always good.
  • 第四行:对于容器,有一些基本的测试,因此我们要把他们导入进来。免费的测试件总是好的。
  • Line 9-13: Define the Container tests. We only have to provide an instance of the container we would like to be tested as the return value of the makeTestObject() method.
  • 第九行-第十三行:定义容器的测试。我们只需要提供要测试容器的实例作为makeTestObject()方法的返回值就可以了。
  • Line 15-19: The test_suite() method collects all the defined test cases and compiles them into one test suite. This method must always be named that way, so that the test runner picks up the suite.

Besides the container test, we also already register the doc tests.

  • 第15-19行:test_suite()方法收集所有已经定义的测试案例,并将他们编入一个测试套件中。该方法必须总是这样命名,这样测试运行器才能够识别到该套件。除了这个容器测试件以外,我们同时还注册了文档测试件。
  • Line 21-23: We also want to allow any test module to be executable by itself. Here we just tell the test runner to execute all tests of the test suite returned by test_suite(). These lines are common boilerplate for any test module in Zope 3.
  • 第21-23行:我们还要让所有的测试模块能够自己执行。在此,我们只要告诉测试运行器执行所有test_suite()所返回测试套件的所有测试件。在Zope3的任何测试模块中,这几行是通用的模板。

Now it is time to do the second test module for the IMessage component. To start, we simply copied the test_messageboard.py to test_message.py and modified the new file to become:

现在,我们要为IMessage组件编写第二个测试模块。我们把test_messageboard.py拷贝成test_message.py,然后把新文件改为:

10 11 def makeTestObject(self): 12 return Message() 13 14 def test_suite(): 15 return unittest.TestSuite(( 16 DocTestSuite('book.messageboard.message'), 17 unittest.makeSuite(Test), 18 )) 19 20 if name == 'main': 21 unittest.main(defaultTest='test_suite')

There is not really any difference between the two testing modules, so that I am not going to point out the same facts again.

这两个测试模块没有任何本质的区别,因此我就不再逐点列出同样的代码说明了。

Note that none of the tests deal with implementation details yet, simply because we do not know what the implementation details will be. These test could be used by other packages, just as we used the SampleContainer base tests, since these tests only depend on the API. In general, however, tests should cover implementation-specific behavior.

注意这些测试都还没有处理具体的实现细节,因为我们我们还不知道具体的实现细节会是什么样的。就像我们使用SampleContainer基础测试件一样,这些测试件可以被其他包使用,因为这些测试仅仅依赖于API。当然,通常来说,测试应当涵盖具体实现的行为。