Ticket #5596: names-examples-tests-5596.patch

File names-examples-tests-5596.patch, 4.0 KB (added by rwall, 4 years ago)

Some basic tests for these examples

  • twisted/names/test/test_examples.py

    === added file 'twisted/names/test/test_examples.py'
     
     1# Copyright (c) Twisted Matrix Laboratories.
     2# See LICENSE for details.
     3
     4"""
     5Tests for L{twisted.names.tap}.
     6"""
     7import os
     8import sys
     9from StringIO import StringIO
     10
     11from twisted.python.filepath import FilePath
     12from twisted.trial.unittest import SkipTest, TestCase
     13
     14
     15class ExampleTestBase(object):
     16    """
     17    This is a mixin which adds an example to the path, tests it, and then
     18    removes it from the path and unimports the modules which the test loaded.
     19    Test cases which test example code and documentation listings should use
     20    this.
     21
     22    This is done this way so that examples can live in isolated path entries,
     23    next to the documentation, replete with their own plugin packages and
     24    whatever other metadata they need.  Also, example code is a rare instance
     25    of it being valid to have multiple versions of the same code in the
     26    repository at once, rather than relying on version control, because
     27    documentation will often show the progression of a single piece of code as
     28    features are added to it, and we want to test each one.
     29    """
     30
     31    examplePath = None
     32
     33    def setUp(self):
     34        """
     35        Add our example directory to the path and record which modules are
     36        currently loaded.
     37        """
     38        self.fakeErr = StringIO()
     39        self.originalErr, sys.stderr = sys.stderr, self.fakeErr
     40        self.originalPath = sys.path[:]
     41        self.originalModules = sys.modules.copy()
     42        here = FilePath(__file__).parent().parent().parent().parent()
     43        for childName in self.examplePath:
     44            here = here.child(childName)
     45        if not here.exists():
     46            raise SkipTest("Examples (%s) not found - cannot test" % (here.path,))
     47        sys.path.append(here.parent().path)
     48        # Import the example as a module
     49        moduleName = here.basename().split('.')[0]
     50        self.example = __import__(moduleName)
     51        self.examplePath = here
     52
     53
     54    def tearDown(self):
     55        """
     56        Remove the example directory from the path and remove all modules loaded by
     57        the test from sys.modules.
     58        """
     59        sys.modules.clear()
     60        sys.modules.update(self.originalModules)
     61        sys.path[:] = self.originalPath
     62        sys.stderr = self.originalErr
     63
     64
     65    def test_executable(self):
     66        """
     67        The example scripts should start with the standard shebang
     68        line and should be executable.
     69        """
     70        self.assertEquals(
     71            self.examplePath.open().readline().rstrip(),
     72            '#!/usr/bin/env python')
     73
     74        mode = os.stat(self.examplePath.path).st_mode
     75        self.assertEquals(mode, 33277)
     76
     77
     78    def test_usage(self):
     79        """
     80        The example script prints a usage message to stderr and raises
     81        SystemExit if it is passed incorrect command line
     82        arguments. The first line should contain a USAGE summary and
     83        the last line should contain an ERROR, explaining that
     84        incorrect arguments were supplied.
     85        """
     86        self.assertRaises(SystemExit, self.example.main, None)
     87        err = self.fakeErr.getvalue().splitlines()
     88        self.assertEquals(err[0][:len('USAGE:')], 'USAGE:')
     89        self.assertEquals(err[-1][:len('ERROR:')], 'ERROR:')
     90
     91
     92class TestDnsTests(ExampleTestBase, TestCase):
     93    """
     94    Tests for the testdns.py example script.
     95    """
     96
     97    examplePath = 'doc/names/examples/testdns.py'.split('/')
     98
     99
     100class GetHostByNameTests(ExampleTestBase, TestCase):
     101    """
     102    Tests for the gethostbyname.py example script.
     103    """
     104
     105    examplePath = 'doc/names/examples/gethostbyname.py'.split('/')
     106
     107
     108class DnsServiceTests(ExampleTestBase, TestCase):
     109    """
     110    Tests for the dns-service.py example script.
     111    """
     112
     113    examplePath = 'doc/names/examples/dns-service.py'.split('/')