Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files
factored couch_test_runner.js out from couch_tests.js, made it usuabl…
…e for unit testing views from design docs

git-svn-id: https://svn.apache.org/repos/asf/incubator/couchdb/trunk@718409 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
jchris committed Nov 17, 2008
1 parent f20583f commit 549caca57ac0adc0ec5cd89837303313ca96bc53
Showing 5 changed files with 196 additions and 177 deletions.
@@ -22,20 +22,18 @@
<script src="script/jquery.js?1.2.6"></script>
<script src="script/couch.js?0.8.0"></script>
<script src="script/pprint.js?0.8.0"></script>
<script src="script/couch_test_runner.js"></script>
<script>
$(document).ready(function() {
$(function() {
updateTestsListing();
$("#toolbar button.run").click(runAllTests);
if (window != parent) parent.updateNavigation();
$("#toolbar button.load").click(function() {
location.reload(true);
});
});
</script>
<script src="script/couch_tests.js"></script>
<script>
$(document).ready(function() {
updateTestsListing();
$("#toolbar button.run").click(runAllTests);
if (window != parent) parent.updateNavigation();
});
var testsPath = document.location.toString().split('?')[1];
loadTests(testsPath||"script/couch_tests.js")
</script>
</head>
<body>
@@ -87,7 +87,7 @@
<li><a href="browse/index.html" target="content">Overview</a></li>
<li><a href="replicator.html" target="content">Replicator</a></li>
<li><a href="config.html" target="content">Configuration</a></li>
<li><a href="couch_tests.html" target="content">Test Suite</a></li>
<li><a href="couch_tests.html?script/couch_tests.js" target="content">Test Suite</a></li>
</ul></li>
<li><span>Recent Databases</span>
<ul id="dbs"></ul>
@@ -873,12 +873,18 @@ function CouchDocumentPage() {
}

function _renderAttachmentItem(name, attachment) {
var attachmentHref = db.uri + encodeURIComponent(docId)
+ "/" + encodeURIComponent(name);
var li = $("<li></li>");
$("<a href='' title='Download file' target='_top'></a>").text(name)
.attr("href", db.uri + encodeURIComponent(docId) + "/" + encodeURIComponent(name))
.attr("href", attachmentHref)
.wrapInner("<tt></tt>").appendTo(li);
$("<span>()</span>").text("" + prettyPrintSize(attachment.length) +
", " + attachment.content_type).addClass("info").appendTo(li);
if (name == "tests.js") {
li.find('span.info').append(', <a href="/_utils/couch_tests.html?'
+ attachmentHref + '">open in test runner</a>');
}
_initAttachmentItem(name, attachment, li);
return li;
}
@@ -0,0 +1,181 @@
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

// *********************** Test Framework of Sorts ************************* //

function loadTests(url) {
document.write('<script src="'+url+'"></script>');
};

function patchTest(fun) {
var source = fun.toString();
var output = "";
var i = 0;
var testMarker = "T("
while (i < source.length) {
var testStart = source.indexOf(testMarker, i);
if (testStart == -1) {
output = output + source.substring(i, source.length);
break;
}
var testEnd = source.indexOf(");", testStart);
var testCode = source.substring(testStart + testMarker.length, testEnd);
output += source.substring(i, testStart) + "T(" + testCode + "," + JSON.stringify(testCode);
i = testEnd;
}
try {
return eval("(" + output + ")");
} catch (e) {
return null;
}
}

function runAllTests() {
var rows = $("#tests tbody.content tr");
$("td", rows).html("&nbsp;");
$("td.status", rows).removeClass("error").removeClass("failure").removeClass("success").text("not run");
var offset = 0;
function runNext() {
if (offset < rows.length) {
var row = rows.get(offset);
runTest($("th button", row).get(0), function() {
offset += 1;
setTimeout(runNext, 1000);
});
}
}
runNext();
}

var numFailures = 0;
var currentRow = null;

function runTest(button, callback, debug) {
if (currentRow != null) {
alert("Can not run multiple tests simultaneously.");
return;
}
var row = currentRow = $(button).parents("tr").get(0);
$("td.status", row).removeClass("error").removeClass("failure").removeClass("success");
$("td", row).html("&nbsp;");
var testFun = tests[row.id];
function run() {
numFailures = 0;
var start = new Date().getTime();
try {
if (debug == undefined || !debug) {
testFun = patchTest(testFun) || testFun;
}
testFun(debug);
var status = numFailures > 0 ? "failure" : "success";
} catch (e) {
var status = "error";
if ($("td.details ol", row).length == 0) {
$("<ol></ol>").appendTo($("td.details", row));
}
$("<li><b>Exception raised:</b> <code class='error'></code></li>")
.find("code").text(JSON.stringify(e)).end()
.appendTo($("td.details ol", row));
if (debug) {
currentRow = null;
throw e;
}
}
if ($("td.details ol", row).length) {
$("<a href='#'>Run with debugger</a>").click(function() {
runTest(this, undefined, true);
}).prependTo($("td.details ol", row));
}
var duration = new Date().getTime() - start;
$("td.status", row).removeClass("running").addClass(status).text(status);
$("td.duration", row).text(duration + "ms");
updateTestsFooter();
currentRow = null;
if (callback) callback();
}
$("td.status", row).addClass("running").text("running…");
setTimeout(run, 100);
}

function showSource(cell) {
var name = $(cell).text();
var win = window.open("", name, "width=700,height=500,resizable=yes,scrollbars=yes");
win.document.title = name;
$("<pre></pre>").text(tests[name].toString()).appendTo(win.document.body).fadeIn();
}

function updateTestsListing() {
for (var name in tests) {
if (!tests.hasOwnProperty(name)) continue;
var testFunction = tests[name];
var row = $("<tr><th></th><td></td><td></td><td></td></tr>")
.find("th").text(name).attr("title", "Show source").click(function() {
showSource(this);
}).end()
.find("td:nth(0)").addClass("status").text("not run").end()
.find("td:nth(1)").addClass("duration").html("&nbsp;").end()
.find("td:nth(2)").addClass("details").html("&nbsp;").end();
$("<button type='button' class='run' title='Run test'></button>").click(function() {
this.blur();
runTest(this);
return false;
}).prependTo(row.find("th"));
row.attr("id", name).appendTo("#tests tbody.content");
}
$("#tests tr").removeClass("odd").filter(":odd").addClass("odd");
updateTestsFooter();
}

function updateTestsFooter() {
var tests = $("#tests tbody.content tr td.status");
var testsRun = tests.not(":contains('not run'))");
var testsFailed = testsRun.not(".success");
$("#tests tbody.footer td").text(testsRun.length + " of " + tests.length +
" test(s) run, " + testsFailed.length + " failures");
}

// Use T to perform a test that returns false on failure and if the test fails,
// display the line that failed.
// Example:
// T(MyValue==1);
function T(arg1, arg2) {
if (!arg1) {
if (currentRow) {
if ($("td.details ol", currentRow).length == 0) {
$("<ol></ol>").appendTo($("td.details", currentRow));
}
$("<li><b>Assertion failed:</b> <code class='failure'></code></li>")
.find("code").text((arg2 != null ? arg2 : arg1).toString()).end()
.appendTo($("td.details ol", currentRow));
}
numFailures += 1
}
}

function equals(a,b) {
if (a === b) return true;
try {
return repr(a) === repr(b);
} catch (e) {
return false;
}
}

function repr(val) {
if (val === undefined) {
return null;
} else if (val === null) {
return "null";
} else {
return JSON.stringify(val);
}
}

0 comments on commit 549caca

Please sign in to comment.