5 Commits

9 changed files with 115 additions and 144 deletions

View File

@ -2,6 +2,11 @@ language: android
env: env:
matrix: matrix:
- ANDROID_SDKS=android-19,sysimg-19 ANDROID_TARGET=android-19 ANDROID_ABI=armeabi-v7a - ANDROID_SDKS=android-19,sysimg-19 ANDROID_TARGET=android-19 ANDROID_ABI=armeabi-v7a
android:
components:
- build-tools-20.0.0
before_install: before_install:
- echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI - echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI
- emulator -avd test -no-skin -no-audio -no-window & - emulator -avd test -no-skin -no-audio -no-window &

View File

@ -52,7 +52,12 @@ android {
} }
// Move the tests to tests/java, tests/res, etc... // Move the tests to tests/java, tests/res, etc...
androidTest.setRoot('src/test') androidTest {
manifest.srcFile 'src/test/AndroidManifest.xml'
java.srcDirs = ['src/test/java']
resources.srcDirs = ['src/test/res']
assets.srcDirs = ['src/test/assets']
}
// Move the build types to build-types/<type> // Move the build types to build-types/<type>
// For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ... // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...

View File

@ -1,12 +0,0 @@
package org.bspeice.minimalbible;
/**
* Massive shout-out to <a href="https://github.com/vovkab">vovkab</a> for this idea.
*/
public interface Injectable {
public Object[] getModules();
public void inject(Object o);
}

View File

@ -10,7 +10,7 @@ import java.io.File;
import dagger.ObjectGraph; import dagger.ObjectGraph;
public class MinimalBible extends Application implements Injectable { public class MinimalBible extends Application {
/** /**
* The graph used by Dagger to track dependencies * The graph used by Dagger to track dependencies
@ -71,14 +71,13 @@ public class MinimalBible extends Application implements Injectable {
public ObjectGraph getObjGraph() { public ObjectGraph getObjGraph() {
if (graph == null) { if (graph == null) {
graph = ObjectGraph.create(getModules()); graph = ObjectGraph.create(MinimalBibleModules.class);
} }
return graph; return graph;
} }
@Override public void plusObjGraph(Object... modules) {
public Object[] getModules() { graph = graph.plus(modules);
return MinimalBibleModules.list();
} }
/** /**

View File

@ -16,12 +16,4 @@ import dagger.Module;
} }
) )
public class MinimalBibleModules { public class MinimalBibleModules {
private MinimalBibleModules() {}
public static Object[] list() {
return new Object[] {
MinimalBibleModules.class
};
}
} }

View File

@ -0,0 +1,19 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.bspeice.minimalbible">
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="20" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:name="org.bspeice.minimalbible.test.MinimalBibleTest" >
</application>
</manifest>

View File

@ -1,38 +1,75 @@
package org.bspeice.minimalbible.test; package org.bspeice.minimalbible.test;
import android.app.Application;
import android.content.Context; import android.content.Context;
import android.os.Build;
import org.bspeice.minimalbible.MinimalBible; import org.bspeice.minimalbible.MinimalBible;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import dagger.ObjectGraph; import dagger.ObjectGraph;
public class MinimalBibleTest extends Application { public class MinimalBibleTest extends MinimalBible {
public MinimalBibleTest(Context ctx) {
attachBaseContext(ctx); /**
* The graph used by Dagger to track dependencies
*/
private ObjectGraph graph;
/**
* A singleton reference to the Application currently being run.
* Used mostly so we have a fixed point to get the App Context from
*/
private static MinimalBibleTest instance;
private String TAG = "MinimalBibleTest";
/**
* Create the application, and persist the application Context
*/
public MinimalBibleTest() {
instance = this;
}
/**
* Get the Application Context. Please note, all attempts to get the App Context should come
* through here, and please be sure that the Application won't satisfy what you need.
* @return The Application Context
*/
public static Context getAppContext() {
return instance;
} }
/**
* Get the Application, rather than just the Application Context. You likely should be using
* this, rather than {@link #getAppContext()}
* @return The MinimalBible {@link android.app.Application} object
*/
public static MinimalBibleTest getApplication() {
return instance;
}
/**
* Create the {@link android.app.Application}. Responsible for building and
* holding on to the master ObjectGraph.
*/
@Override @Override
public void attachBaseContext(Context base) { public void onCreate() {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) { super.onCreate();
super.attachBaseContext(base); //TODO: Is this necessary?
} else { inject(this);
try { }
Class<Application> applicationClass = Application.class;
Method attach = applicationClass.getDeclaredMethod("attach", Context.class); /**
attach.setAccessible(true); * Inject a Dagger object
attach.invoke(this, base); * @param o The object to be injected
} catch (NoSuchMethodException e) { */
e.printStackTrace(); @Override
} catch (IllegalAccessException e) { public void inject(Object o) {
e.printStackTrace(); getObjGraph().inject(o);
} catch (InvocationTargetException e) { }
e.printStackTrace();
} public ObjectGraph getObjGraph() {
if (graph == null) {
graph = ObjectGraph.create(MinimalBibleModulesTest.class);
} }
return graph;
} }
} }

View File

@ -1,28 +0,0 @@
package org.bspeice.minimalbible.test;
import android.content.Context;
import org.bspeice.minimalbible.Injectable;
import dagger.ObjectGraph;
/**
* Created by bspeice on 6/27/14.
*/
public abstract class MinimalBibleTestMockable extends MinimalBibleTest implements Injectable {
private ObjectGraph mObjectGraph;
public MinimalBibleTestMockable(Context context) {
super(context);
mObjectGraph = ObjectGraph.create(getModules());
}
@Override
public abstract Object[] getModules();
@Override
public void inject(Object o) {
mObjectGraph.inject(o);
}
}

View File

@ -1,88 +1,47 @@
package org.bspeice.minimalbible.test.activities.downloader; package org.bspeice.minimalbible.test.activities.downloader;
import android.app.Application;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.test.ActivityUnitTestCase; import android.test.ActivityInstrumentationTestCase2;
import org.bspeice.minimalbible.MinimalBible; import org.bspeice.minimalbible.MinimalBible;
import org.bspeice.minimalbible.activities.downloader.BookListFragment; import org.bspeice.minimalbible.activities.downloader.BookListFragment;
import org.bspeice.minimalbible.activities.downloader.DownloadActivity; import org.bspeice.minimalbible.activities.downloader.DownloadActivity;
import org.bspeice.minimalbible.activities.downloader.DownloadPrefs; import org.bspeice.minimalbible.activities.downloader.DownloadPrefs;
import org.bspeice.minimalbible.test.MinimalBibleModulesTest; import org.bspeice.minimalbible.test.MinimalBibleModulesTest;
import org.bspeice.minimalbible.test.MinimalBibleTest;
import org.bspeice.minimalbible.test.MinimalBibleTestMockable;
import org.crosswire.jsword.book.BookCategory; import org.crosswire.jsword.book.BookCategory;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import javax.inject.Inject;
import dagger.Module; import dagger.Module;
import dagger.Provides;
import de.devland.esperandro.Esperandro; import de.devland.esperandro.Esperandro;
/** /**
* Created by bspeice on 6/23/14. * Created by bspeice on 6/23/14.
*/ */
public class BookListFragmentTest extends ActivityUnitTestCase<DownloadActivity> { public class BookListFragmentTest extends ActivityInstrumentationTestCase2<DownloadActivity> {
private static Class activityUnderTest = DownloadActivity.class;
@Module(injects = TestDialogDisplayedIfFirstTimeFragment.class, @Module(injects = TestDialogDisplayedIfFirstTimeFragment.class,
addsTo = MinimalBibleModulesTest.class, addsTo = MinimalBibleModulesTest.class
overrides = true
) )
protected static class BookListFragmentTestModule{ protected static class BookListFragmentTestModule{}
@Provides
DownloadPrefs providePrefs() {
return Esperandro.getPreferences(DownloadPrefs.class,
MinimalBible.getApplication());
}
}
public BookListFragmentTest() { public BookListFragmentTest() {
super(activityUnderTest); super(DownloadActivity.class);
} }
@Inject DownloadPrefs downloadPrefs;
FragmentManager mFragmentManager; FragmentManager mFragmentManager;
private Application mApplication;
private Context mContext;
@Override
public void setUp() throws Exception { public void setUp() throws Exception {
super.setUp(); super.setUp();
// Set 'dexmaker.dexcache' system property, otherwise sometimes it is null and test will crash mFragmentManager = getActivity().getSupportFragmentManager();
// System.setProperty("dexmaker.dexcache", getInstrumentation().getTargetContext().getCacheDir().getPath()); assertNotNull(mFragmentManager);
mContext = new ContextWrapper(getInstrumentation().getTargetContext()) {
@Override
public Context getApplicationContext() {
return mApplication;
}
};
mApplication = new MinimalBibleTestMockable(mContext) {
@Override public Object[] getModules() {
return new Object[]{new BookListFragmentTestModule()};
}
};
setApplication(mApplication);
} }
@Override
public void tearDown() throws Exception {
super.tearDown();
}
public <F extends Fragment> F startFragment(F fragment) { public <F extends Fragment> F startFragment(F fragment) {
try { try {
@ -109,19 +68,15 @@ public class BookListFragmentTest extends ActivityUnitTestCase<DownloadActivity>
return (F)(mFragmentManager.findFragmentById(android.R.id.content)); return (F)(mFragmentManager.findFragmentById(android.R.id.content));
} }
public void testApplicationReplacementWorks() {
setActivityContext(mContext);
startActivity(new Intent(mContext, activityUnderTest), null, null);
assertTrue(getActivity().getApplicationContext() instanceof MinimalBibleTestMockable);
}
protected class TestDialogDisplayedIfFirstTimeFragment extends BookListFragment { protected class TestDialogDisplayedIfFirstTimeFragment extends BookListFragment {
/** /**
* If the refresh dialog is blank after calling display, it must be showing the warning * If the refresh dialog is blank after calling display, it must be showing the warning
* @return Whether the warning dialog is showing * @return Whether the warning dialog is showing
*/ */
public boolean callDisplayModules() { public boolean callDisplayModules(DownloadPrefs prefs) {
// Inject the new preferences...
this.downloadPrefs = prefs;
displayModules(); displayModules();
return (refreshDialog == null); return (refreshDialog == null);
} }
@ -134,30 +89,29 @@ public class BookListFragmentTest extends ActivityUnitTestCase<DownloadActivity>
} }
public void testDialogDisplayedIfFirstTime() { public void testDialogDisplayedIfFirstTime() {
setActivityContext(mContext); ((MinimalBible)getActivity().getApplication()).plusObjGraph(BookListFragmentTestModule.class);
startActivity(new Intent(mContext, activityUnderTest), null, null);
TestDialogDisplayedIfFirstTimeFragment f = new TestDialogDisplayedIfFirstTimeFragment(); TestDialogDisplayedIfFirstTimeFragment f = new TestDialogDisplayedIfFirstTimeFragment();
f.setArgs(BookCategory.BIBLE); f.setArgs(BookCategory.BIBLE);
startFragment(f); startFragment(f);
assertNotNull(f); DownloadPrefs prefs = Esperandro.getPreferences(DownloadPrefs.class, getActivity());
prefs.hasShownDownloadDialog(false);
downloadPrefs.hasShownDownloadDialog(false); assertNotNull(f);
assertTrue(f.callDisplayModules()); assertTrue(f.callDisplayModules(Esperandro.getPreferences(DownloadPrefs.class, getActivity())));
} }
public void testRefreshDisplayedAfterFirstTime() { public void testRefreshDisplayedAfterFirstTime() {
setActivityContext(mContext); ((MinimalBible)getActivity().getApplication()).plusObjGraph(BookListFragmentTestModule.class);
startActivity(new Intent(mContext, activityUnderTest), null, null);
TestDialogDisplayedIfFirstTimeFragment f = new TestDialogDisplayedIfFirstTimeFragment(); TestDialogDisplayedIfFirstTimeFragment f = new TestDialogDisplayedIfFirstTimeFragment();
f.setArgs(BookCategory.BIBLE); f.setArgs(BookCategory.BIBLE);
startFragment(f); startFragment(f);
assertNotNull(f); DownloadPrefs prefs = Esperandro.getPreferences(DownloadPrefs.class, getActivity());
prefs.hasShownDownloadDialog(true);
downloadPrefs.hasShownDownloadDialog(true); assertNotNull(f);
assertFalse(f.callDisplayModules()); assertFalse(f.callDisplayModules(Esperandro.getPreferences(DownloadPrefs.class, getActivity())));
} }
} }