/[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 596 by bh, Thu Apr 3 11:37:01 2003 UTC revision 1673 by bh, Thu Aug 28 13:04:44 2003 UTC
# Line 15  __version__ = "$Revision$" Line 15  __version__ = "$Revision$"
15    
16  import os, sys  import os, sys
17  import unittest  import unittest
18    import traceback
19    
20    import postgissupport
21    
22    
23  def thuban_dir():  def thuban_dir():
24      """Return the directory containing the Thuban package"""      """Return the directory containing the Thuban package"""
25      thisdir = os.path.dirname(__file__)      thisdir = os.path.dirname(__file__)
26      return os.path.join(thisdir, os.pardir)      return os.path.join(thisdir, os.pardir)
27    
28    def resource_dir():
29        return os.path.join(thuban_dir(), "Resources")
30    
31  def add_thuban_dir_to_path():  def add_thuban_dir_to_path():
32      """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 52  def initthuban():
52          import thubaninit          import thubaninit
53          _initthuban_done = 1          _initthuban_done = 1
54    
 def run_tests():  
     """Frontend for unittest.main that prints some additional debug information  
55    
56      After calling unittest.main, run the garbage collector and print  #
57      uncollected objects. Also print any un-unsubscribed messages.  # Special test runner and result that support skipping tests
58    #
59    
60    class SkipTest(Exception):
61        """Exception to raise in tests that are skipped for some reason
62    
63        For instance, since gdal support is optional, test cases that
64        require gdal raise this exception to indicate that they are skipped.
65        Skipped is different from failure or error in that it is expected
66        under certain circumstances.
67        """
68    
69    class ThubanTestResult(unittest._TextTestResult):
70    
71        def __init__(self, stream, descriptions, verbosity):
72            unittest._TextTestResult.__init__(self, stream, descriptions,
73                                              verbosity)
74            self.skipped_tests = {}
75    
76        def add_skipped_test(self, test, exc):
77            reason = str(exc)
78            self.skipped_tests.setdefault(reason, []).append(test)
79    
80        def count_skipped(self):
81            sum = 0
82            for tests in self.skipped_tests.values():
83                sum += len(tests)
84            return sum
85    
86        def addError(self, test, err):
87            """Extend inherited method to handle SkipTest exceptions specially
88            """
89            #print "addError", test, err
90            if isinstance(err[1], SkipTest):
91                self.add_skipped_test(test, err[1])
92                if self.showAll:
93                    self.stream.writeln("skipped")
94                elif self.dots:
95                    self.stream.write('S')
96            else:
97                unittest._TextTestResult.addError(self, test, err)
98    
99        def printErrors(self):
100            if self.skipped_tests:
101                if self.dots or self.showAll:
102                    self.stream.writeln()
103                self.stream.writeln("Skipped tests:")
104                for reason, tests in self.skipped_tests.items():
105                    self.stream.writeln("  %s:" % reason)
106                    for test in tests:
107                        self.stream.writeln("    " + test.id())
108            unittest._TextTestResult.printErrors(self)
109    
110    
111    class ThubanTestRunner(unittest.TextTestRunner):
112    
113        def _makeResult(self):
114            return ThubanTestResult(self.stream, self.descriptions, self.verbosity)
115    
116        def run(self, test):
117            result = unittest.TextTestRunner.run(self, test)
118            self.stream.writeln("skipped = %d" % result.count_skipped())
119            return result
120    
121    
122    class ThubanTestProgram(unittest.TestProgram):
123    
124        def runTests(self):
125            """Extend inherited method so that we use a ThubanTestRunner"""
126            self.testRunner = ThubanTestRunner(verbosity = self.verbosity)
127            unittest.TestProgram.runTests(self)
128    
129    
130    def execute_as_testsuite(callable, *args, **kw):
131        """Call callable  with args as if it were the entry point to the test suite
132    
133        Return watever callable returns.
134    
135        This is a helper function for run_tests and runtests.py. Call
136        callable in a try-finally block and run some cleanup and print some
137        additional information in the finally block.
138    
139        The additionaly information include:
140    
141         - A list of uncollected objects (after an explicit garbage
142           collector call)
143    
144         - any unsubscribed messages
145      """      """
146      try:      try:
147          unittest.main()          return callable(*args, **kw)
148      finally:      finally:
149          # This has to be in a finally clause because unittest.main()          # This has to be in a finally clause because unittest.main()
150          # ends with a sys.exit to make sure that the process exits with          # ends with a sys.exit to make sure that the process exits with
151          # an appropriate exit code          # an appropriate exit code
152          print_garbage_information()  
153            # Shutdown the postgis server if it's running
154            try:
155                postgissupport.shutdown_test_server()
156            except:
157                traceback.print_exc()
158    
159            # Print additional information
160            print_additional_summary()
161    
162    def run_tests():
163        """Frontend for unittest.main that prints some additional debug information
164    
165        After calling unittest.main, run the garbage collector and print
166        uncollected objects. Also print any un-unsubscribed messages.
167        """
168        execute_as_testsuite(ThubanTestProgram)
169    
170    
171    def print_additional_summary():
172        """Print some additional summary information after tests have been run"""
173        print_garbage_information()
174        import xmlsupport
175        xmlsupport.print_summary_message()
176    
177  def print_garbage_information():  def print_garbage_information():
178      """Print information about things that haven't been cleaned up.      """Print information about things that haven't been cleaned up.
# Line 66  def print_garbage_information(): Line 180  def print_garbage_information():
180      Run the garbage collector and print uncollected objects. Also print      Run the garbage collector and print uncollected objects. Also print
181      any un-unsubscribed messages.      any un-unsubscribed messages.
182      """      """
183        # this function may be called indirectly from test cases that test
184        # test support modules which do not use anything from thuban itself,
185        # so we call initthuban so that we can import the connector module
186        initthuban()
187      import gc, Thuban.Lib.connector      import gc, Thuban.Lib.connector
188      gc.collect()      gc.collect()
189      if gc.garbage:      if gc.garbage:
# Line 74  def print_garbage_information(): Line 192  def print_garbage_information():
192          print gc.garbage          print gc.garbage
193      Thuban.Lib.connector._the_connector.print_connections()      Thuban.Lib.connector._the_connector.print_connections()
194    
195    #
196    
197  def create_temp_dir():  def create_temp_dir():
198      """Create a temporary directory and return its name.      """Create a temporary directory and return its name.
# Line 108  class FileTestMixin: Line 227  class FileTestMixin:
227          return create_temp_dir()          return create_temp_dir()
228    
229    
230    
231    class FileLoadTestCase(unittest.TestCase, FileTestMixin):
232    
233        """Base class for test case that test loading files.
234    
235        This base class provides some common infrastructure for testing the
236        reading of files.
237    
238        Each test case should be its own class derived from this one. There
239        is one file associated with each class. The contents are defined by
240        the file_contents class attribute and its name by the filename
241        method.
242    
243        Derived classes usually only have to provide appropriate values for
244        the file_contents and file_extension class attributes.
245        """
246    
247        file_contents = None
248        file_extension = ""
249    
250        def filename(self):
251            """Return the name of the test file to use.
252    
253            The default implementation simply calls self.volatile_file_name
254            with a basename derived from the class name by stripping off a
255            leading 'test_' and appending self.file_extension.
256            """
257            name = self.__class__.__name__
258            if name.startswith("test_"):
259                name = name[5:]
260            return self.temp_file_name(name + self.file_extension)
261    
262        def setUp(self):
263            """Create the volatile file for the test.
264    
265            Write self.contents (which should be a string) to the file named
266            by self.filename().
267            """
268            filename = self.filename()
269            file = open(filename, "w")
270            file.write(self.file_contents)
271            file.close()
272    
273    
274  class FloatComparisonMixin:  class FloatComparisonMixin:
275    
276      """      """
# Line 118  class FloatComparisonMixin: Line 281  class FloatComparisonMixin:
281      """      """
282    
283      fp_epsilon = 1e-6      fp_epsilon = 1e-6
284            fp_inf = float('1e1000')   # FIXME: hack for infinite
285      def assertFloatEqual(self, test, value):  
286        def assertFloatEqual(self, test, value, epsilon = None):
287          """Assert equality of test and value with some tolerance.          """Assert equality of test and value with some tolerance.
288    
289          Assert that the absolute difference between test and value is          Assert that the absolute difference between test and value is
290          less than self.fp_epsilon.          less than self.fp_epsilon.
291          """          """
292          self.assert_(self.fp_epsilon > abs(test - value),          if epsilon is None:
293                       "abs(%g - %g) >= %g" % (test, value, self.fp_epsilon))              epsilon = self.fp_epsilon
294            if abs(test) == self.fp_inf:
295                self.assertEqual(test, value)
296            else:
297                self.assert_(epsilon > abs(test - value),
298                         "abs(%g - %g) >= %g" % (test, value, epsilon))
299    
300      def assertFloatSeqEqual(self, test, value, epsilon = None):      def assertFloatSeqEqual(self, test, value, epsilon = None):
301          """Assert equality of the sequences test and value with some tolerance.          """Assert equality of the sequences test and value with some tolerance.
# Line 135  class FloatComparisonMixin: Line 304  class FloatComparisonMixin:
304          value in test and value is less than the optional parameter          value in test and value is less than the optional parameter
305          epsilon. If epsilon is not given use self.fp_epsilon.          epsilon. If epsilon is not given use self.fp_epsilon.
306          """          """
         if epsilon is None:  
             epsilon = self.fp_epsilon  
307          for i in range(len(test)):          for i in range(len(test)):
308              self.assert_(epsilon > abs(test[i] - value[i]),              self.assertFloatEqual(test[i], value[i], epsilon)
309                           "abs(%g - %g) >= %g" % (test[i], value[i], epsilon))  
310        def assertPointListEquals(self, test, value):
311            """Assert equality of two lists of lists of tuples of float
312    
313            This assertion is usually used to compare the geometry of shapes
314            as returned by a Shape object's Points() method, hence the name.
315            """
316            for i in range(len(test)):
317                self.assertEquals(len(test[i]), len(value[i]))
318                for j in range(len(test[i])):
319                    self.assertFloatSeqEqual(test[i][j], value[i][j])
320    
321    
322  class SubscriberMixin:  class SubscriberMixin:
# Line 181  class SubscriberMixin: Line 358  class SubscriberMixin:
358      def check_messages(self, messages):      def check_messages(self, messages):
359          """Check whether the messages received match the list messages"""          """Check whether the messages received match the list messages"""
360          self.assertEquals(messages, self.received_messages)          self.assertEquals(messages, self.received_messages)
361    

Legend:
Removed from v.596  
changed lines
  Added in v.1673

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26