Building Android Test Projects

chlai88 edited this page Apr 5, 2013 · 17 revisions

Building Android Test Projects

Under construction (please feel free to fix this up)

Put your Android test code in {project dir}/tests/src/main/(scala, java, AndroidManifest.xml, assets, res, etc.) To build the tests, use sbt tests/android:package-debug

Edit your project/build.scala to add the following missing lines as needed:

...
 settings = General.settings ++ AndroidTest.androidSettings ++ Seq(
      name := "MyScalaProjectTest", // You need to name your test project differently to avoid a circular dependency error
      libraryDependencies += "com.jayway.android.robotium" % "robotium-solo" % "2.4", // If you're using Robotium
      libraryDependencies += "junit" % "junit" % "3.8.2", // If you're using Junit
      ...
  ) dependsOn main

To build the tests and run them on a device, try:

sbt android:package-debug android:install-device tests/android:package-debug tests/android:install-device tests/android:test-device

You can alias the above in the shell with the below:

 alias instrument = ;android:package-debug;android:install-device;tests/android:package-debug;tests/android:install-device;tests/android:test-device

Or to use the emulator:

sbt android:package-debug android:install-emulator tests/android:package-debug tests/android:install-emulator tests/android:test-emulator

and its alias:

alias instrumentEmulator = ;android:package-debug;android:install-emulator;tests/android:package-debug;tests/android:install-emulator tests/android:test-emulator

As far as actually running the tests, good luck with that. I've been unsuccessful. See the (unanswered) stack overflow question.

Quick start with instrumentation.

I spent few hours (more than one) before setup my own test farm. So I hope that this information help you to start your test farm in minutes. This is just strategy, I looking for:

  • very fast environment setup.
  • any project support (simple and complex with multilevel subproject and library dependencies). I have complex :-/
  • you may setup completely independent environment for every feature (especially in manifest)
  • all code shared, no synchronization needed (I have not time to merge changes between test and production code :-/)

Copy project definition

  1. create folders
       our sbt project
         +test
           +testFeatureA
           +testFeatureB
           ....
  1. copy to folders testFeatureNN production project build.sbt (or scala project definition) and AndroidManifest.xml
  2. overwrite sbt keys mainResPath, managedJavaPath, sourceDirectory, unmanagedBase(if needed), unmanagedSourceDirectories, .... For example
unmanagedSourceDirectories in Compile <+= (baseDirectory) (_ / "../.." / "src" / "test" / "scala")

You got an idea. So you point your test environment to original resources. 4. build you project in testFeatureNNN from original location. You build use AndroidManifest.xml in testFeatureNNN directory. You may correct your manifests for each feature individually.

now you have mirror build system for your project in root directory

Upgrade your mirror to instrumentation environment

  1. add to build.sbt in testFeatureNNN test library dependencies - scalatest, robotium, ...

  2. add to manifest

<uses-library android:name="android.test.runner" />
    <instrumentation
        android:name="android.test.InstrumentationTestRunner"
        android:label="FooTest"
        android:targetPackage="blablabla" />
  1. rebuild. You have apk with instrumentation injected

Thats all!

Troubleshooting

Check that your new apk attach test classes

dexdump classes.dex | grep "org/digimead/digi/ctrl/a/main.ControlActivityTest"

TestRunner output if test class file not included

adb shell am instrument -w org.digimead.digi.ctrl/android.test.InstrumentationTestRunner

Test results for InstrumentationTestRunner=
Time: 0.0

OK (0 tests)

with class without tests

TestRunner output if tests in test class forgotten

adb shell am instrument -w -e class org.digimead.digi.ctrl.a.main.ControlActivityTest org.digimead.digi.ctrl/android.
test.InstrumentationTestRunner

junit.framework.TestSuite$1:
Failure in warning:
junit.framework.AssertionFailedError: No tests found in org.digimead.digi.ctrl.a.main.ControlActivityTest
        at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
        at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
        at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:545)
        at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1551)

Test results for InstrumentationTestRunner=.F
Time: 0.021

FAILURES!!!
Tests run: 1,  Failures: 1,  Errors: 0

Successful running

adb shell am instrument -w -e class org.digimead.digi.ctrl.a.main.ControlActivityTest org.digimead.digi.ctrl/android.
test.InstrumentationTestRunner

org.digimead.digi.ctrl.a.main.ControlActivityTest:.
Test results for InstrumentationTestRunner=.
Time: 0.123

OK (1 test)

or from sbt

> android:test-emulator
[info] testing org.digimead.digi.ctrl (1 test)
[info] passed: org.digimead.digi.ctrl.a.main.ControlActivityTest#testHelloWorld
[success] All tests passed
[success] Total time: 25 s, completed 29.05.2012 18:04:14
>

I spent only few minutes to write this, but I hope that you will save your time and be more efficient.

Native speakers, Please correct my fluent English and delete this string too ;-). Ezh

Some examples with instrumentation tests: ScalaTest, Robotium, ActivityInstrumentationTestCase2, ...