-
Notifications
You must be signed in to change notification settings - Fork 14
Source and Testing 0.5.0
As of version 0.4, the layout of the system has been changed over into multiple Eclipse projects in order to reduce code duplication across the
Java library and the Android library. As such, there are 3 additional Eclipse projects that exist in order to help with
testing the source code: a Google App Engine/GWT project for hosting the test services and testing the services in GWT, a
sample Android app for manual testing, and an Android testing app to conduct automated testing of the library on Android.
All Eclipse launchers are stored in the .settings
folder of the respective projects. On project import, they should be
directly available to you, check the Run Configurations manually in case they don't show up right away.
Traces of the prior build/test system, which was non-functional, have been removed as of version 0.5.
Additionally, the SyncProxy system can be used as an excellent tool for Synchronous testing of GWT Services. Please see this Sebastian Gurin's Blog for details.
All testing projects are setup to draw the testing services directly from GWT source so that it can be automatically tested
against the latest version as GWT changes whenever possible. The current Android and POJ tests are slightly modified replicates of the GWT tests
at the 2.7.0 version (minor modifications were made to remove/modify the GWTTestCase
dependency). As such, you must have a checkout of the entire google-web-toolkit trunk checked out
to the path google-web-toolkit
in your workspace. Make sure to checkout the proper branch release version (eg. 2.7.0) AND change all project
dependencies to the same GWT version. When updating App Engine dependencies, make sure to copy the new versions servlet-api.jar into the SPALibrary projects "lib" folder (this is found in the AppEngine Dependency module listing).
Additionally, you will need gdata checked-out to gdata
within
your workspace as well (a future version will look to remove/upgrade this dependency: See Roadmap). The Android library is dependent on the included gwt-servlet.jar web-app's servlet-api.jar library. While only a fraction of the sources in the gwt-user are needed for the
project, there is a lot of internal referencing that can cause errors if not made available. This is compensated for by using a modified version of
a couple of the gwt-user source files to break the referencing chain.
Checking out the entire trunk with all necessary dependencies should give you a layout workspace similar to the following:
Workspace\
Workspace\gdata
Workspace\google-web-toolkit
Workspace\gwt-syncproxy
Workspace\SPAAppTest
Workspace\SPALibrary
Workspace\SPWebTest
All paths within the Eclipse projects are path dependent on the WORKSPACE_LOC
variable, so make sure it is set properly to avoid
build path problems. The google-web-toolkit dependencies for are primarily for testing purposes as the general gwt-syncproxy library
will function with the gwt-user.jar in place. It is also utilized for drawing source code into the Andorid library.
However, the gdata dependencies are utilized directly in the library, so those will be needed
in production as well. See the .project and .classpath files to note the appropriate dependencies. A future version will upgrade this system to
utilize Gradle (see Roadmap) and hopefully eliminate the strict dependency on Eclipse.
For simplicity, the SPWebTest project also makes use of a single user-defined library called AppEngineTesting. It will need to reference the following
jars which can likely be found in your eclipse\plugins
path:
junit.jar - org.junit_4.10.0.v4_10_0_v20120426-0900 (or acceptable alternative)
appengine-testing.jar - com.google.appengine.eclipse.sdkbundle_1.9.17\appengine-java-sdk-1.9.17\lib\testing
appengine-api.jar - com.google.appengine.eclipse.sdkbundle_1.9.17\appengine-java-sdk-1.9.17\lib\impl
appengine-api-labs.jar - com.google.appengine.eclipse.sdkbundle_1.9.17\appengine-java-sdk-1.9.17\lib\impl
appengine-stubs.jar - com.google.appengine.eclipse.sdkbundle_1.9.17\appengine-java-sdk-1.9.17\lib\impl
The current library (0.5) has been compiled/tested against GWT 2.7.0, GAE 1.9.17, and Android V21 (Lollipop). Testing against newer versions should be as simple as updating the library references within each appropriate project and updating the checked-out source code for GWT and GData. However, there may be some complications that arise with newer versions from GWT source as subtle changes in classes referenced may render the build paths incomplete.
If you are utilizing the Android library, the account management system is only available on a Google APIs Android Virtual Device for testing. It is recommended that you create and utilize an AVD with as much memory as your system will accept (Windows may max at about 768mb) and a VM Heap of at least 64 to help with testing. Additionally, the Android library comes with the ability to send fake accounts while testing against a local GAE dev server. Please see the Android wiki doc for details.
Alternatively, as of version 0.5, you can use a hardware device to conduct testing against any specified URL for the server.
The SPWebTest project hosts an AppEngine project that serves several of the gwt-user test services for both the Java and Android client to send tests to, generally testing serialization of different formats and types. In order to utilize the hosting server:
- GWT-Compile the SPWebTest project
- Launch the
SPAWebTest
launcher - Open the local URL to startup the module (may take a few minutes to load the first time...a future upgrade will support SuperDevMode)
In order to use the Java-only Library and testing, you need only get two projects from the source, gwt-syncproxy and SPWebTest.
There are two sets of tests contained between these two projects: one to test the hosted services (just to make sure nothing
has changed), and one to test the library from a Java-stand alone. The gwt hosting tests can be run utilizing the SPGWTTest-dev
launcher and the Java stand alone tests can be launched using the PojGSPTests
launcher.
The Android library requires all of the source hierarchy described above SourceAndTesting-0.5.0#Dependencies. Additionally, there is an
integrated project that will need to be imported into eclipse within the SPAAppTest/tests/
path. This contains the source
for the SPAAppTester project, which conducts the Android JUnit testing using the SPAAppTest app as a base. The android tests
can be launched using the SPATests
launcher. The actual app for manual testing can be launched using the SPA_App
launcher.
This portion of the document will review the process needed to add more tests throughout the system. All testing within the system is currently done utilizing the JUnit structures, and there are 3 separate locations to add tests.
If your test will be run against a service, there are a number of steps to ensure success without compile/run-time issues.
- Create the service in the SPWebTest project
- Even if it is not utilized manually, make sure it is referenced in the
client/SPAWebTest
class so that it's service handle will be serialized for retrieval. - Add the servlet handlers to the
web.xml
- GWT-Compile the SPWebTest project
- Create a test within the
test/.../client/gwttests
path. Be sure to properly utilize the GWTTestCase finishTest() and delayTestFinish() methods for Asynchronous testing. - Add this test to the
/gwttests/GwtTests
TestSuite class.
You can utilize the same testing structure for the stand along test, but you will need to modify the source-copied to work outside the GWTTestCase structure.
- Copy the test case into the gwt-syncproxy project
test/.../test/poj/
path. - Convert the test from a GWTTestCase to a TestCase
- (Recommended not required) Create the SyncProxy service statically in the test case.
- Convert the finishTest()/delayTestFinish() to utilize a CountDownLatch. This can be easily done across a large test case with the following search/replacements
* If you have a standard method start, like service = GWT.create(...), Replace With
final CountDownLatch signal = new CountDownLatch(1);
* SearchfinishTest()
Replace withsignal.countDown()
* SearchdelayTestFinish(2000)
Replace withassertTrue("Failed to Complete", signal.await(2, TimeUnit.SECONDS))
- Resolve any pending issues
- Add this testcase to
PojGSPTests
TestSuite class
As with the Java Stand Alone Testing, you can utilize the converted Java SA test for the Android Testing system. This requires some additional subtle modification since Android requires network access to be completed off the main thread. We do this with the AsyncTask.
- Copy the converted test case in the Java Stand Alone to the SPAAppTester
test/gwttests
path. - Convert TestCase to
ActivityInstrumentationTestCase2<MainActivity>
- Connect to the service in the Constructor using the following pattern: * Take note of the url path that is connected to. Android uses the 10.0.2.2 url to access the locally hosted webserver at 127.0.0.1.
final CountDownLatch signal = new CountDownLatch(1);
final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... arg0) {
service = (CollectionsTestServiceAsync) SyncProxy
.newProxyInstance(CollectionsTestServiceAsync.class,
"http://10.0.2.2:8888/spawebtest/",
"collections", true);
signal.countDown();
return null;
}
};
task.execute();
if (!signal.await(20, TimeUnit.SECONDS)) {
throw new RuntimeException("Failed to get service started");
}
- Convert to the AsyncTask system utilizing the following Search/Replace systems as a guide. It will be very useful to utilize auto-format after these search/replacements
* Search
service.echo
(or your appropriate method call) Replace withfinal AsyncTask<Void, Void, Void> myTask = new AsyncTask<Void, Void, Void>() {@Override protected Void doInBackground(Void... arg0){ service.echo
* Search});
Replace with});return null;}};runTestOnUiThread(new Runnable(){@Override public void run(){myTask.execute();}});
* Searchthrows InterruptedException
Replace withthrows Throwable
In order to make it easier to test between the emulator and a device, SPALibrary as of version 0.4.4 utilizes a String resource R.string.test_server_url. Specifically, each test now inherits from a new TestCase AndroidGWTTestCase which provides access to the method
getModuleBaseURL()
which looks at this resource. In this manner, by changing the value in the strings.xml file, you can switch between the emulator's loopback interface (10.0.2.2) and any url you may wish to specify. For device testing locally, you will likely use a local IP address such as 192.168.1.XXX. Make sure that your device and the computer hosting the App Engine Dev Server are on the same network.
Similar to the above with slight modifications to build from AndroidGWTTestCase. Create a template for quick use with the following:
setTask(new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... arg0) {
${line_selection}
return null;
}
});
Then for each existing test, highlight the code within the test,
<alt>
<shift>
-Z, and your template should come up (if close to top of alphabet, then 1).
and this will automatically surround the given code with AsyncTasked Code for use in Android Testing. The rest of the async needs and waiting are handled by AndroidGWTTestCase. Remember that the call to
delayTestFinishForRpc()
must come before the call to set the Task.
The following times are based on my system, so you can expect changes in processing times accordingly (6-core [email protected], 8GB, Win 7-64) and Eclipse (-Xms1g, -Xmx2g). Android testing takes about 600s (Heavy in UnicodeEscaping, ValueTypes, and Collections). Plain old Java (POJ) testing takes about 110s (Heavy in Collections and ValueTypes). GWT testing takes 83s (45s within the UnicodeEscapingTest).
When running either the Java Standalone Tests PojGSPTests
or the Android Tests SPATests
, you must make sure the web service has been
GWT compiled and is running SPAWebTest
TestCase | Project | Issue | Resolution/Reason |
---|---|---|---|
CollectionsTest | Android | Failure in EnumMap tests. EnumMap serializer does not work for Android version of this class (different that in current JRE). | Not Yet Resolved |
ExceptionTest | Java & Android | Failure on Server side because the UmbrellaException class doesn't implement the IsSerializable interface | A manual override of this class with the IsSerializable interface makes the test pass. |
FinalFieldsTest | GWT | IncompatibleRemoteServiceException for FinalFieldsNode | Not Yet Resolved |
RemoteServiceServletTests | Java & Android | Methods utilizing Request or RequestBuilder fail as they are not yet supported by SyncProxy | Will be supported in a future version |
RunTimeSerializationTests | Java & Android | SAA | SAA |
ValueTypesTest | Java & Android | The over64KB tests fail with insufficient time or data match failure | Not Yet Resolved |
XsrfProtectionTest | Java & Android | Failures due to lack of Xsrf support in SyncProxy. However, they unexpectedly pass in Android tests. | Will be supported in a future version |
Within the current set of tests implemented, there are a couple of tests which are failing, so please see below a for a list of failures and the issue. There are also a number of tests in the original test system which were not re-implemented (either for time or other reason, explained below).
TestCase | Project | Issue | Resolution/Reason |
---|---|---|---|
AsyncEnumsTest & EnumsTest | Java & Android | Failure on Server side because the Enums don't implement the IsSerializable interface | A manual override of those enum classes with the IsSerializable interface makes the tests pass. |
CollectionsTest#testArraysAsList | Java & Android | Fails with a NoClassDefFoundError for GWTBridge | Not Yet Resolved |
EnumsTest#testNull | Android | Server-side throws IncompatibleRemoteServiceException for accessing echo(Object) | Not Yet Resolved |
ExceptionTest | Java & Android | Failure on Server side because the UmbrellaException class doesn't implement the IsSerializable interface | A manual override of this class with the IsSerializable interface makes the test pass. |
HttpsTest | Java & Android | SSL Plain Text Error | Not Yet Resolved |
ALL | Not reimplemented | No original implementation | |
SessionTest | ALL | Not reimplemented | No value noted for reimplementing this scenario in unit testing |
UnicodeEscapingTest#ServerToClientNonBMP | GWT | GAE | Throws a series of StringIndexOutOfBoundsException's |
XsrfProtectionTest | ALL | Not Fully Implemented | Many of the original tests were not implemented |
As of version 0.6, testing (manually) against an HTTPS server is supported. In order to do us, we use STunnel to create the secured proxy. This section is being modified regularly as 0.6 is being worked on, so information here may change quickly and unexpectedly.
As a resource (http://stackoverflow.com/questions/2138940/import-pem-into-java-key-store).
Tutorial: http://www.blueesoteric.com/blog/2015/04/testing-android-app-engine-over-https-local-development