Package cherrypy :: Package test :: Module helper
[hide private]
[frames] | no frames]

Source Code for Module cherrypy.test.helper

  1  """A library of helper functions for the CherryPy test suite. 
  2   
  3  The actual script that runs the entire CP test suite is called 
  4  "test.py" (in this folder); test.py calls this module as a library. 
  5   
  6  Usage 
  7  ===== 
  8  Each individual test_*.py module imports this module (helper), 
  9  usually to make an instance of CPWebCase, and then call testmain(). 
 10   
 11  The CP test suite script (test.py) imports this module and calls 
 12  run_test_suite, possibly more than once. CP applications may also 
 13  import test.py (to use TestHarness), which then calls helper.py. 
 14  """ 
 15   
 16  # GREAT CARE has been taken to separate this module from test.py, 
 17  # because different consumers of each have mutually-exclusive import 
 18  # requirements. So don't go moving functions from here into test.py, 
 19  # or vice-versa, unless you *really* know what you're doing. 
 20   
 21  import re 
 22  import sys 
 23  import thread 
 24   
 25  import cherrypy 
 26  from cherrypy.lib import http, profiler 
 27  from cherrypy.test import webtest 
 28   
 29   
30 -class CPWebCase(webtest.WebCase):
31 32 script_name = "" 33 scheme = "http" 34
35 - def prefix(self):
36 return self.script_name.rstrip("/")
37
38 - def base(self):
39 if ((self.scheme == "http" and self.PORT == 80) or 40 (self.scheme == "https" and self.PORT == 443)): 41 port = "" 42 else: 43 port = ":%s" % self.PORT 44 45 host = self.HOST 46 if not host: 47 # The empty string signifies INADDR_ANY, 48 # which should respond on localhost. 49 host = "127.0.0.1" 50 51 return "%s://%s%s%s" % (self.scheme, host, port, 52 self.script_name.rstrip("/"))
53
54 - def exit(self):
55 sys.exit()
56
57 - def tearDown(self):
58 pass
59
60 - def getPage(self, url, headers=None, method="GET", body=None, protocol=None):
61 """Open the url. Return status, headers, body.""" 62 if self.script_name: 63 url = http.urljoin(self.script_name, url) 64 webtest.WebCase.getPage(self, url, headers, method, body, protocol)
65
66 - def assertErrorPage(self, status, message=None, pattern=''):
67 """Compare the response body with a built in error page. 68 69 The function will optionally look for the regexp pattern, 70 within the exception embedded in the error page.""" 71 72 # This will never contain a traceback 73 page = cherrypy._cperror.get_error_page(status, message=message) 74 75 # First, test the response body without checking the traceback. 76 # Stick a match-all group (.*) in to grab the traceback. 77 esc = re.escape 78 epage = esc(page) 79 epage = epage.replace(esc('<pre id="traceback"></pre>'), 80 esc('<pre id="traceback">') + '(.*)' + esc('</pre>')) 81 m = re.match(epage, self.body, re.DOTALL) 82 if not m: 83 self._handlewebError('Error page does not match\n' + page) 84 return 85 86 # Now test the pattern against the traceback 87 if pattern is None: 88 # Special-case None to mean that there should be *no* traceback. 89 if m and m.group(1): 90 self._handlewebError('Error page contains traceback') 91 else: 92 if (m is None) or (not re.search(re.escape(pattern), m.group(1))): 93 msg = 'Error page does not contain %s in traceback' 94 self._handlewebError(msg % repr(pattern))
95 96 97 CPTestLoader = webtest.ReloadingTestLoader() 98 CPTestRunner = webtest.TerseTestRunner(verbosity=2) 99
100 -def setConfig(conf):
101 """Set the global config using a copy of conf.""" 102 if isinstance(conf, basestring): 103 # assume it's a filename 104 cherrypy.config.update(conf) 105 else: 106 cherrypy.config.update(conf.copy())
107 108
109 -def run_test_suite(moduleNames, server, conf):
110 """Run the given test modules using the given server and conf. 111 112 The server is started and stopped once, regardless of the number 113 of test modules. The config, however, is reset for each module. 114 """ 115 cherrypy.config.reset() 116 setConfig(conf) 117 cherrypy.server.quickstart(server) 118 # The Pybots automatic testing system needs the suite to exit 119 # with a non-zero value if there were any problems. 120 # Might as well stick it in the engine... :/ 121 cherrypy.engine.test_success = True 122 cherrypy.engine.start_with_callback(_run_test_suite_thread, 123 args=(moduleNames, conf)) 124 if cherrypy.engine.test_success: 125 return 0 126 else: 127 return 1
128
129 -def sync_apps(profile=False, validate=False, conquer=False):
130 apps = [] 131 for base, app in cherrypy.tree.apps.iteritems(): 132 if base == "/": 133 base = "" 134 if profile: 135 app = profiler.make_app(app, aggregate=False) 136 if conquer: 137 try: 138 import wsgiconq 139 except ImportError: 140 warnings.warn("Error importing wsgiconq. pyconquer will not run.") 141 else: 142 app = wsgiconq.WSGILogger(app) 143 if validate: 144 try: 145 from wsgiref import validate 146 except ImportError: 147 warnings.warn("Error importing wsgiref. The validator will not run.") 148 else: 149 app = validate.validator(app) 150 apps.append((base, app)) 151 apps.sort() 152 apps.reverse() 153 for s in cherrypy.server.httpservers: 154 s.mount_points = apps
155
156 -def _run_test_suite_thread(moduleNames, conf):
157 for testmod in moduleNames: 158 # Must run each module in a separate suite, 159 # because each module uses/overwrites cherrypy globals. 160 cherrypy.tree = cherrypy._cptree.Tree() 161 cherrypy.config.reset() 162 setConfig(conf) 163 164 m = __import__(testmod, globals(), locals()) 165 setup = getattr(m, "setup_server", None) 166 if setup: 167 setup() 168 169 # The setup functions probably mounted new apps. 170 # Tell our server about them. 171 sync_apps(profile=conf.get("profiling.on", False), 172 validate=conf.get("validator.on", False), 173 conquer=conf.get("conquer.on", False), 174 ) 175 176 suite = CPTestLoader.loadTestsFromName(testmod) 177 result = CPTestRunner.run(suite) 178 cherrypy.engine.test_success &= result.wasSuccessful() 179 180 teardown = getattr(m, "teardown_server", None) 181 if teardown: 182 teardown() 183 thread.interrupt_main()
184
185 -def testmain(conf=None):
186 """Run __main__ as a test module, with webtest debugging.""" 187 if conf is None: 188 conf = {'server.socket_host': '127.0.0.1'} 189 setConfig(conf) 190 try: 191 cherrypy.server.quickstart() 192 cherrypy.engine.start_with_callback(_test_main_thread) 193 except KeyboardInterrupt: 194 cherrypy.server.stop() 195 cherrypy.engine.stop()
196
197 -def _test_main_thread():
198 try: 199 webtest.WebCase.PORT = cherrypy.server.socket_port 200 webtest.main() 201 finally: 202 thread.interrupt_main()
203