All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.junit.client.GWTTestCase Maven / Gradle / Ivy

There is a newer version: 2.10.0
Show newest version
/*
 * Copyright 2008 Google Inc.
 *
 * 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.
 */
package com.google.gwt.junit.client;

import com.google.gwt.junit.JUnitShell;
import com.google.gwt.junit.JUnitShell.Strategy;
import com.google.gwt.junit.PropertyDefiningStrategy;
import com.google.gwt.junit.client.impl.JUnitHost.TestInfo;

import junit.framework.TestCase;
import junit.framework.TestResult;

import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

/**
 * Acts as a bridge between the JUnit environment and the GWT environment. We
 * hook the run method and stash the TestResult object for later communication
 * between the test runner and the unit test shell that drives the test case
 * inside a hosted browser.
 *
 * 

* There are two versions of this class. This version is the binary version that * derives from JUnit's {@link TestCase} and handles all the work of starting up * the GWT environment. The other version is a translatable class that is used * within the browser. See the translatable subpackage for the * translatable implementation. *

*/ @SuppressWarnings("unused") public abstract class GWTTestCase extends TestCase { /** * Information about a synthetic module used for testing. */ public static final class TestModuleInfo { private String moduleName; private String syntheticModuleName; private Strategy strategy; /** * The ordered tests in this synthetic module. */ private Set tests = new LinkedHashSet(); /** * Construct a new {@link TestModuleInfo}. * * @param moduleName the module name * @param syntheticModuleName the synthetic module name * @param strategy the test {@link Strategy} */ public TestModuleInfo(String moduleName, String syntheticModuleName, Strategy strategy) { this.moduleName = moduleName; this.syntheticModuleName = syntheticModuleName; this.strategy = strategy; } public String getModuleName() { return moduleName; } public Strategy getStrategy() { return strategy; } public String getSyntheticModuleName() { return syntheticModuleName; } /** * Returns the tests that are part of this module. */ public Set getTests() { return tests; } } /** * Records all live GWTTestCases by synthetic module name so we can optimize * run they are compiled and run. Ordered so that we can precompile the * modules in the order that they will run. */ public static final Map ALL_GWT_TESTS = new LinkedHashMap(); /** * The lock for ALL_GWT_TESTS. */ private static final Object ALL_GWT_TESTS_LOCK = new Object(); /** * Get the names of all test modules. * * @return all test module names */ public static String[] getAllTestModuleNames() { synchronized (ALL_GWT_TESTS_LOCK) { return ALL_GWT_TESTS.keySet().toArray(new String[ALL_GWT_TESTS.size()]); } } /** * Get the number of modules. * * @return the module count. */ public static int getModuleCount() { synchronized (ALL_GWT_TESTS_LOCK) { return ALL_GWT_TESTS.size(); } } /** * Get the set of all {@link TestInfo} for the specified module. * * @param syntheticModuleName the synthetic module name * @return all tests for the module */ public static TestModuleInfo getTestsForModule(String syntheticModuleName) { synchronized (ALL_GWT_TESTS_LOCK) { return ALL_GWT_TESTS.get(syntheticModuleName); } } /** * Object that collects the results of this test case execution. */ protected TestResult testResult = null; /** * Whether this test case should be always run in pure Java mode (non-GWT). * Setting this to true has the same effect as returning * null in {@link #getModuleName}. * * @see #isPureJava */ private boolean forcePureJava; /** * The {@link Strategy} used by this test. */ private Strategy strategy; /** * A new instance of your subclass is constructed for each test method that is * to be run. You should avoid running code in your subclass constructor, * initializer blocks, and field initializations, because if those code blocks * must be runnable outside of the GWT environment. As an example of what * could go wrong if you run code there, trying to run a JSNI method could * generate an {@link UnsatisfiedLinkError}, and trying to call * {@link com.google.gwt.core.client.GWT#create(Class)} could throw an * {@link UnsupportedOperationException}. Instead, override * {@link #gwtSetUp()} and perform any initialization code there. */ public GWTTestCase() { } /** * Determines whether or not exceptions will be caught by the test fixture. * Override this method and return false to let exceptions escape * to the browser. This will break the normal JUnit reporting functionality, * but can be useful in Production Mode with a JavaScript debugger to pin down * where exceptions are originating. * * @return true for normal JUnit behavior, or false * to disable normal JUnit exception reporting */ public boolean catchExceptions() { return true; } /** * Specifies a module to use when running this test case. Subclasses must * return the name of a module that will cause the source for that subclass to * be included. * * @return the fully qualified name of a module, or null to run * as a pure Java (non-GWT) test case (same effect as passing * true to {@link #setForcePureJava}) * * @see #isPureJava */ public abstract String getModuleName(); /** * Get the {@link Strategy} to use when compiling and running this test. * * @return the test {@link Strategy} */ public Strategy getStrategy() { if (strategy == null) { strategy = new PropertyDefiningStrategy(this); } return strategy; } /** * Get the synthetic module name, which includes the synthetic extension * defined by the {@link Strategy}. * * @return the synthetic module name, or null if this test case * is run in pure Java mode (non-GWT) * * @see #isPureJava */ public final String getSyntheticModuleName() { if (isPureJava()) { return null; } else { return getModuleName() + "." + getStrategy().getSyntheticModuleExtension(); } } /** * Returns whether this test case should be run in pure Java mode (non-GWT). * Returns true if and only if {@link #getModuleName} returns * null, or {@link #setForcePureJava} was last invoked with * true. */ public boolean isPureJava() { return forcePureJava || (getModuleName() == null); } /** * Stashes result so that it can be accessed during * {@link #runTest()}. */ @Override public final void run(TestResult result) { testResult = result; super.run(result); } /** * Specifies whether this test case should be always run in pure Java mode * (non-GWT). Passing true has the same effect as returning * null in {@link #getModuleName}. The setting is * false by default. * * @param forcePureJava true to always run this test case in pure * Java mode (non-GWT); false to run this test case in GWT * mode if {@link #getModuleName} does not return null * * @see #isPureJava */ public void setForcePureJava(boolean forcePureJava) { this.forcePureJava = forcePureJava; } @Override public void setName(String name) { super.setName(name); synchronized (ALL_GWT_TESTS_LOCK) { // Once the name is set, we can add ourselves to the global set. String syntheticModuleName = getSyntheticModuleName(); TestModuleInfo moduleInfo = ALL_GWT_TESTS.get(syntheticModuleName); if (moduleInfo == null) { // It should be safe to assume that tests with the same synthetic module // name have the same test strategy. If they didn't, they would compile // over each other. moduleInfo = new TestModuleInfo(getModuleName(), syntheticModuleName, getStrategy()); ALL_GWT_TESTS.put(syntheticModuleName, moduleInfo); } moduleInfo.getTests().add( new TestInfo(syntheticModuleName, getClass().getName(), getName())); } } /** * Put the current test in asynchronous mode. If the test method completes * normally, this test will not immediately succeed. Instead, a delay * period begins. During the delay period, the test system will wait for * one of three things to happen: * *
    *
  1. If {@link #finishTest()} is called before the delay period expires, * the test will succeed.
  2. *
  3. If any exception escapes from an event handler during the delay * period, the test will error with the thrown exception.
  4. *
  5. If the delay period expires and neither of the above has happened, the * test will error with a {@link TimeoutException}.
  6. *
* *

* This method is typically used to test event driven functionality. *

* *

* Example: * {@example com.google.gwt.examples.AsyncJUnitExample#testTimer()} *

* * @param timeoutMillis how long to wait before the current test will time out * @tip Subsequent calls to this method reset the timeout. * @see #finishTest() * * @throws UnsupportedOperationException if {@link #supportsAsync()} is false */ protected final void delayTestFinish(int timeoutMillis) { // implemented in the translatable version of this class } /** * Cause this test to succeed during asynchronous mode. After calling * {@link #delayTestFinish(int)}, call this method during the delay period to * cause this test to succeed. This method is typically called from an event * handler some time after the test method returns control to the caller. * *

* Calling this method before the test method completes, will undo the effect * of having called delayTestFinish(). The test will revert to * normal, non-asynchronous mode. *

* *

* Example: * {@example com.google.gwt.examples.AsyncJUnitExample#testTimer()} *

* * @throws IllegalStateException if this test is not in asynchronous mode * @throws UnsupportedOperationException if {@link #supportsAsync()} is false * * @see #delayTestFinish(int) */ protected final void finishTest() { // implemented in the translatable version of this class } /** * Reports an exception that might have escaped to the browser. *

* This method is called by the test framework to report uncaught exceptions. The default * implementation causes the test case to be reported as 'failed'. However in some rare situations * where an uncaught exception is expected, a test case may choose to alter the behavior by * overriding it: *

   * class SomeTestCase extends GWTTestCase {
   *
   *   class ExpectedTestException extends Exception {}
   *
   *   {@literal @}Override
   *   protected void reportUncaughtException(Throwable t) {
   *     // Ignore exceptions that are expected to be thrown by our test cases:
   *     if (t instanceof ExpectedTestException) {
   *       return;
   *     }
   *     super.reportUncaughtException(t);
   *   }
   *   ...
   * }
   * 
* * Note that this method will not cause the test case to fail immediately if the main test body is * still executing. In that case, test will fail after the main body returns with the reported * exception. If the test has already finished (fail or success) before this method is called, * the reported exception is currently ignored, but this may result in an error in a future * version of GWT. * * @see com.google.gwt.core.client.GWT#reportUncaughtException */ protected void reportUncaughtException(Throwable ex) { // implemented in the translatable version of this class } /** * A replacement for JUnit's {@link #setUp()} method. This method runs once * per test method in your subclass, just before your each test method runs * and can be used to perform initialization. Override this method instead of * {@link #setUp()}. This method is run even in pure Java mode (non-GWT). * * @see #setForcePureJava */ protected void gwtSetUp() throws Exception { } /** * A replacement for JUnit's {@link #tearDown()} method. This method runs once * per test method in your subclass, just after your each test method runs and * can be used to perform cleanup. Override this method instead of * {@link #tearDown()}. This method is run even in pure Java mode (non-GWT). * * @see #setForcePureJava */ protected void gwtTearDown() throws Exception { } /** * Runs the test via the {@link JUnitShell} environment. Do not override or * call this method. */ @Override protected void runTest() throws Throwable { if (this.getName() == null) { throw new IllegalArgumentException( "GWTTestCases require a name; \"" + this.toString() + "\" has none. Perhaps you used TestSuite.addTest() instead of addTestClass()?"); } if (isPureJava()) { super.runTest(); } else { JUnitShell.runTest(this, testResult); } } /** * This method has been made final to prevent you from accidentally running * client code outside of the GWT environment. Please override * {@link #gwtSetUp()} instead. */ @Override protected final void setUp() throws Exception { if (isPureJava()) { gwtSetUp(); } } /** * This method has been made final to prevent you from accidentally running * client code outside of the GWT environment. Please override * {@link #gwtTearDown()} instead. */ @Override protected final void tearDown() throws Exception { if (isPureJava()) { gwtTearDown(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy