Bug 429690: add ability to run browser tests individually, r=Mossop
authorGavin Sharp <gavin@mozilla.com>
Fri, 16 Jan 2009 14:19:25 -0500
changeset 23816 fe5e6c0bb20c49b26e07f37ab9aeec062590185e
parent 23815 d7c6fc72e3cd032ee4c24f903d58730336372dd3
child 23817 e81a52c40a43afc03a1a2be46fa67b37d9f452d1
push id4742
push usergsharp@mozilla.com
push dateFri, 16 Jan 2009 19:19:59 +0000
treeherdermozilla-central@ff4f631fe406 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMossop
bugs429690
milestone1.9.2a1pre
Bug 429690: add ability to run browser tests individually, r=Mossop
testing/mochitest/browser-harness.xul
testing/mochitest/browser-test.js
--- a/testing/mochitest/browser-harness.xul
+++ b/testing/mochitest/browser-harness.xul
@@ -37,27 +37,29 @@
    - the provisions above, a recipient may use your version of this file under
    - the terms of any one of the MPL, the GPL or the LGPL.
    -
    - ***** END LICENSE BLOCK ***** -->
 
 <window id="browserTestHarness"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         onload="TestStart();"
-        title="Browser chrome tests">
+        title="Browser chrome tests"
+        width="1024">
   <script src="chrome://mochikit/content/tests/SimpleTest/MozillaFileLogger.js"/>
   <script src="chrome://mochikit/content/tests/SimpleTest/quit.js"/>
   <style xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
     #results {
       margin: 5px;
       background-color: window;
       -moz-user-select: text;
     }
 
     #summary {
+      color: white;
       border: 2px solid black;
     }
 
     #summary.success {
       background-color: green;
     }
 
     #summary.failure {
@@ -82,17 +84,17 @@
     function TestStart() {
       gConfig = readConfig();
 
       // If MochiTest was started with the --test-path flag specifying a subset
       // of tests to run, put that path in the label of the "Run Tests" button
       // so the tester knows which tests will run when they press that button.
       if (gConfig.testPath)
         document.getElementById("runTestsButton").label =
-          "Run " + gConfig.testPath + " Tests";
+          "Run " + gConfig.testPath + " tests";
 
       if (gConfig.autoRun)
         setTimeout(runAllTests, 0);
     }
 
     function readConfig() {
       var fileLocator = Cc["@mozilla.org/file/directory_service;1"].
                         getService(Ci.nsIProperties);
@@ -182,37 +184,53 @@
     function listTests() {
       const Cc = Components.classes; const Ci = Components.interfaces;
 
       var ioSvc = Cc["@mozilla.org/network/io-service;1"].
                   getService(Ci.nsIIOService);
 
       var testsDir = getChromeDir();
       testsDir.appendRelativePath("browser");
+
+      var requestPath = "chrome://mochikit/content/browser";
+      var fileNameRegexp = /browser_.+\.js$/;
+
       if (gConfig.testPath) {
         var testsDirURI = ioSvc.newFileURI(testsDir);
         testsDir = ioSvc.newURI(gConfig.testPath, null, testsDirURI)
                         .QueryInterface(Ci.nsIFileURL).file;
+
+        // Invalid testPath...
+        if (!testsDir.exists())
+          return [];
+
+        // If we were passed a specific file, run only that test.
+        if (testsDir.isFile()) {
+          if (fileNameRegexp.test(testsDir.leafName))
+            return [new browserTestFile(requestPath + "/" + gConfig.testPath)];
+
+          // We were passed a file that's not a test...
+          return [];
+        }
+
+        // otherwise, we were passed a directory of tests
+        requestPath += "/" + gConfig.testPath;
       }
 
-      /** load server.js in so we can share template functions **/
+      // load server.js in so we can share template functions
       var scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
                          getService(Ci.mozIJSSubScriptLoader);
       var srvScope = {};
       scriptLoader.loadSubScript("chrome://mochikit/content/server.js", srvScope);
 
-      var requestPath = "chrome://mochikit/content/browser";
-      if (gConfig.testPath)
-        requestPath += "/" + gConfig.testPath;
+      var [links, ] = srvScope.list(requestPath, testsDir, true);
+      var fileNames = [];
+      srvScope.arrayOfTestFiles(links, fileNames, fileNameRegexp);
 
-      var [links, count] = srvScope.list(requestPath, testsDir, true);
-      var fileNames = [];
-      srvScope.arrayOfTestFiles(links, fileNames, /browser_.+\.js$/);
-
-      return fileNames.map(function (f) new browserTestFile(f));;
+      return fileNames.map(function (f) new browserTestFile(f));
     }
 
     function setStatus(aStatusString) {
       document.getElementById("status").value = aStatusString;
     }
 
     function runAllTests() {
       var windowMediator = Cc['@mozilla.org/appshell/window-mediator;1'].
@@ -221,20 +239,27 @@
 
       setStatus("Running...");
       testWin.focus();
 
       var Tester = new testWin.Tester(listTests(), testsFinished);
       Tester.start();
     }
 
+    function sum(a, b) {
+      return a + b;
+    }
+
     function getHTMLLogFromTests(aTests) {
+      if (!aTests.length)
+        return "<div id=\"summary\" class=\"success\">No tests to run. " +
+               "Did you pass an invalid --test-path?</div>";
+
       var log = "";
 
-      function sum(a, b){ return a + b; }
       var passCount = aTests.map(function (f) f.passCount).reduce(sum);
       var failCount = aTests.map(function (f) f.failCount).reduce(sum);
       var todoCount = aTests.map(function (f) f.todoCount).reduce(sum);
       log += "<div id=\"summary\" class=\"";
       log += failCount == 0 ? "success" : "failure";
       log += "\">\n<p>Passed: " + passCount + "</p>\n" +
              "<p>Failed: " + failCount + "</p>\n" +
              "<p>Todo: " + todoCount + "</p>\n</div>\n<div id=\"log\">\n";
@@ -250,17 +275,17 @@
 
       var log = aTests.map(function (f) {
                              var output = f.path + "\n";
                              if (f.log)
                                output += f.log + "\n";
                              return output;
                            }).join("");
       log += "\nBrowser Chrome Test Summary\n";
-      function sum(a, b){ return a + b; }
+
       var passCount = aTests.map(function (f) f.passCount).reduce(sum);
       var failCount = aTests.map(function (f) f.failCount).reduce(sum);
       var todoCount = aTests.map(function (f) f.todoCount).reduce(sum);
       log += "\tPass: " + passCount + "\n\tFail: " + failCount + "\n\tTodo: " + todoCount + "\n";
 
       return log;
     }
 
@@ -290,11 +315,11 @@
       // UI
       document.getElementById("results").innerHTML = getHTMLLogFromTests(aTests);
       setStatus("Done.");
     }
   ]]></script>
   <button id="runTestsButton" onclick="runAllTests();" label="Run All Tests"/>
   <label id="status"/>
   <scrollbox flex="1" style="overflow: auto" align="stretch">
-    <div id="results" xmlns="http://www.w3.org/1999/xhtml"/>
+    <div id="results" xmlns="http://www.w3.org/1999/xhtml" flex="1"/>
   </scrollbox>
 </window>
--- a/testing/mochitest/browser-test.js
+++ b/testing/mochitest/browser-test.js
@@ -37,17 +37,20 @@ Tester.prototype = {
   get done() {
     return this.currentTestIndex == this.tests.length - 1;
   },
   step: function Tester_step() {
     this.currentTestIndex++;
   },
 
   start: function Tester_start() {
-    this.execTest();
+    if (this.tests.length)
+      this.execTest();
+    else
+      this.finish();
   },
 
   finish: function Tester_finish() {
     // Tests complete, notify the callback and return
     this.callback(this.tests);
     this.callback = null;
     this.tests = null;
   },