From 969adad9b0ef1f4d2e8cd48f22b023d0016587cd Mon Sep 17 00:00:00 2001 From: Bradlee Speice Date: Tue, 24 Jun 2014 00:38:43 -0400 Subject: [PATCH 1/3] I have a PoC Unit test. It needs refactoring. Desperately. --- .../bspeice/minimalbible/MinimalBible.java | 4 + .../downloader/BookListFragment.java | 8 +- .../test/DownloadActivityTest.java | 104 --------------- .../minimalbible/test/MinimalBibleTest.java | 42 ++++++ .../downloader/BookListFragmentTest.java | 123 ++++++++++++++++++ 5 files changed, 173 insertions(+), 108 deletions(-) delete mode 100644 MinimalBible/src/test/java/org/bspeice/minimalbible/test/DownloadActivityTest.java create mode 100644 MinimalBible/src/test/java/org/bspeice/minimalbible/test/MinimalBibleTest.java create mode 100644 MinimalBible/src/test/java/org/bspeice/minimalbible/test/activities/downloader/BookListFragmentTest.java diff --git a/MinimalBible/src/main/java/org/bspeice/minimalbible/MinimalBible.java b/MinimalBible/src/main/java/org/bspeice/minimalbible/MinimalBible.java index 1f62f14..42a5d65 100644 --- a/MinimalBible/src/main/java/org/bspeice/minimalbible/MinimalBible.java +++ b/MinimalBible/src/main/java/org/bspeice/minimalbible/MinimalBible.java @@ -76,6 +76,10 @@ public class MinimalBible extends Application { return graph; } + public void plusObjGraph(Object... modules) { + graph = graph.plus(modules); + } + /** * Notify jSword that it needs to store files in the Android internal directory * NOTE: Android will uninstall these files if you uninstall MinimalBible. diff --git a/MinimalBible/src/main/java/org/bspeice/minimalbible/activities/downloader/BookListFragment.java b/MinimalBible/src/main/java/org/bspeice/minimalbible/activities/downloader/BookListFragment.java index 90c875e..f980af0 100644 --- a/MinimalBible/src/main/java/org/bspeice/minimalbible/activities/downloader/BookListFragment.java +++ b/MinimalBible/src/main/java/org/bspeice/minimalbible/activities/downloader/BookListFragment.java @@ -40,7 +40,7 @@ public class BookListFragment extends BaseFragment { * The fragment argument representing the section number for this fragment. * Not a candidate for Dart (yet) because I would have to write a Parcelable around it. */ - private static final String ARG_BOOK_CATEGORY = "book_category"; + protected static final String ARG_BOOK_CATEGORY = "book_category"; private final String TAG = "BookListFragment"; @@ -48,9 +48,9 @@ public class BookListFragment extends BaseFragment { ListView downloadsAvailable; @Inject RefreshManager refreshManager; - @Inject DownloadPrefs downloadPrefs; + @Inject protected DownloadPrefs downloadPrefs; - private ProgressDialog refreshDialog; + protected ProgressDialog refreshDialog; private LayoutInflater inflater; /** @@ -93,7 +93,7 @@ public class BookListFragment extends BaseFragment { * Trigger the functionality to display a list of modules. Prompts user if downloading * from the internet is allowable. */ - private void displayModules() { + protected void displayModules() { boolean dialogDisplayed = downloadPrefs.hasShownDownloadDialog(); if (!dialogDisplayed) { diff --git a/MinimalBible/src/test/java/org/bspeice/minimalbible/test/DownloadActivityTest.java b/MinimalBible/src/test/java/org/bspeice/minimalbible/test/DownloadActivityTest.java deleted file mode 100644 index 864b637..0000000 --- a/MinimalBible/src/test/java/org/bspeice/minimalbible/test/DownloadActivityTest.java +++ /dev/null @@ -1,104 +0,0 @@ -package org.bspeice.minimalbible.test; - -import android.test.InstrumentationTestCase; -import android.util.Log; - -import org.bspeice.minimalbible.MinimalBible; -import org.bspeice.minimalbible.MinimalBibleModules; -import org.bspeice.minimalbible.activities.downloader.manager.BookDownloadManager; -import org.bspeice.minimalbible.activities.downloader.manager.DLProgressEvent; -import org.bspeice.minimalbible.activities.downloader.manager.DownloadManager; -import org.bspeice.minimalbible.activities.downloader.manager.InstalledManager; -import org.bspeice.minimalbible.activities.downloader.manager.RefreshManager; -import org.crosswire.jsword.book.Book; -import org.crosswire.jsword.book.BookException; -import org.crosswire.jsword.book.Books; -import org.crosswire.jsword.book.install.InstallException; -import org.crosswire.jsword.book.install.Installer; -import org.crosswire.jsword.passage.NoSuchKeyException; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import javax.inject.Inject; - -import dagger.Module; -import dagger.ObjectGraph; -import rx.Observable; - -import static com.jayway.awaitility.Awaitility.await; - -/** - * Tests for the Download activity - */ -public class DownloadActivityTest extends InstrumentationTestCase { - - @Module(addsTo = MinimalBibleModules.class, - injects = DownloadActivityTest.class) - public static class DownloadActivityTestModule {} - - @Inject DownloadManager dm; - @Inject InstalledManager im; - @Inject RefreshManager rm; - @Inject BookDownloadManager bdm; - - public void setUp() { - MinimalBible application = MinimalBible.getApplication(); - ObjectGraph graph = application.getObjGraph(); - ObjectGraph plusGraph = graph.plus(DownloadActivityTestModule.class); - plusGraph.inject(this); - } - - public void testBasicAssertion() { - assertEquals(true, true); - } - - /** - * Test that we can successfully download and remove a book - */ - /* Testing disabled for right now, I'm having lots of issues with the jSword API being - inconsistent on Android. These will be enabled again once I can take some time to figure that - out, or mock out the sections I need. For now in the phase of heavy development, I'll do without - - public void testInstallAndRemoveBook() { - // Install a book - Installer i = (Installer) dm.getInstallers().values().toArray()[0]; - final Book testBook = i.getBooks().get(0); - bdm.installBook(testBook); - await().atMost(30, TimeUnit.SECONDS) - .until(new Callable() { - @Override - public Boolean call() throws Exception { - return Books.installed().getBooks().contains(testBook); - } - }); - - // Validate that we can actually do something with the book - // TODO: Validate that the book exists on the filesystem too - try { - assertNotNull(testBook.getRawText(testBook.getKey("Gen 1:1"))); - } catch (BookException e) { - fail(e.getMessage()); - } catch (NoSuchKeyException e) { - fail(e.getMessage()); - } - - // Remove the book and make sure it's gone - // TODO: Validate that the book is off the filesystem - im.removeBook(testBook); - await().atMost(10, TimeUnit.SECONDS) - .until(new Callable() { - @Override - public Boolean call() throws Exception { - return !Books.installed().getBooks().contains(testBook); - } - }); - } - */ - -} diff --git a/MinimalBible/src/test/java/org/bspeice/minimalbible/test/MinimalBibleTest.java b/MinimalBible/src/test/java/org/bspeice/minimalbible/test/MinimalBibleTest.java new file mode 100644 index 0000000..d99c253 --- /dev/null +++ b/MinimalBible/src/test/java/org/bspeice/minimalbible/test/MinimalBibleTest.java @@ -0,0 +1,42 @@ +package org.bspeice.minimalbible.test; + +import android.test.InstrumentationTestCase; + +import org.bspeice.minimalbible.MinimalBible; +import org.bspeice.minimalbible.MinimalBibleModules; +import org.bspeice.minimalbible.activities.downloader.manager.BookDownloadManager; +import org.bspeice.minimalbible.activities.downloader.manager.DownloadManager; +import org.bspeice.minimalbible.activities.downloader.manager.InstalledManager; +import org.bspeice.minimalbible.activities.downloader.manager.RefreshManager; + +import javax.inject.Inject; + +import dagger.Module; +import dagger.ObjectGraph; + +import static com.jayway.awaitility.Awaitility.await; + +/** + * Tests for the Download activity + */ +public class MinimalBibleTest extends InstrumentationTestCase { + + @Module(addsTo = MinimalBibleModules.class, + injects = MinimalBibleTest.class) + public static class DownloadActivityTestModule {} + + public void setUp() { + MinimalBible application = MinimalBible.getApplication(); + ObjectGraph graph = application.getObjGraph(); + ObjectGraph plusGraph = graph.plus(DownloadActivityTestModule.class); + plusGraph.inject(this); + } + + /** + * If we've made it to the actual test, injection seems to be working correctly. + */ + public void testBasicInjection() { + assertEquals(true, true); + } + +} diff --git a/MinimalBible/src/test/java/org/bspeice/minimalbible/test/activities/downloader/BookListFragmentTest.java b/MinimalBible/src/test/java/org/bspeice/minimalbible/test/activities/downloader/BookListFragmentTest.java new file mode 100644 index 0000000..d9e7813 --- /dev/null +++ b/MinimalBible/src/test/java/org/bspeice/minimalbible/test/activities/downloader/BookListFragmentTest.java @@ -0,0 +1,123 @@ +package org.bspeice.minimalbible.test.activities.downloader; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; +import android.test.ActivityInstrumentationTestCase2; +import android.test.ActivityUnitTestCase; +import android.test.InstrumentationTestCase; +import android.view.ContextThemeWrapper; + +import org.bspeice.minimalbible.MinimalBible; +import org.bspeice.minimalbible.MinimalBibleModules; +import org.bspeice.minimalbible.R; +import org.bspeice.minimalbible.activities.downloader.ActivityDownloaderModule; +import org.bspeice.minimalbible.activities.downloader.BookListFragment; +import org.bspeice.minimalbible.activities.downloader.DownloadActivity; +import org.bspeice.minimalbible.activities.downloader.DownloadPrefs; +import org.crosswire.jsword.book.BookCategory; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.inject.Inject; + +import dagger.Module; +import dagger.ObjectGraph; +import dagger.Provides; +import de.devland.esperandro.Esperandro; + +import static com.jayway.awaitility.Awaitility.await; + +/** + * Created by bspeice on 6/23/14. + */ +public class BookListFragmentTest extends ActivityInstrumentationTestCase2 { + + @Module(injects = TestDialogDisplayedIfFirstTimeFragment.class, + addsTo = ActivityDownloaderModule.class + ) + protected static class BookListFragmentTestModule{} + + public BookListFragmentTest() { + super(DownloadActivity.class); + } + + FragmentManager mFragmentManager; + + public void setUp() throws Exception { + super.setUp(); + + mFragmentManager = getActivity().getSupportFragmentManager(); + assertNotNull(mFragmentManager); + } + + + public F startFragment(F fragment) { + try { + mFragmentManager.beginTransaction() + .replace(android.R.id.content, fragment) + .commit(); + } catch (Exception e) { + e.printStackTrace(); + } + final CountDownLatch signal = new CountDownLatch(1); + + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + mFragmentManager.executePendingTransactions(); + signal.countDown(); + } + }); + try { + signal.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return (F)(mFragmentManager.findFragmentById(android.R.id.content)); + } + + + protected class TestDialogDisplayedIfFirstTimeFragment extends BookListFragment { + /** + * If the refresh dialog is blank after calling display, it must be showing the warning + * @return Whether the warning dialog is showing + */ + public boolean callDisplayModules(DownloadPrefs prefs) { + // Inject the new preferences... + this.downloadPrefs = prefs; + displayModules(); + return (refreshDialog == null); + } + + public void setArgs(BookCategory c) { + Bundle args = new Bundle(); + args.putString(ARG_BOOK_CATEGORY, c.toString()); + this.setArguments(args); + } + } + + public void testDialogDisplayedIfFirstTime() { + /* + SharedPreferences prefs = getActivity() + .getSharedPreferences("DownloadPrefs", Context.MODE_PRIVATE); + prefs.edit().putBoolean("hasShownDownloadDialog", false); + */ + ((MinimalBible)getActivity().getApplication()).plusObjGraph(BookListFragmentTestModule.class); + TestDialogDisplayedIfFirstTimeFragment f = new TestDialogDisplayedIfFirstTimeFragment(); + f.setArgs(BookCategory.BIBLE); + startFragment(f); + + assertNotNull(f); + assertTrue(f.callDisplayModules(Esperandro.getPreferences(DownloadPrefs.class, getActivity()))); + } +} From b19b740c432517c4eba6dba65e37f6530949dab3 Mon Sep 17 00:00:00 2001 From: Bradlee Speice Date: Fri, 27 Jun 2014 21:20:53 -0400 Subject: [PATCH 2/3] Update to the latest project version --- MinimalBible/AndroidManifest.xml | 68 ++++++++++++------------ MinimalBible/build.gradle | 2 +- appcompat_v7/build.gradle | 2 +- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 +- 5 files changed, 39 insertions(+), 39 deletions(-) diff --git a/MinimalBible/AndroidManifest.xml b/MinimalBible/AndroidManifest.xml index cd934cb..caa96c4 100644 --- a/MinimalBible/AndroidManifest.xml +++ b/MinimalBible/AndroidManifest.xml @@ -1,34 +1,34 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/MinimalBible/build.gradle b/MinimalBible/build.gradle index 2314c4a..9d1429a 100644 --- a/MinimalBible/build.gradle +++ b/MinimalBible/build.gradle @@ -39,7 +39,7 @@ dependencies { android { compileSdkVersion 19 - buildToolsVersion '19.0.3' + buildToolsVersion '20' sourceSets { main { manifest.srcFile 'AndroidManifest.xml' diff --git a/appcompat_v7/build.gradle b/appcompat_v7/build.gradle index 2c144a5..f49faaf 100644 --- a/appcompat_v7/build.gradle +++ b/appcompat_v7/build.gradle @@ -6,7 +6,7 @@ dependencies { android { compileSdkVersion 19 - buildToolsVersion "19.0.3" + buildToolsVersion "20" sourceSets { main { diff --git a/build.gradle b/build.gradle index fdf10eb..0d9b5eb 100644 --- a/build.gradle +++ b/build.gradle @@ -4,6 +4,6 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:0.9.+' + classpath 'com.android.tools.build:gradle:0.12.+' } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 95a5de0..f2c754c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Jun 10 19:26:46 EDT 2014 +#Fri Jun 27 21:15:50 EDT 2014 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=http\://services.gradle.org/distributions/gradle-1.11-all.zip +distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip From 1c15767d104bb24cdb99c14fccc599ecf5da59f7 Mon Sep 17 00:00:00 2001 From: Bradlee Speice Date: Fri, 27 Jun 2014 21:35:49 -0400 Subject: [PATCH 3/3] Prettify the unit testing --- MinimalBible/build.gradle | 9 +- .../{ => src/main}/AndroidManifest.xml | 0 MinimalBible/src/test/AndroidManifest.xml | 19 +++++ .../test/MinimalBibleModulesTest.java | 20 +++++ .../minimalbible/test/MinimalBibleTest.java | 83 +++++++++++++------ .../downloader/BookListFragmentTest.java | 22 +---- 6 files changed, 106 insertions(+), 47 deletions(-) rename MinimalBible/{ => src/main}/AndroidManifest.xml (100%) create mode 100644 MinimalBible/src/test/AndroidManifest.xml create mode 100644 MinimalBible/src/test/java/org/bspeice/minimalbible/test/MinimalBibleModulesTest.java diff --git a/MinimalBible/build.gradle b/MinimalBible/build.gradle index 9d1429a..04250e6 100644 --- a/MinimalBible/build.gradle +++ b/MinimalBible/build.gradle @@ -42,7 +42,7 @@ android { buildToolsVersion '20' sourceSets { main { - manifest.srcFile 'AndroidManifest.xml' + manifest.srcFile 'src/main/AndroidManifest.xml' java.srcDirs = ['src/main/java'] resources.srcDirs = ['src/main/res'] aidl.srcDirs = ['src'] @@ -52,7 +52,12 @@ android { } // 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/ // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ... diff --git a/MinimalBible/AndroidManifest.xml b/MinimalBible/src/main/AndroidManifest.xml similarity index 100% rename from MinimalBible/AndroidManifest.xml rename to MinimalBible/src/main/AndroidManifest.xml diff --git a/MinimalBible/src/test/AndroidManifest.xml b/MinimalBible/src/test/AndroidManifest.xml new file mode 100644 index 0000000..cce9973 --- /dev/null +++ b/MinimalBible/src/test/AndroidManifest.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + diff --git a/MinimalBible/src/test/java/org/bspeice/minimalbible/test/MinimalBibleModulesTest.java b/MinimalBible/src/test/java/org/bspeice/minimalbible/test/MinimalBibleModulesTest.java new file mode 100644 index 0000000..c356ded --- /dev/null +++ b/MinimalBible/src/test/java/org/bspeice/minimalbible/test/MinimalBibleModulesTest.java @@ -0,0 +1,20 @@ +package org.bspeice.minimalbible.test; + +import org.bspeice.minimalbible.MinimalBible; +import org.bspeice.minimalbible.MinimalBibleModules; + +import dagger.Module; + +/** + * Master module for MinimalBible + */ +@Module( + injects = { + MinimalBible.class + }, + includes = { + MinimalBibleModules.class + } +) +public class MinimalBibleModulesTest { +} diff --git a/MinimalBible/src/test/java/org/bspeice/minimalbible/test/MinimalBibleTest.java b/MinimalBible/src/test/java/org/bspeice/minimalbible/test/MinimalBibleTest.java index d99c253..0f54763 100644 --- a/MinimalBible/src/test/java/org/bspeice/minimalbible/test/MinimalBibleTest.java +++ b/MinimalBible/src/test/java/org/bspeice/minimalbible/test/MinimalBibleTest.java @@ -1,42 +1,75 @@ package org.bspeice.minimalbible.test; -import android.test.InstrumentationTestCase; +import android.content.Context; import org.bspeice.minimalbible.MinimalBible; -import org.bspeice.minimalbible.MinimalBibleModules; -import org.bspeice.minimalbible.activities.downloader.manager.BookDownloadManager; -import org.bspeice.minimalbible.activities.downloader.manager.DownloadManager; -import org.bspeice.minimalbible.activities.downloader.manager.InstalledManager; -import org.bspeice.minimalbible.activities.downloader.manager.RefreshManager; -import javax.inject.Inject; - -import dagger.Module; import dagger.ObjectGraph; -import static com.jayway.awaitility.Awaitility.await; +public class MinimalBibleTest extends MinimalBible { -/** - * Tests for the Download activity - */ -public class MinimalBibleTest extends InstrumentationTestCase { + /** + * The graph used by Dagger to track dependencies + */ + private ObjectGraph graph; - @Module(addsTo = MinimalBibleModules.class, - injects = MinimalBibleTest.class) - public static class DownloadActivityTestModule {} + /** + * 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; - public void setUp() { - MinimalBible application = MinimalBible.getApplication(); - ObjectGraph graph = application.getObjGraph(); - ObjectGraph plusGraph = graph.plus(DownloadActivityTestModule.class); - plusGraph.inject(this); + 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; } /** - * If we've made it to the actual test, injection seems to be working correctly. + * 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 void testBasicInjection() { - assertEquals(true, true); + public static MinimalBibleTest getApplication() { + return instance; } + /** + * Create the {@link android.app.Application}. Responsible for building and + * holding on to the master ObjectGraph. + */ + @Override + public void onCreate() { + super.onCreate(); + //TODO: Is this necessary? + inject(this); + } + + /** + * Inject a Dagger object + * @param o The object to be injected + */ + @Override + public void inject(Object o) { + getObjGraph().inject(o); + } + + public ObjectGraph getObjGraph() { + if (graph == null) { + graph = ObjectGraph.create(MinimalBibleModulesTest.class); + } + return graph; + } } diff --git a/MinimalBible/src/test/java/org/bspeice/minimalbible/test/activities/downloader/BookListFragmentTest.java b/MinimalBible/src/test/java/org/bspeice/minimalbible/test/activities/downloader/BookListFragmentTest.java index d9e7813..5a69512 100644 --- a/MinimalBible/src/test/java/org/bspeice/minimalbible/test/activities/downloader/BookListFragmentTest.java +++ b/MinimalBible/src/test/java/org/bspeice/minimalbible/test/activities/downloader/BookListFragmentTest.java @@ -1,49 +1,31 @@ package org.bspeice.minimalbible.test.activities.downloader; -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.test.ActivityInstrumentationTestCase2; -import android.test.ActivityUnitTestCase; -import android.test.InstrumentationTestCase; -import android.view.ContextThemeWrapper; import org.bspeice.minimalbible.MinimalBible; -import org.bspeice.minimalbible.MinimalBibleModules; -import org.bspeice.minimalbible.R; -import org.bspeice.minimalbible.activities.downloader.ActivityDownloaderModule; +import org.bspeice.minimalbible.test.MinimalBibleModulesTest; import org.bspeice.minimalbible.activities.downloader.BookListFragment; import org.bspeice.minimalbible.activities.downloader.DownloadActivity; import org.bspeice.minimalbible.activities.downloader.DownloadPrefs; import org.crosswire.jsword.book.BookCategory; import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import javax.inject.Inject; import dagger.Module; -import dagger.ObjectGraph; -import dagger.Provides; import de.devland.esperandro.Esperandro; -import static com.jayway.awaitility.Awaitility.await; - /** * Created by bspeice on 6/23/14. */ public class BookListFragmentTest extends ActivityInstrumentationTestCase2 { @Module(injects = TestDialogDisplayedIfFirstTimeFragment.class, - addsTo = ActivityDownloaderModule.class + addsTo = MinimalBibleModulesTest.class ) protected static class BookListFragmentTestModule{}