My setup:
My project has the library project linked as a library project. It compiles and runs fine.
Now I try to test my application using a normal test project. Running the tests in eclipse works perfect. If I try to run the tests using ant, the test project doesn't even compile:
[javac] LoginActivityTest.java:9: cannot access com.actionbarsherlock.app.SherlockActivity
[javac] class file for com.actionbarsherlock.app.SherlockActivity not found
[javac] public class LoginActivityTest extends ActivityInstrumentationTestCase2<LoginActivity> {
[javac] ^
[javac] LoginActivityTest.java:25: cannot find symbol
Building via eclipse works perfect and the test runs perfect, too.
If I link the library project to my test project, it compiles with ant but the tests fails.
[exec] Error in testSuiteConstructionFailed:
[exec] java.lang.RuntimeException: Exception during suite construction
[exec] at android.test.suitebuilder.TestSuiteBuilder$FailedToCreateTests.testSuiteConstructionFailed(TestSuiteBuilder.java:238)
[exec] at java.lang.reflect.Method.invokeNative(Native Method)
[exec] at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
[exec] at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
[exec] at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:537)
[exec] at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1551)
[exec] Caused by: java.lang.reflect.InvocationTargetException
[exec] at java.lang.reflect.Constructor.constructNative(Native Method)
[exec] at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
[exec] at android.test.suitebuilder.TestMethod.instantiateTest(TestMethod.java:87)
[exec] at android.test.suitebuilder.TestMethod.createTest(TestMethod.java:73)
[exec] at android.test.suitebuilder.TestSuiteBuilder.addTest(TestSuiteBuilder.java:262)
[exec] at android.test.suitebuilder.TestSuiteBuilder.build(TestSuiteBuilder.java:184)
[exec] at android.test.InstrumentationTestRunner.onCreate(InstrumentationTestRunner.java:371)
[exec] at com.zutubi.android.junitreport.JUnitReportTestRunner.onCreate(JUnitReportTestRunner.java:90)
[exec] at android.app.ActivityThread.handleBindApplication(ActivityThread.java:3891)
[exec] at android.app.ActivityThread.access$1300(ActivityThread.java:122)
[exec] at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1184)
[exec] at android.os.Handler.dispatchMessage(Handler.java:99)
[exec] at android.os.Looper.loop(Looper.java:137)
[exec] at android.app.ActivityThread.main(ActivityThread.java:4340)
[exec] at java.lang.reflect.Method.invokeNative(Native Method)
[exec] at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
[exec] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
[exec] at dalvik.system.NativeStart.main(Native Method)
[exec] Caused by: java.lang.NoClassDefFoundError: com.myproject.android.app.activities.LoginActivity
[exec] at com.myproject.android.app.test.LoginActivityTest.<init>(LoginActivityTest.java:18)
[exec] ... 19 more
My test class:
public class LoginActivityTest extends ActivityInstrumentationTestCase2<LoginActivity> {
private LoginActivity mActivity;
private EditText mTextUserName;
private EditText mTextUserPassword;
public LoginActivityTest() {
// the super call is line 18 (see stack trace above)
super("com.myproject.android.app.activities", LoginActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
mActivity = getActivity();
mTextUserName = (EditText) mActivity.findViewById(com.myproject.android.app.R.id.login_activity_username);
mTextUserPassword = (EditText) mActivity.findViewById(com.myproject.android.app.R.id.login_activity_password);
}
public void testPreConditions() {
assertTrue("Activity is null!", mActivity != null);
}
public void testLogin() throws Throwable {
mActivity.runOnUiThread(new Runnable() {
public void run() {
mTextUserName.setText("username");
mTextUserPassword.setText("password");
}
});
sendKeys(KeyEvent.KEYCODE_ENTER);
}
}
Some ideas how I can fix this?
Update: it looks like the ant build/test is still a mess. According to this blog entry about testing a library project most of the 7 listed issues will be fixed in the next ADT release (ADT r20).
There are lots of different bits of information floating around regarding using Library
projects since ADT 17 broke/fixed everything (depending on wether you're currently banging your head against your desk).
First of all, please note the difference between Library
and "library" where Library
is a noun as decreed by the Android team. I'm also using Referencing
project which describes a project which uses a Library
project.
ie, A Referencing
project uses a Library
project.
non Library
"library" Projects
In normal Java development it's possible to link projects in Eclipse where one is dependent on the source of the other. I believe this approach has the effect of using the library projects source(s) as the source for the referencing project. This means that library projects source is in scope while compiling the referencing project. The library project classes are built at the same time as those of the referencing project.
When building for use in most situations this works perfectly well as all of the classes are built and then packaged in JARs or WARs or whatever.
Library Projects
A competing (not a mix and match) approach to library projects are the Android teams Library
projects:
An Android project marked as being a Library
Project will compile and build it's sources into a jar
file in its bin
directory (after a clean/build command). Any Referencing
projects automatically importing this jar
and gaining access to the Library
projects functionality. You can see this relationship by looking inside the Java Library Android Dependencies
in the Package Explorer.
Alongside the class dependency resolution the resource are also being directly referenced and compiled into R.java
files inside of the Referencing
projects gen
directory.
The new ADT
introduced problems to peoples set up's because it added "support" for including jars which were referenced by the Library
project:
Pre ADT 17
The Library
project had a jar added to it's build path.
The Referencing
project could also have the jar added to its own build path.
ADT 17 onwards
Dealing With Dependencies
After ADT 17 Library
projects which dynamically referenced their own jars started to behave strangely. It wasn't simply a case of including the same dependent reference in your Referencing
project to keep the jar visible in both scopes. This now resulted in strange duplication of included classes.
Unfortunately simply removing the library from the Referencing
or Library
project (so only one link was present) then confused eclipse, it could no longer could see the jar from the scope of the Project using it.
To fix this you need to place the Library
projects jars in the /libs
directory - this can be a pain in the rear if you jars are on disperate places on your harddrive. These jars will then automatically be used in your Library
and Referencing
projects.
So, to move past ADT 17:
Library
or Referencing
project).Library
project (instead compile them into jars).Library
project, copy them to the libs
directory instead.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With