Android SDK ツール r15 と Eclipse を使用します。
Eclipse で 3 つのプロジェクトを作成するとします。 Lib (Android ライブラリ プロジェクト) <- App (Android アプリケーション プロジェクト) <- Test (Android 単体テスト プロジェクト) で、次のクラスを定義します。
[リブ]
public class A {}
[アプリ]
public class A extends B {}
[テスト]
public class MyUnitTest extends AndroidTestCase {
public void test() {
new A();
new B();
}
}
この設定では、TestMain は Android ライブラリとして TestLib を参照し、TestMainTest は TestMain へのプロジェクト参照を持っています。
A を解決できないため、 Test がコンパイルされないことがわかります。Test には Lib への可視性がないため、これは予期されることです。1 つの解決策は、Test から Lib へのライブラリ参照を追加することです。これによりコンパイルの問題は修正されますが、実行時に問題が発生します。多数のエラーが発生しますが、興味深いのは次のとおりです。
W/dalvikvm( 9275): Class resolved by unexpected DEX: Lcom/example/B;(0x40513450):0x294c70 ref [Lcom/example/A;] Lcom/example/A;(0x40513450):0x8f600
W/dalvikvm( 9275): (Lcom/example/B; had used a different Lcom/example/A; during pre-verification)
W/dalvikvm( 9275): Unable to resolve superclass of Lcom/example/B; (1)
W/dalvikvm( 9275): Link of class 'Lcom/example/B;' failed
E/dalvikvm( 9275): Could not find class 'com.example.B', referenced from method com.example.test.MyUnitTest.test
W/dalvikvm( 9275): VFY: unable to resolve new-instance 3 (Lcom/example/B;) in Lcom/example/test/MyUnitTest;
D/dalvikvm( 9275): VFY: replacing opcode 0x22 at 0x0000
D/dalvikvm( 9275): VFY: dead code 0x0002-000a in Lcom/example/test/MyUnitTest;.test ()V
これは、Test プロジェクトと App プロジェクトの両方が Lib ライブラリ プロジェクトを参照しているため、作成された両方の apk に com.example.A のコピーが含まれているためです。
テスト プロジェクトからライブラリ プロジェクトに明示的な依存関係を Eclipse に追加しないでください (そのライブラリがテスト対象のアプリケーション プロジェクトの依存関係である場合)。これを行うと、アプリケーション プロジェクトとテスト プロジェクトの両方で、結果の apk に同じクラスのコピーが含まれ、実行時にテストが失敗する可能性があります。
コンパイル時の可視性の問題を回避する方法を見つける必要があります。実行時に、Test は App を認識できるため、Lib のクラスを認識できます。Test から Lib へのライブラリ参照を作成する代わりに、アプリのビルド パスを更新して、そのライブラリ プロジェクトをエクスポートします。テストがコンパイルされ、単体テストが正常に実行されるようになりました。
Eclipse で、ライブラリ プロジェクトを参照するアプリケーション プロジェクトをテストするには、ビルド パス設定でアプリケーション プロジェクトからライブラリ プロジェクトをエクスポートします。
今ではすべてが Eclipse で動作しますが、それは Ant についてですか? android update [lib-|test-]project コマンドを使用して、必要な build.xml ファイルを作成します。Lib、App、Test の 3 つのディレクトリすべてで Ant clean を実行してください。3 つのプロジェクトすべてを消去しないと、コンパイルが成功する可能性があります。
Ant のコンパイルは次のように失敗します。
[javac] ...Test/src/com/example/test/MyUnitTest.java:3: cannot find symbol
[javac] symbol : class A
[javac] location: package com.example
[javac] import com.example.A;
[javac] ^
[javac] ...Test/src/com/example/test/MyUnitTest.java:10: cannot access com.example.A
[javac] class file for com.example.A not found
[javac] new B();
[javac] ^
[javac] ...Test/src/com/example/test/MyUnitTest.java:11: cannot find symbol
[javac] symbol : class A
[javac] location: class com.example.test.MyUnitTest
[javac] new A();
[javac] ^
[javac] 3 errors
Eclipse ビルドが成功すると、Ant ビルドが失敗するのはなぜですか? Eclipse と Ant のビルド システムは異なります。App in Eclipse からライブラリ プロジェクトをエクスポートしても、Ant ビルドには影響しません。Test プロジェクトには Lib プロジェクトへの可視性がないため、ビルドは失敗しました。android.library.refernce プロパティを Test/project.properties に追加してこの問題を解決しようとすると、Eclipse で Test から Lib にライブラリ参照を追加するのとまったく同じことを行ったことになります。Ant のビルドは成功しますが、テストは実行時におなじみの「クラスが予期しない DEX によって解決されました」というエラーで失敗します。
テスト プロジェクトをライブラリ プロジェクトに対してコンパイルする方法が必要ですが、dexing プロセスには含めません。このプロセスには 2 つのステップがあります。最初に、Eclipse に影響を与えない Test から Lib への参照を含めます。次に、Ant ビルド システムを更新して、ライブラリがコンパイルされ、dexing から除外されるようにします。
Test/build.xml の先頭で、ライブラリを指すプロパティを定義します。これは、Eclipse が参照しない点を除いて、Test/project.properties への参照を追加するのと似ています。
ここで、ライブラリ jar を dexing プロセスから除外する必要があります。これには、dex-helper マクロを更新する必要があります。Test/build.xml ファイルの行の後にマクロ オーバーライドを配置します。新しい dex-helper は、テスト プロジェクト フォルダー ツリーにないすべての jar ファイルを dexing プロセスから除外します。
<macrodef name="dex-helper">
<element name="external-libs" optional="yes"/>
<attribute name="nolocals" default="false"/>
<sequential>
<!-- sets the primary input for dex. If a pre-dex task sets it to
something else this has no effect -->
<property name="out.dex.input.absolute.dir" value="${out.classes.absolute.dir}"/>
<!-- set the secondary dx input: the project (and library) jar files
If a pre-dex task sets it to something else this has no effect -->
<if>
<condition>
<isreference refid="out.dex.jar.input.ref"/>
</condition>
<else>
<!--
out.dex.jar.input.ref is not set. Compile the list of jars to dex.
For test projects, only dex jar files included in the project
path
-->
<if condition="${project.is.test}">
<then>
<!-- test project -->
<pathconvert pathsep="," refid="jar.libs.ref" property="jars_to_dex_pattern"/>
<path id="out.dex.jar.input.ref">
<files includes="${jars_to_dex_pattern}">
<!-- only include jar files actually in the test project -->
<filename name="${basedir}/**/*"/>
</files>
</path>
<property name="in_jars_to_dex" refid="jar.libs.ref"/>
<property name="out_jars_to_dex" refid="out.dex.jar.input.ref"/>
<echo message="Test project! Reducing jars to dex from ${in_jars_to_dex} to ${out_jars_to_dex}."/>
</then>
<else>
<path id="out.dex.jar.input.ref"/>
</else>
</if>
</else>
</if>
<dex executable="${dx}" output="${intermediate.dex.file}" nolocals="@{nolocals}" verbose="${verbose}">
<path path="${out.dex.input.absolute.dir}"/>
<path refid="out.dex.jar.input.ref"/>
<external-libs/>
</dex>
</sequential>
</macrodef>
これらの変更により、Test は Eclipse と Ant の両方からビルドおよび実行されます。
ハッピーテスト!
その他の注意事項: Eclipse で何かがビルドされず、そうすべきだと思われる場合は、Lib、App、Test の順にプロジェクトを更新してみてください。ビルドパスを変更した後、これを頻繁に行う必要があります。また、物事が適切に機能するために、クリーンなビルドを行う必要がある場合もあります。