/[thuban]/branches/WIP-pyshapelib-bramz/test/support.py
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/test/support.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 292 by bh, Fri Aug 30 09:44:12 2002 UTC revision 1574 by bh, Mon Aug 11 12:07:47 2003 UTC
# Line 1  Line 1 
1  # Copyright (c) 2002 by Intevation GmbH  # Copyright (c) 2002, 2003 by Intevation GmbH
2  # Authors:  # Authors:
3  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
4  #  #
# Line 21  def thuban_dir(): Line 21  def thuban_dir():
21      thisdir = os.path.dirname(__file__)      thisdir = os.path.dirname(__file__)
22      return os.path.join(thisdir, os.pardir)      return os.path.join(thisdir, os.pardir)
23    
24    def resource_dir():
25        return os.path.join(thuban_dir(), "Resources")
26    
27  def add_thuban_dir_to_path():  def add_thuban_dir_to_path():
28      """Insert the Thuban directory at the beginning of the python path.      """Insert the Thuban directory at the beginning of the python path.
# Line 46  def initthuban(): Line 48  def initthuban():
48          import thubaninit          import thubaninit
49          _initthuban_done = 1          _initthuban_done = 1
50    
 def run_suite(suite):  
     """Run the test suite suite and return the result"""  
     runner = unittest.TextTestRunner(verbosity = 2)  
     return runner.run(suite)  
51    
52    #
53    # Special test runner and result that support skipping tests
54    #
55    
56    class SkipTest(Exception):
57        """Exception to raise in tests that are skipped for some reason
58    
59        For instance, since gdal support is optional, test cases that
60        require gdal raise this exception to indicate that they are skipped.
61        Skipped is different from failure or error in that it is expected
62        under certain circumstances.
63        """
64    
65    class ThubanTestResult(unittest._TextTestResult):
66    
67        def __init__(self, stream, descriptions, verbosity):
68            unittest._TextTestResult.__init__(self, stream, descriptions,
69                                              verbosity)
70            self.skipped_tests = {}
71    
72        def add_skipped_test(self, test, exc):
73            reason = str(exc)
74            self.skipped_tests.setdefault(reason, []).append(test)
75    
76        def count_skipped(self):
77            sum = 0
78            for tests in self.skipped_tests.values():
79                sum += len(tests)
80            return sum
81    
82        def addError(self, test, err):
83            """Extend inherited method to handle SkipTest exceptions specially
84            """
85            #print "addError", test, err
86            if isinstance(err[1], SkipTest):
87                self.add_skipped_test(test, err[1])
88                if self.showAll:
89                    self.stream.writeln("skipped")
90                elif self.dots:
91                    self.stream.write('S')
92            else:
93                unittest._TextTestResult.addError(self, test, err)
94    
95        def printErrors(self):
96            if self.skipped_tests:
97                if self.dots or self.showAll:
98                    self.stream.writeln()
99                self.stream.writeln("Skipped tests:")
100                for reason, tests in self.skipped_tests.items():
101                    self.stream.writeln("%s:" % reason)
102                    for test in tests:
103                        self.stream.writeln("    " + test.id())
104            unittest._TextTestResult.printErrors(self)
105    
106    
107    class ThubanTestRunner(unittest.TextTestRunner):
108    
109        def _makeResult(self):
110            return ThubanTestResult(self.stream, self.descriptions, self.verbosity)
111    
112        def run(self, test):
113            result = unittest.TextTestRunner.run(self, test)
114            self.stream.writeln("skipped = %d" % result.count_skipped())
115            return result
116    
117    
118    class ThubanTestProgram(unittest.TestProgram):
119    
120        def runTests(self):
121            """Extend inherited method so that we use a ThubanTestRunner"""
122            print "ThubanTestProgram.runTests"
123            self.testRunner = ThubanTestRunner(verbosity = self.verbosity)
124            unittest.TestProgram.runTests(self)
125    
126    
127    def run_tests():
128        """Frontend for unittest.main that prints some additional debug information
129    
130        After calling unittest.main, run the garbage collector and print
131        uncollected objects. Also print any un-unsubscribed messages.
132        """
133        try:
134            ThubanTestProgram()
135        finally:
136            # This has to be in a finally clause because unittest.main()
137            # ends with a sys.exit to make sure that the process exits with
138            # an appropriate exit code
139            print_additional_summary()
140    
141    def print_additional_summary():
142        """Print some additional summary information after tests have been run"""
143        print_garbage_information()
144        import xmlsupport
145        xmlsupport.print_summary_message()
146    
147    def print_garbage_information():
148        """Print information about things that haven't been cleaned up.
149    
150        Run the garbage collector and print uncollected objects. Also print
151        any un-unsubscribed messages.
152        """
153        import gc, Thuban.Lib.connector
154        gc.collect()
155        if gc.garbage:
156            print
157            print "There are %d uncollected objects:" % len(gc.garbage)
158            print gc.garbage
159        Thuban.Lib.connector._the_connector.print_connections()
160    
161    #
162    
163  def create_temp_dir():  def create_temp_dir():
164      """Create a temporary directory and return its name.      """Create a temporary directory and return its name.
# Line 83  class FileTestMixin: Line 191  class FileTestMixin:
191      def temp_dir(self):      def temp_dir(self):
192          """Return the name of the directory for the temporary files"""          """Return the name of the directory for the temporary files"""
193          return create_temp_dir()          return create_temp_dir()
194    
195    
196    
197    class FileLoadTestCase(unittest.TestCase, FileTestMixin):
198    
199        """Base class for test case that test loading files.
200    
201        This base class provides some common infrastructure for testing the
202        reading of files.
203    
204        Each test case should be its own class derived from this one. There
205        is one file associated with each class. The contents are defined by
206        the file_contents class attribute and its name by the filename
207        method.
208    
209        Derived classes usually only have to provide appropriate values for
210        the file_contents and file_extension class attributes.
211        """
212    
213        file_contents = None
214        file_extension = ""
215    
216        def filename(self):
217            """Return the name of the test file to use.
218    
219            The default implementation simply calls self.volatile_file_name
220            with a basename derived from the class name by stripping off a
221            leading 'test_' and appending self.file_extension.
222            """
223            name = self.__class__.__name__
224            if name.startswith("test_"):
225                name = name[5:]
226            return self.temp_file_name(name + self.file_extension)
227    
228        def setUp(self):
229            """Create the volatile file for the test.
230    
231            Write self.contents (which should be a string) to the file named
232            by self.filename().
233            """
234            filename = self.filename()
235            file = open(filename, "w")
236            file.write(self.file_contents)
237            file.close()
238    
239    
240    class FloatComparisonMixin:
241    
242        """
243        Mixin class for tests comparing floating point numbers.
244    
245        This class provides a few methods for testing floating point
246        operations.
247        """
248    
249        fp_epsilon = 1e-6
250        fp_inf = float('1e1000')   # FIXME: hack for infinite
251    
252        def assertFloatEqual(self, test, value, epsilon = None):
253            """Assert equality of test and value with some tolerance.
254    
255            Assert that the absolute difference between test and value is
256            less than self.fp_epsilon.
257            """
258            if epsilon is None:
259                epsilon = self.fp_epsilon
260            if abs(test) == self.fp_inf:
261                self.assertEqual(test, value)
262            else:
263                self.assert_(epsilon > abs(test - value),
264                         "abs(%g - %g) >= %g" % (test, value, epsilon))
265    
266        def assertFloatSeqEqual(self, test, value, epsilon = None):
267            """Assert equality of the sequences test and value with some tolerance.
268    
269            Assert that the absolute difference between each corresponding
270            value in test and value is less than the optional parameter
271            epsilon. If epsilon is not given use self.fp_epsilon.
272            """
273            for i in range(len(test)):
274                self.assertFloatEqual(test[i], value[i], epsilon)
275    
276        def assertPointListEquals(self, test, value):
277            """Assert equality of two lists of lists of tuples of float
278    
279            This assertion is usually used to compare the geometry of shapes
280            as returned by a Shape object's Points() method, hence the name.
281            """
282            for i in range(len(test)):
283                self.assertEquals(len(test[i]), len(value[i]))
284                for j in range(len(test[i])):
285                    self.assertFloatSeqEqual(test[i][j], value[i][j])
286    
287    
288    class SubscriberMixin:
289    
290        """Mixin class for tests for messages sent through the Connector
291    
292        The SubscriberMixin has some methods that can be used as subscribers
293        of events that when called append information about the message into
294        a list of messages received.
295    
296        A derived class should call the clear_messages() method in both its
297        setUp and tearDown methods to clear the list of messages received.
298        """
299    
300        def clear_messages(self):
301            """Clear the list of received messages.
302    
303            Call this at least in the tests setUp and tearDown methods. It's
304            important to do it in tearDown too because otherwise there may
305            be cyclic references.
306            """
307            self.received_messages = []
308    
309        def subscribe_no_params(self):
310            """Method for subscriptions without parameters.
311    
312            Add an empty tuple to the list of received messages.
313            """
314            self.received_messages.append(())
315    
316        def subscribe_with_params(self, *args):
317            """Method for subscriptions with parameters.
318    
319            Append the tuple will all arguments to this function (except for
320            the self argument) to the list of received messages.
321            """
322            self.received_messages.append(args)
323    
324        def check_messages(self, messages):
325            """Check whether the messages received match the list messages"""
326            self.assertEquals(messages, self.received_messages)
327    

Legend:
Removed from v.292  
changed lines
  Added in v.1574

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26