Insider's Guide To Udacity Android Developer Nanodegree Part 4 - Build it Bigger |
Written by Nikos Vaggalis | |||||
Monday, 02 October 2017 | |||||
Page 4 of 4
Putting it all togetherThat took care of the GCE and the Joke generating library, so let's now have a high level overview of the flow of the application: Clicking on the main's 'app' screen 'Show a Joke' button, fires an Asynctask which communicates with the GCE. The GCE in turn calls into the Java library joke generator 'jokelib', retrieves the joke and returns it to app which in turn forwards it to the Android library 'showlib', the one that finally displays it:
This also goes to highlight the difference between a Java and Android library;the latter has the ability to bundle resources and have a UI as such acting like a self-contained Activity but with the added restriction that it can only be instantiated by another Activity. FlavorsAnother requirement specifically introduced in order to make you really dig into Gradle's build configuration was to create two product flavors that group the source code according to functionality.
For Gradle this just required tweaking the productFlavors configuration block: productFlavors { free { applicationId
"com.example.udacity.declaringflavors.free"
} paid { applicationId "com.example.udacity.declaringflavors.paid" } }
Now what was left was to write the code for each case, something that Fragments are perfect for since they permit having a common 'main' code base but differentiate through multiple instances which host the per case code.
TestingWe've already utilized testing in the previous modules, specifically local unit testing with Junit and UI instrumentation/ connected/ integrated testing with Espresso.Yes, the terminology is not of much help. The primary distinction between the two,is that unit tests run on a regular Java VM on your computer. And connected tests run on an Android device or emulator.In general, you should use unit tests for testing generic, non-Android related classes as any such code that calls the android API will fail. In this case, you should either use a mocking framework like Makido, to mock the appropriate android dependencies, or use a connected test instead. Nicely settled by the instructors. The focus here is on the Connected part only, also performed through JUnit, with the difference from Espresso being that we don't test the UI itself but instead isolate non UI related tasks that must be run on an Android Virtual machine, Emulator or Physical Device, and test them against some predefined assertions. In this case the tests had to "verify that the AsyncTask is indeed loading jokes“ and "that the Async task successfully retrieves a non-empty string”. The issue here was that by design I had the AsyncTask retrieving the joke by connecting to the GCE and subsequently passing it on to the Android library (showlib) through its PostExecute method.
new Intent(context, ShowActivity.class); This was hindering testing as the AsyncTask couldn't be isolated and checked against the test's requirements since the returned joke would had been only accessible from within PostExecute calling the 'showlib' Activity as such tying AsyncTask to the UI. This would require writing tests against the UI too (with Espresso) which would defy JUnit's usage in the first place. Alternatively, I could had modified the code so that again inside Postexecute, would instead use an Interface that would play the role of communicating the joke from the AsyncTask back to the app's main Activity, that way also delegating calling 'showlib' to it. This would avoid calling 'showlib' inside PostExecute, as such AsyncTask's could now run in isolation and independent of the UI. But since I wasn't in the mood to disturb the balance already established, and as this was a class on Gradle after all, I used Gradle's flexible configuration to my advantage. So I just made a new AsyncTask that doesn't use PostExecute which would consume the retrieved joke, but instead returns it to its caller. This technique, while not appropriate for returning a joke back to the UI thread was sufficient for a standalone test and on its own thread. The test related code could then be run in its own isolated thread container:
package com.udacity.gradle.builditbigger; import android.support.test.InstrumentationRegistry; import org.junit.Assert; @RunWith(AndroidJUnit4.class)
The test simply checks that the length of the string/joke returned is in fact 5, as the jokes available 'joke1','joke2', and so on are all of them of length 5. After writing the test code I directed Gradle to initialize the new EndpointsAsyncTaskTest (aTest) the one without the PostExecute method, from the custom directory 'src/instruTest/java'
This made the test pass and placed the final element in the project. Closing upClosing up, I found "Gradle for Android and Java" a pleasant intermission in the Nanodegree, one that included a challenging project that required merging quite a few diverse concepts. There's a few other things that I would have liked to see included in the class, like the difference between the CompileSdk and TargetSdk configuration options; Gradle's Runtime vs Compile time scope of dependencies and especially more material on Connected testing, but nevertheless I have learned a lot, once again.
More InformationNikos Vaggalis - "Build it Bigger" on GitHub Related ArticlesInsider's Guide To Udacity Android Developer Nanodegree - 1 Insider's Guide To Udacity Android Developer Nanodegree - 2 Insider's Guide To Udacity Android Developer Nanodegree - 3 To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.
Comments
or email your comment to: comments@i-programmer.info |
|||||
Last Updated ( Monday, 20 November 2017 ) |