| var __EASE_UnitTest_TestRunner = { |
| |
| /** |
| * Execute all unit tests. |
| */ |
| run : function() { |
| this.getUnitTestModule().setThrowOnFailure(true); |
| |
| var iterator = getScriptEngine().getVariables().entrySet().iterator(); |
| while (iterator.hasNext()) { |
| var candidateEntry = iterator.next(); |
| var candidate = candidateEntry.getValue(); |
| if (this.isUnitTest(candidate)) { |
| // this is a unit test class |
| var testClass = this.getUnitTestModule().addTestClass(candidateEntry.getKey()); |
| if (candidate.hasOwnProperty("__description")) |
| testClass.setDescription(candidate.__description); |
| |
| var testcases = new Array(); |
| var testClassSetup = null; |
| var testClassTeardown = null; |
| var testSetup = null; |
| var testTeardown = null; |
| |
| for (test in candidate) { |
| var annotations = this.getAnnotations(candidate[test]); |
| |
| if (annotations.hasOwnProperty("before")) |
| testSetup = test; |
| else if (annotations.hasOwnProperty("after")) |
| testTeardown = test; |
| else if (annotations.hasOwnProperty("beforeclass")) |
| testClassSetup = test; |
| else if (annotations.hasOwnProperty("afterclass")) |
| testClassTeardown = test; |
| else if ((annotations.hasOwnProperty("test")) || (test.match(/^test.*/) != null)) |
| testcases[testcases.length] = test; |
| } |
| |
| if ((test.length > 0) && (testClassSetup != null)) |
| candidate[testClassSetup](); |
| |
| for (index in testcases) { |
| var test = testcases[index]; |
| var annotations = this.getAnnotations(candidate[test]); |
| |
| this.getUnitTestModule().startTest(test, annotations["description"]); |
| |
| // register test start location |
| try { |
| // only works for Rhino debug engine |
| var debugView = getScriptEngine().getContext().getDebuggableView(candidate[test]); |
| var file = org.eclipse.ease.tools.ResourceTools.resolve(debugView.getSourceName()); |
| var script = new org.eclipse.ease.Script("", file, false); |
| // line numbers are not sorted |
| var debugFrame = new org.eclipse.ease.debugging.ScriptDebugFrame(script, this |
| .getFirstLineNumber(debugView.getLineNumbers()), -1); |
| |
| var stackTrace = new org.eclipse.ease.debugging.ScriptStackTrace(); |
| stackTrace.add(debugFrame); |
| |
| this.getUnitTestModule().getCurrentTest().setStackTrace(stackTrace); |
| |
| } catch (e) { |
| // we could not set the stacktrace for the unit test start location, ignore |
| } |
| |
| if (candidate.hasOwnProperty("__ignore")) { |
| this.getUnitTestModule().ignoreTest(candidate["__ignore"]); |
| |
| } else if (annotations.hasOwnProperty("ignore")) { |
| this.getUnitTestModule().ignoreTest(annotations["ignore"]); |
| |
| } else { |
| |
| try { |
| if (testSetup != null) |
| candidate[testSetup](); |
| |
| try { |
| this.getUnitTestModule().setTestTimeout(this.getTimeout(annotations)); |
| |
| // execute the test |
| candidate[test](); |
| |
| // check for expected exception |
| var expectedException = this.getExpectedException(annotations); |
| if (expectedException != null) { |
| this.getUnitTestModule().failure( |
| "Expected exception not thrown: " + expectedException, |
| this.getUnitTestModule().getCurrentTest().getStackTrace()); |
| } |
| |
| } catch (e) { |
| if (this.isAssertion(e)) { |
| // test failure |
| try { |
| this.getUnitTestModule().failure(e.javaException.getMessage(), |
| getScriptEngine().getExceptionStackTrace()); |
| } catch (e1) { |
| // no exception stacktrace available |
| this.getUnitTestModule().failure(e.javaException.getMessage()); |
| } |
| |
| } else if (this.isExpectedException(annotations, e)) { |
| // nothing to do, test is pass |
| } else { |
| // test error |
| var message = (typeof (e.javaException) !== 'undefined') ? e.javaException |
| .getMessage() : e; |
| try { |
| this.getUnitTestModule().error(message, |
| getScriptEngine().getExceptionStackTrace()); |
| } catch (e1) { |
| // no exception stacktrace available |
| this.getUnitTestModule().error(message); |
| } |
| } |
| } finally { |
| |
| try { |
| if (testTeardown != null) |
| candidate[testTeardown](); |
| } catch (e) { |
| // test setup error |
| var message = (typeof (e.javaException) !== 'undefined') ? e.javaException |
| .getMessage() : e; |
| try { |
| this.getUnitTestModule().error("Test teardown error: " + message, |
| getScriptEngine().getExceptionStackTrace()); |
| } catch (e1) { |
| // no exception stacktrace available |
| this.getUnitTestModule().error("Test teardown error: " + message); |
| } |
| } |
| } |
| |
| } catch (e) { |
| // test setup error |
| var message = (typeof (e.javaException) !== 'undefined') ? e.javaException.getMessage() : e; |
| try { |
| this.getUnitTestModule().error("Test setup error: " + message, |
| getScriptEngine().getExceptionStackTrace()); |
| } catch (e1) { |
| // no exception stacktrace available |
| this.getUnitTestModule().error("Test setup error: " + message); |
| } |
| } |
| } |
| |
| this.getUnitTestModule().endTest(); |
| } |
| |
| if ((test.length > 0) && (testClassTeardown != null)) |
| candidate[testClassTeardown](); |
| |
| this.getUnitTestModule().addTestClass(null); |
| } |
| } |
| }, |
| |
| /** |
| * Get the lowest number in an unsorted array of line numbers |
| * |
| * @param {array} |
| * lineNumbers - unsorted line numbers of a function |
| * @return lowest line number |
| */ |
| getFirstLineNumber : function(lineNumbers) { |
| var min = lineNumbers[0]; |
| for (index in lineNumbers) { |
| if (lineNumbers[index] < min) |
| min = lineNumbers[index]; |
| } |
| |
| return min; |
| }, |
| |
| /** |
| * Verify that an object is a unit test. |
| * |
| * @param {object} |
| * candidate - object to test |
| */ |
| isUnitTest : function(candidate) { |
| try { |
| return candidate.hasOwnProperty("__unittest"); |
| } catch (e) { |
| return false; |
| } |
| }, |
| |
| /** |
| * Get annotations from a method. Annotations are simple string literals |
| * starting with an '@' at the beginning of the function code. |
| * |
| * @param {function} |
| * method - function to get annotations from |
| */ |
| getAnnotations : function(method) { |
| var annotations = {}; |
| var data = method.toString(); |
| |
| var expression = /@(\w+)(?:\((.*)\)["'])?;?/g; |
| var match; |
| |
| do { |
| match = expression.exec(data); |
| if (match) { |
| annotations[match[1].toLowerCase()] = match[2]; |
| } |
| } while (match); |
| |
| return annotations; |
| }, |
| |
| /** |
| * Check if a thrown exception was expected by the provided test function. |
| * |
| * @param {array} |
| * annotations - function annotations |
| * @param {exception} |
| * e - thrown exception |
| */ |
| isExpectedException : function(annotations, e) { |
| try { |
| if (this.isJavaException(e)) |
| return (e.javaException.getClass().getName() == this.getExpectedException(annotations)); |
| |
| else if (e instanceof java.lang.Throwable) |
| return (e.getClass().getName() == this.getExpectedException(annotations)); |
| |
| } catch (e1) { |
| } |
| |
| return false; |
| }, |
| |
| /** |
| * Extract expected exception type from given method annotations. |
| * |
| * @param {array} |
| * annotations - method annotations |
| * @return expected java exception class name or <code>null</code> |
| */ |
| getExpectedException : function(annotations) { |
| if (annotations.hasOwnProperty("expect")) |
| return annotations["expect"]; |
| |
| return null; |
| }, |
| |
| /** |
| * Validate if an exception is actually a wrapped java exception. |
| * |
| * @param {Exception} |
| * e - exception to query |
| * @return <code>true</code> when exception is a wrapped java exception |
| */ |
| isJavaException : function(e) { |
| try { |
| return (typeof (e.javaException) !== 'undefined'); |
| } catch (e1) { |
| } |
| |
| return false; |
| }, |
| |
| /** |
| * Validate if an exception is actually a test assertion. |
| * |
| * @param {Exception} |
| * e - exception to query |
| * @return <code>true</code> when exception is an assertion |
| */ |
| isAssertion : function(e) { |
| return this.isJavaException(e) |
| && e.javaException.getClass().equals(org.eclipse.ease.lang.unittest.AssertionException); |
| }, |
| |
| /** |
| * Get test timeout in [ms]. |
| * |
| * @param {array} |
| * annotations - method annotations |
| * @return timeout in milliseconds or 0 |
| */ |
| getTimeout : function(annotations) { |
| if (annotations.hasOwnProperty("timeout")) |
| return parseInt(annotations["timeout"]); |
| |
| return 0; |
| }, |
| |
| /** |
| * Get instance of EASE unittest module. Will be loaded on demand. |
| * |
| * @return unittest module |
| */ |
| getUnitTestModule : function() { |
| var module = getScriptEngine().getVariable("__MOD_org_eclipse_ease_lang_unittest_UnitTestModule"); |
| if (module == null) { |
| loadModule("/Unittest", true); |
| module = getScriptEngine().getVariable("__MOD_org_eclipse_ease_lang_unittest_UnitTestModule"); |
| } |
| |
| return module; |
| }, |
| } |
| |
| // execute test runner |
| __EASE_UnitTest_TestRunner.run(); |