/* Copyright (C) 2009 Mobile Sorcery AB This program is free software; you can redistribute it and/or modify it under the terms of the Eclipse Public License v1.0. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Eclipse Public License v1.0 for more details. You should have received a copy of the Eclipse Public License v1.0 along with this program. It is also available at http://www.eclipse.org/legal/epl-v10.html */ package com.mobilesorcery.sdk.testing; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; public class TestResult extends TestListenerBase { public static final int TIME_UNDEFINED = -1; private HashMap<ITest, List<Object>> failures = new HashMap<ITest, List<Object>>(); private HashSet<ITest> inProgress = new HashSet<ITest>(); private HashSet<ITest> done = new HashSet<ITest>(); private HashMap<ITest, Integer> elapsedTime = new HashMap<ITest, Integer>(); private HashMap<ITest, HashMap<String, Object>> properties = new HashMap<ITest, HashMap<String, Object>>(); private ITestSession session; /** * Adds a failure to a test. * @param test * @param errorToken A language specific representation of the failure, * may be a <code>Throwable</code>, or just an error message <code>String</code>. */ public synchronized void addFailure(ITest test, Object errorToken) { List<Object> failuresForTest = failures.get(test); if (failuresForTest == null) { failuresForTest = new ArrayList<Object>(); failures.put(test, failuresForTest); } failuresForTest.add(errorToken); notifyListeners(new TestSessionEvent(TestSessionEvent.TEST_FAILED, session, test)); } public TestResult(ITestSession session) { this.session = session; } public void startTest(ITest test) { if (!test.isSuite()) { inProgress.add(test); } notifyListeners(new TestSessionEvent(TestSessionEvent.TEST_STARTED, session, test)); } public void endTest(ITest test, int elapsedTimeInMillis) { if (!test.isSuite()) { done.add(test); inProgress.remove(test); if (elapsedTimeInMillis != TIME_UNDEFINED) { elapsedTime.put(test, elapsedTimeInMillis); } } notifyListeners(new TestSessionEvent(TestSessionEvent.TEST_FINISHED, session, test)); } public int countTestsInProgress() { return inProgress.size(); } public int countRunTests() { return done.size(); } public int countFailedTests() { return failures.size(); } public boolean passed(ITest test, boolean recursive) { List<Object> failuresForTest = failures.get(test); boolean passed = failuresForTest == null || failuresForTest.size() == 0; if (recursive && passed && test instanceof ITestSuite) { ITestSuite suite = (ITestSuite) test; ITest[] tests = suite.getTests(); for (int i = 0; i < tests.length; i++) { if (!passed(tests[i], true)) { return false; } } } return passed; } public boolean hasFinished(ITest test) { if (test.isSuite()) { for (ITest oneTest : ((ITestSuite)test).getTests()) { if (!hasFinished(oneTest)) { return false; } } return true; } else { return done.contains(test); } } public boolean isRunning(ITest test) { if (test.isSuite()) { for (ITest oneTest : ((ITestSuite)test).getTests()) { if (isRunning(oneTest)) { return true; } } return false; } else { return inProgress.contains(test); } } public void setProperty(ITest test, String key, Object value) { HashMap<String, Object> properties = this.properties.get(test); if (properties == null) { properties = new HashMap<String, Object>(); this.properties.put(test, properties); } if (value == null) { properties.remove(key); } else { properties.put(key, value); } } public Object getProperty(ITest test, String key) { HashMap<String, Object> propertiesForTest = properties.get(test); return propertiesForTest == null ? null : propertiesForTest.get(key); } /** * Returns a list of failures associated with a test, * or if <code>test</code> is a <code>ITestSession</code>, any * problems actually executing the test suite. * @param test * @return */ public List<Object> getFailures(ITest test) { return failures.get(test); } public int getElapsedTime(ITest test) { if (test.isSuite()) { int testsWithElapsedTime = 0; int aggElapsedTime = 0; ITestSuite suite = (ITestSuite) test; for (ITest oneTest : suite.getTests()) { int elapsedTimeForOneTest = getElapsedTime(oneTest); if (elapsedTimeForOneTest != TIME_UNDEFINED) { aggElapsedTime += getElapsedTime(oneTest); testsWithElapsedTime++; } } return testsWithElapsedTime == 0 ? TIME_UNDEFINED : aggElapsedTime; } else { Integer elapsedTime = this.elapsedTime.get(test); return elapsedTime == null ? TIME_UNDEFINED : elapsedTime.intValue(); } } public boolean hasFailures(ITest test) { List<Object> failuresForOneTest = getFailures(test); return failuresForOneTest != null && failuresForOneTest.size() > 0; } /** * <p>Returns whether the actual test run failed (for example, the tests * were never run due to a communication error or something).</p> * <p>That kind of failure should be reported as a failure on the <code>ITestSession</code> itself. * @return */ public boolean didTestExecutionFail() { return hasFailures(session); } }