Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

root/branches/cherrypy-2.1/cherrypy/test/test.py

Revision 746 (checked in by rdelon, 3 years ago)

Removing VirtualHostFilter? for the 2.1 release

Line 
1 """
2 Copyright (c) 2004, CherryPy Team (team@cherrypy.org)
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8     * Redistributions of source code must retain the above copyright notice,
9       this list of conditions and the following disclaimer.
10     * Redistributions in binary form must reproduce the above copyright notice,
11       this list of conditions and the following disclaimer in the documentation
12       and/or other materials provided with the distribution.
13     * Neither the name of the CherryPy Team nor the names of its contributors
14       may be used to endorse or promote products derived from this software
15       without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
21 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 """
28
29 # This is the actual script that runs the entire CP test suite.
30 # There is a library of helper functions for the CherryPy test suite,
31 # called "helper.py" (in this folder); this module calls that as a library.
32 #
33 # GREAT CARE has been taken to separate this module from helper.py,
34 # because different consumers of each have mutually-exclusive import
35 # requirements. So don't go moving functions from here into helper.py,
36 # or vice-versa, unless you *really* know what you're doing.
37
38
39 import sys
40 import os, os.path
41 import webtest
42 import getopt
43
44
45 class TestHarness(object):
46    
47     """A test harness for the CherryPy framework and CherryPy applications."""
48    
49     # The first server in the list is the default server.
50     available_servers = {'serverless': (0, "Serverless", None),
51                          'native': (1, "Native HTTP Server",
52                                     "cherrypy._cphttpserver.embedded_server"),
53                          'wsgi': (2, "Native WSGI Server",
54                                   "cherrypy._cpwsgi.WSGIServer"),
55                          }
56     default_server = "wsgi"
57    
58     def __init__(self, available_tests):
59         """Constructor to populate the TestHarness instance.
60         
61         available_tests should be a list of module names (strings).
62         """
63         self.available_tests = available_tests
64        
65         self.cover = False
66         self.profile = False
67         self.protocol = "HTTP/1.0"
68         self.basedir = None
69         self.PORT = 8000
70        
71         self.servers = []
72         self.tests = []
73    
74     def load(self, args=sys.argv[1:]):
75         """Populate a TestHarness from sys.argv.
76         
77         args defaults to sys.argv[1:], but you can provide a different
78             set of args if you like.
79         """
80        
81         longopts = ['cover', 'profile', '1.1', 'help',
82                     'basedir=', 'all', 'port=']
83         longopts.extend(self.available_servers)
84         longopts.extend(self.available_tests)
85         try:
86             opts, args = getopt.getopt(args, "", longopts)
87         except getopt.GetoptError:
88             # print help information and exit
89             self.help()
90             sys.exit(2)
91        
92         self.cover = False
93         self.profile = False
94         self.protocol = "HTTP/1.0"
95         self.basedir = None
96        
97         self.servers = []
98         self.tests = []
99        
100         for o, a in opts:
101             if o == '--help':
102                 self.help()
103                 sys.exit()
104             elif o == "--cover":
105                 self.cover = True
106             elif o == "--profile":
107                 self.profile = True
108             elif o == "--1.1":
109                 self.protocol = "HTTP/1.1"
110             elif o == "--basedir":
111                 self.basedir = a
112             elif o == "--all":
113                 self.servers = self.available_servers.keys()
114             elif o == "--port":
115                 self.PORT = int(a)
116             else:
117                 o = o[2:]
118                 if o in self.available_servers and o not in self.servers:
119                     self.servers.append(o)
120                 elif o in self.available_tests and o not in self.tests:
121                     self.tests.append(o)
122        
123         if self.cover and self.profile:
124             # Print error message and exit
125             print ('Error: you cannot run the profiler and the '
126                    'coverage tool at the same time.')
127             sys.exit(2)
128        
129         if not self.servers:
130             self.servers = [self.default_server]
131        
132         if not self.tests:
133             self.tests = self.available_tests[:]
134    
135     def help(self):
136         """Print help for test.py command-line options."""
137        
138         print """CherryPy Test Program
139     Usage:
140         test.py --servers* --1.1 --cover --basedir=path --profile --tests**
141         
142     """
143         print '    * servers:'
144         s = [(val, name) for name, val in self.available_servers.iteritems()]
145         s.sort()
146         for val, name in s:
147             if name == self.default_server:
148                 print '        --' + name, '(default)'
149             else:
150                 print '        --' + name
151        
152         print """        --all (runs all servers in order)
153     
154     --1.1: use HTTP/1.1 servers instead of default HTTP/1.0
155     
156     --cover: turn on code-coverage tool
157     --basedir=path: display coverage stats for some path other than cherrypy.
158     
159     --profile: turn on profiling tool
160     """
161        
162         print '    ** tests:'
163         for name in self.available_tests:
164             print '        --' + name
165    
166     def start_coverage(self):
167         """Start the coverage tool.
168         
169         To use this feature, you need to download 'coverage.py',
170         either Gareth Rees' original implementation:
171         http://www.garethrees.org/2001/12/04/python-coverage/
172         
173         or Ned Batchelder's enhanced version:
174         http://www.nedbatchelder.com/code/modules/coverage.html
175         
176         If neither module is found in PYTHONPATH, coverage is disabled.
177         """
178         try:
179             from coverage import the_coverage as coverage
180             c = os.path.join(os.path.dirname(__file__), "../lib/coverage.cache")
181             coverage.cache_default = c
182             if c and os.path.exists(c):
183                 os.remove(c)
184             coverage.start()
185             import cherrypy
186             cherrypy.codecoverage = True
187         except ImportError:
188             coverage = None
189         self.coverage = coverage
190    
191     def stop_coverage(self):
192         """Stop the coverage tool, save results, and report."""
193         import cherrypy
194         cherrypy.codecoverage = False
195         if self.coverage:
196             self.coverage.save()
197             self.report_coverage()
198             print ("run cherrypy/lib/covercp.py as a script to serve "
199                    "coverage results on port 8080")
200    
201     def report_coverage(self):
202         """Print a summary from the code coverage tool."""
203        
204         basedir = self.basedir
205         if basedir is None:
206             # Assume we want to cover everything in "../../cherrypy/"
207             localDir = os.path.dirname(__file__)
208             basedir = os.path.normpath(os.path.join(os.getcwd(), localDir, '../'))
209         else:
210             if not os.path.isabs(basedir):
211                 basedir = os.path.normpath(os.path.join(os.getcwd(), basedir))
212         basedir = basedir.lower()
213        
214         self.coverage.get_ready()
215         morfs = [x for x in self.coverage.cexecuted
216                  if x.lower().startswith(basedir)]
217        
218         total_statements = 0
219         total_executed = 0
220        
221         print
222         print "CODE COVERAGE (this might take a while)",
223         for morf in morfs:
224             sys.stdout.write(".")
225             sys.stdout.flush()
226             name = os.path.split(morf)[1]
227             if morf.find('test') != -1:
228                 continue
229             try:
230                 _, statements, _, missing, readable  = self.coverage.analysis2(morf)
231                 n = len(statements)
232                 m = n - len(missing)
233                 total_statements = total_statements + n
234                 total_executed = total_executed + m
235             except KeyboardInterrupt:
236                 raise
237             except:
238                 # No, really! We truly want to ignore any other errors.
239                 pass
240        
241         pc = 100.0
242         if total_statements > 0:
243             pc = 100.0 * total_executed / total_statements
244        
245         print ("\nTotal: %s Covered: %s Percent: %2d%%"
246                % (total_statements, total_executed, pc))
247    
248     def run(self, conf=None):
249         """Run the test harness."""
250         self.load()
251        
252         # Start the coverage tool before importing cherrypy,
253         # so module-level global statements are covered.
254         if self.cover:
255             self.start_coverage()
256        
257         import cherrypy
258         v = sys.version.split()[0]
259         print "Python version used to run this test script:", v
260         print "CherryPy version", cherrypy.__version__
261         print
262        
263         if conf is None:
264             conf = {'server.socketHost': '127.0.0.1',
265                     'server.socketPort': self.PORT,
266                     'server.threadPool': 10,
267                     'server.logToScreen': False,
268                     'server.environment': "production",
269                     'server.showTracebacks': True,
270                     }
271         elif isinstance(conf, basestring):
272             conf = cherrypy.config.dict_from_config_file(conf)
273        
274         conf['server.protocolVersion'] = self.protocol
275        
276         if self.profile:
277             conf['profiling.on'] = True
278        
279         self._run_all_servers(conf)
280        
281         if self.profile:
282             del conf['profiling.on']
283             print
284             print ("run /cherrypy/lib/profiler.py as a script to serve "
285                    "profiling results on port 8080")
286        
287         if self.cover:
288             self.stop_coverage()
289    
290     def _run_all_servers(self, conf):
291         # helper must be imported lazily so the coverage tool
292         # can run against module-level statements within cherrypy.
293         # Also, we have to do a relative import here, not
294         # "from cherrypy.test import helper", because the latter
295         # would stick a second instance of webtest in sys.modules,
296         # and we wouldn't be able to globally override the port anymore.
297         import helper
298         s = [self.available_servers[name] for name in self.servers]
299         s.sort()
300         webtest.WebCase.PORT = self.PORT
301         for priority, name, cls in s:
302             print
303             print "Running tests:", name
304             helper.run_test_suite(self.tests, cls, conf)
305
306
307 class CPTestHarness(TestHarness):
308    
309     def _run_all_servers(self, conf):
310         # helper must be imported lazily so the coverage tool
311         # can run against module-level statements within cherrypy.
312         # Also, we have to do a relative import here, not
313         # "from cherrypy.test import helper", because the latter
314         # would stick a second instance of webtest in sys.modules,
315         # and we wouldn't be able to globally override the port anymore.
316         import helper, test_states
317         s = [self.available_servers[name] for name in self.servers]
318         s.sort()
319         webtest.WebCase.PORT = self.PORT
320         for priority, name, cls in s:
321             print
322             print "Running tests:", name
323             reload(test_states)
324             test_states.run(cls, conf)
325             helper.run_test_suite(self.tests, cls, conf)
326
327 def run():
328     # Place this __file__'s grandparent (../../) at the start of sys.path,
329     # so that all cherrypy/* imports are from this __file__'s package.
330     localDir = os.path.dirname(__file__)
331     curpath = os.path.normpath(os.path.join(os.getcwd(), localDir))
332     sys.path.insert(0, os.path.normpath(os.path.join(curpath, '../../')))
333    
334     testList = [
335         'test_baseurl_filter',
336         'test_cache_filter',
337         'test_combinedfilters',
338         'test_core',
339         'test_decodingencoding_filter',
340         'test_gzip_filter',
341         'test_logdebuginfo_filter',
342         'test_objectmapping',
343         'test_static_filter',
344         'test_tutorials',
345         #'test_virtualhost_filter',
346         'test_session_filter',
347         'test_sessionauthenticate_filter',
348         'test_xmlrpc_filter',
349     ]
350     CPTestHarness(testList).run()
351    
352     print
353     raw_input('hit enter')
354
355
356 if __name__ == '__main__':
357     run()
Note: See TracBrowser for help on using the browser.

Hosted by WebFaction

Log in as guest/cpguest to create tickets