from google.appengine.ext import webapp from google.appengine.ext.webapp.util import run_wsgi_app from nose import core from nose import loader import sys sys.path.append('/home/praveen/testmelange/app/tests') from tests import online_run def getInvalidRequestArgs(request): """Validates the POST requests. """ valid_args = ['module','package','class','alltests','entity','submit'] invalid_args = [arg for arg in request.arguments() if arg not in valid_args] if len(invalid_args) > 0: return invalid_args else: return [] class PrepareForTests(webapp.RequestHandler): """Handler to prepare the tests which are to be executed. A suite is prepared and only the test ids are collected in the pre test run period. This is accomplished by using the --collect-only and --with-id plugin options of nose. The no. of test cases is passed to the javascript in client. """ def prepareSuite(self, name): """Prepare suite of tests """ test_loader = loader.TestLoader() suite = test_loader.loadTestsFromName(name) return suite def getNoOfTestCases(self, suite): """Return the number of Test Cases in suite """ return suite.countTestCases() def post(self): """ The POST request arguments are checked for invalid arguments. entity : entity can be any module, directory, class or test alltests: stores an integer value which is 1 if the radio button is selected """ invalid_arguments = getInvalidRequestArgs(self.request) if invalid_arguments: errors = ["The request parameter %s is invalid."%arg for arg in invalid_arguments] self.response.out.write(" ".join(errors)) return entity = self.request.get('entity') alltests = self.request.get('alltests') #path=os.getcwd() #self.response.out.write("alltests %s"%path) if entity and alltests: self.response.out.write("Please choose only one option") self.response.out.write(MAIN_PAGE_CONTENT) return if alltests == 1: self.suite = self.prepareSuite(path) else: self.suite = self.prepareSuite(entity) no_of_tests = self.getNoOfTestCases(self.suite) self.response.out.write(no_of_tests) #only for debugging args = ['--with-id', '--collect-only'] self.stream = self.response.out test_runner = core.TextTestRunner(stream=self.stream) runner = online_run.OnlineTestRunner(argv=args, testRunner=test_runner,suite=self.suite) runner.run() self.response.out.write(TEST_PAGE_CONTENT%no_of_tests) class RunTests(webapp.RequestHandler): """ This class runs the actual tests according to the test ids requested by the client. """ def get(self): requested_test_id = int(self.request.get('test_id')) self.stream = self.response.out args=['--with-id %d'%requested_test_id] test_runner = core.TextTestRunner(stream=self.request.out) runner = online_run.OnlineTestRunner(argv=args, testRunner=test_runner) class MainTestPageHandler(webapp.RequestHandler): def get(self): self.response.out.write(MAIN_PAGE_CONTENT) MAIN_PAGE_CONTENT = """ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1- transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Welcome to Melange Online Test Runner</title> </head> <body style = " background:#C3D9FF; font-family:Lucida Grande, Tahoma, Arial, Verdana, sans-serif;font-size:medium;margin:20px 0 16px; text-align:center;" > <div style="background:#fff;margin:25px 50px 75px 25%; text-align:left;width:650px;height:390px"> <form style=" font-family:Lucida Grande, Tahoma, Arial, Verdana, sans-serif;font-size:small;" method="post" action="runtest/prepare-run"> <div style = " border-bottom:1px dotted #ccc; clear:both; display:inline-block; margin:5px;"> <h2>Melange Online Test Runner</h2> </div> <ul style="list-style-type: none;"> <li> <label for="module_name">Test Module</label> <div style="width:78%"> <input id="module_name" name="entity" class="element text large" type="text" maxlength="255" value=""/> </div> <p style="width:90%"> <small> Enter the path to the test module using a dotted notation. For e.g app.soc.logic.test_allocation </small> </p> </li> <li> <span> <input id="all_tests" name="alltests" class="element radio" type="radio" value="1" /> <label style=" color:#444;font-size:100%; line-height:1.4em;margin:-1.55em 0 0 30px; width:100%;" for="alltests">Run all tests</label> </span> <p> <small><br/> Select this option if you want to run all the tests. </small> </p> </li> <li> <div style="margin-left:-3px;width:100%; background-color:#C3D9FF"> <input style="margin-left:30px; margin-top: 5px;" id="submitform" type="submit" name="submit" value="Run" /> </div> </li> </ul> </form> </div> </body> </html> """ TEST_PAGE_CONTENT = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1- transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Welcome to Melange Online Test Runner</title> <script language="javascript" type="text/javascript"> var totaltests = %s; function newXmlHttp() { try { return new XMLHttpRequest(); } catch(e) {} try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {} try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {} alert("XMLHttpRequest not supported"); return null; } function requestTestRun(testID) { var xmlHttp = newXmlHttp(); xmlHttp.open("GET", "/runtest/run?test_id=testID, true); xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState==4){ if (xmlHttp.status==200 || window.location.href.indexOf("http")==-1){ document.getElementById("result").innerHTML=xmlHttp.responseText } else{ alert("An error has occured making the request") } } }; xmlHttp.send(null); } function runTests() { // Run each test asynchronously (concurrently). var totalTests = parseInt(totaltests) for (var id = 1; i <=totalTests; i++) { requestTestRun(id); } } </script> </head> <body style = " background:#C3D9FF; font-family:Lucida Grande, Tahoma, Arial, Verdana, sans-serif;font-size:medium;margin:20px 0 16px; text-align:center;" > <div style="background: #000000;margin:25px auto 75px auto; text-align:left;width:800px;height:900px;"> <p style="color:#00FF00;align:left;padding:8px;font-size:15px; font-family:Courier,Arial, Verdana, sans-serif" id ='result'"> </p> </div> </body> </html>""" application = webapp.WSGIApplication( [('/runtest', MainTestPageHandler), ('/runtest/prepare-run',PrepareForTests), ('/runtest/run',RunTests)], debug=True) def main(): run_wsgi_app(application) if __name__ == "__main__": main()