Continuing with my series of boardgame-related side projects, I've written a small holo-themed app for determining who goes first called (unsurprisingly) Who Goes First. As with most side projects it's also open source. I released this app a while ago but thought I'd mention it here.
There wasn't much complex about it; mostly I was pleased with how easy it is to make a good-looking app with holo theming (even if you're not very talented in the design department).
The only interesting thing I learned relate to the arrow pointing towards who goes first. If you need more than six arrows, then it'll just show "X#" inside of the arrow instead. This required scaling the text size depending on how long the text was. I ended up using a Region for the arrow (defined via the Path used to construct the arrow) and another Region for the text and test if they overlapped; if they did, shrink text size until they don't. You can check out what I'm talking about in the actual ArrowView.
The one problem I've run into is when there are multiple people at the table with this app. The app does not use networking to sync their random seeds, so you can end up with multiple people going first. I guess my next project will have to be a "Who Runs Who Goes First First" app. :)
I post random things I've learned while coding with the hope that it will save people time and effort.
Wednesday, December 18, 2013
Monday, December 16, 2013
Testing on Android (Part 1): Unit Tests
I've recently been doing research on Android testing. I'm quite new to this business; automated testing has (for the longest time) felt unnecessary. But I've been slowly convinced that the benefits outweigh the time costs - as long as you do it in an efficient manner. To that end, I set out to evaluate the many, many Android testing frameworks to see which ones seemed to save the most time.
I began by summarizing all the tools/services I could find in a spreadsheet (let me know if I'm missing anything). Beyond that, I am going to do a series of posts going into more detail about different parts of Android testing:
Unit Tests
There's no reason you can't use normal JUnit 4 testing for Android applications... as long as you stay away from anything Android.
Normally you compile against the SDK's android.jar, which contains nothing but stubbed methods that throw exceptions when run. When you actually upload your APK to a device, it uses the device's implementations of all those stubs. As a result, when running normal unit tests in your IDE, you get no access to those framework implementations (instead receiving mountains of exceptions). This is not a big deal if you're testing some simple functionality that doesn't touch Android itself.
Pros:
The Android testing framework is the official method of unit testing on Android. It loads your application onto a device, then runs JUnit-based test suites. Since it runs on the actual OS you can use the Android framework as you normally would in your application and can conduct a series of realistic tests that way.
Ostensibly the testing framework is unit testing, but the slowness of having to fully compile and upload your app onto a device before executing any tests makes testing slow. Plus, you have to make sure you've got a device attached or an emulator running. As a result, I might consider the testing framework for semi-regular tests (e.g., whenever you push a new commit, or nightly tests) but I would have trouble using them while actively developing.
Pros:
Robolectric is a project that unifies the speed of unit testing with the ability to access the Android framework. It does this by implementing all those stubs with mocked classes.
Having tried it out, it is lightning fast and works as expected. I'm also impressed with the amount of active development on it - this is a rapidly improving framework. However, the active development does take a toll; documentation is a bit lacking, plus some new versions of Robolectric break things in previous versions. Plus, it can't mock everything - for example, inter-app communication - since it's not on an actual Android OS. That said, the benefits here far outweigh the negatives when it comes to unit testing Android.
Pros:
I'm a fan of what Jason Sankey said on StackOverflow about tiered unit testing: Prefer pure unit tests, then Robolectric, then the Android testing framework. The tests get harder/slower the higher the tier, but sometimes you need it.
I began by summarizing all the tools/services I could find in a spreadsheet (let me know if I'm missing anything). Beyond that, I am going to do a series of posts going into more detail about different parts of Android testing:
- Part 1: Unit Tests
- Part 2: Functional Tests
- Part 3: Other Testing Tools
- Part 4: Testing Services
- Spreadsheet: Android Testing
Unit Tests
There's no reason you can't use normal JUnit 4 testing for Android applications... as long as you stay away from anything Android.
Normally you compile against the SDK's android.jar, which contains nothing but stubbed methods that throw exceptions when run. When you actually upload your APK to a device, it uses the device's implementations of all those stubs. As a result, when running normal unit tests in your IDE, you get no access to those framework implementations (instead receiving mountains of exceptions). This is not a big deal if you're testing some simple functionality that doesn't touch Android itself.
Pros:
- Fast and easy
- Cannot use any Android framework classes
The Android testing framework is the official method of unit testing on Android. It loads your application onto a device, then runs JUnit-based test suites. Since it runs on the actual OS you can use the Android framework as you normally would in your application and can conduct a series of realistic tests that way.
Ostensibly the testing framework is unit testing, but the slowness of having to fully compile and upload your app onto a device before executing any tests makes testing slow. Plus, you have to make sure you've got a device attached or an emulator running. As a result, I might consider the testing framework for semi-regular tests (e.g., whenever you push a new commit, or nightly tests) but I would have trouble using them while actively developing.
Pros:
- Access to the Android framework
- Slow
- Requires attached device or running emulator
- Uses JUnit 3 (instead of the newer JUnit 4)
Robolectric is a project that unifies the speed of unit testing with the ability to access the Android framework. It does this by implementing all those stubs with mocked classes.
Having tried it out, it is lightning fast and works as expected. I'm also impressed with the amount of active development on it - this is a rapidly improving framework. However, the active development does take a toll; documentation is a bit lacking, plus some new versions of Robolectric break things in previous versions. Plus, it can't mock everything - for example, inter-app communication - since it's not on an actual Android OS. That said, the benefits here far outweigh the negatives when it comes to unit testing Android.
Pros:
- Fast
- Can access mocked Android framework
- Actively developed
- Not the true Android framework
- Not everything is mocked
- Lacking documentation
I'm a fan of what Jason Sankey said on StackOverflow about tiered unit testing: Prefer pure unit tests, then Robolectric, then the Android testing framework. The tests get harder/slower the higher the tier, but sometimes you need it.
Thursday, December 5, 2013
Thoughts on the Current State of Android IDEs
I've repeatedly been getting the question "which IDE should I use for Android?" recently so I'm writing up a brief summary. Here's my current thoughts on the state of Android IDEs (circa December 2013):
Eclipse + ADT
The original Android IDE, officially supported by Google.
IntelliJ IDEA + Android Plugin
A Java IDE that has an Android plugin built for it by IntelliJ. This is the one IDE I haven't used extensively, so take my comments with a grain of salt.
Android Studio + Gradle
Android Studio is a fork of IntelliJ IDEA with gradle-based build support.
Eclipse + ADT
The original Android IDE, officially supported by Google.
- Supports the most features for creating/building Android apps.
- Abundant documentation, both from Google and from years of people asking questions about it on StackOverflow.
- Many 3rd party tools, since it's been the main player for years.
- Relatively stable; your project won't suddenly stop building when you update your sources.
IntelliJ IDEA + Android Plugin
A Java IDE that has an Android plugin built for it by IntelliJ. This is the one IDE I haven't used extensively, so take my comments with a grain of salt.
- A fan favorite; people rave about IntelliJ (especially those who were burned in one way or another by Eclipse).
- As stable (if not more so) than Eclipse, because it lacks some of the built-in instabilities in Eclipse (aka, randomly crashing every once in a while).
- Does not support NDK.
Android Studio + Gradle
Android Studio is a fork of IntelliJ IDEA with gradle-based build support.
- Gradle is the future of Android build processes, so using it you'll be one step ahead of the curve.
- Since it's still heavily in development Android Studio is quite unstable. It's gone from rarely working to only stabbing you in the back every once in a while, but use of it requires extra maintenance work.
- Does not support all features, like NDK or lint. (There are workarounds, though.)
- Improves weekly because that's about how often they push out updates. If you love cutting edge technology that's a pro, if you like stability that's a con. (You can switch off of the "canary" update channel if you're more conservative.)
- If you need all Android features (like NDK support), use Eclipse.
- If you hate Eclipse, use IntelliJ IDEA.
- If you love gradle builds or want to plan for the future and are willing to put in some extra effort, use Android Studio.
Also, if you've got anything to add let me know - I'd be curious if there's some important pieces I'm leaving out, as I am far from an IDE expert.
Tuesday, December 3, 2013
Streaming JSON Parsing Performance Test: Jackson vs. GSON
A few years ago, when speed and memory became a concern in one of my Android apps, I implemented some streaming JSON parsing using Jackson. At the time I chose Jackson over Gson because the benchmarks seemed to show it was significantly faster*; however, I've heard that recent versions of Gson rival Jackson for speed. I want to re-examine the benchmarks again to make sure I'm choosing the right library.
The best benchmark I found is at json-benchmark. There were a number of other benchmarks out there but they didn't appeal to me for various reasons, either because they didn't provide source, the benchmark didn't seem very fair, or it didn't test on the Dalvik VM.
Unfortunately, json-benchmark's last documented test is from two and a half years ago. I decided to try to reproduce these tests against the latest libraries, Jackson 2.3 and Gson 2.2.4. There were a few trials getting the test to run again:
Of course your mileage may vary depending on what exactly you're parsing, but with somewhere between 1.5-2x the speed I think I'll stick Jackson when I need my JSON parsing to be fast.
* Speed isn't everything; if Gson was only marginally slower than Jackson I still would have preferred it; I find their streaming parsing paradigm easier to use.
The best benchmark I found is at json-benchmark. There were a number of other benchmarks out there but they didn't appeal to me for various reasons, either because they didn't provide source, the benchmark didn't seem very fair, or it didn't test on the Dalvik VM.
Unfortunately, json-benchmark's last documented test is from two and a half years ago. I decided to try to reproduce these tests against the latest libraries, Jackson 2.3 and Gson 2.2.4. There were a few trials getting the test to run again:
- The JSON benchmarking code has moved to libcore, so I checked out and referenced the latest benchmarks from there.
- The ParseBenchmarks code to test Jackson and GSON directly was removed, so I had to re-add it (using the same old code, but with some package names updated).
- vogar uses old assumptions about where "dx" (and related tools) are located; it still thinks they are in $ANDROID_HOME/platform-tools. Rather than fix and recompile I just made my files match its assumptions for a bit.
document api ms linear runtime TWEETS ANDROID_STREAM 19.82 === TWEETS JACKSON_STREAM 11.47 == TWEETS GSON_STREAM 17.98 === TWEETS GSON_DOM 39.00 ======= TWEETS ORG_JSON 30.86 ===== TWEETS XML_PULL 26.08 ==== TWEETS XML_DOM 85.32 =============== TWEETS XML_SAX 33.83 ====== READER_SHORT ANDROID_STREAM 4.60 = READER_SHORT JACKSON_STREAM 2.99 = READER_SHORT GSON_STREAM 4.36 = READER_SHORT GSON_DOM 8.07 = READER_SHORT ORG_JSON 6.42 = READER_SHORT XML_PULL 6.75 = READER_SHORT XML_DOM 14.84 == READER_SHORT XML_SAX 5.54 = READER_LONG ANDROID_STREAM 38.24 ======= READER_LONG JACKSON_STREAM 18.12 === READER_LONG GSON_STREAM 43.81 ======== READER_LONG GSON_DOM 72.34 ============= READER_LONG ORG_JSON 52.47 ========= READER_LONG XML_PULL 65.53 ============ READER_LONG XML_DOM 160.02 ============================== READER_LONG XML_SAX 47.37 ========
Of course your mileage may vary depending on what exactly you're parsing, but with somewhere between 1.5-2x the speed I think I'll stick Jackson when I need my JSON parsing to be fast.
* Speed isn't everything; if Gson was only marginally slower than Jackson I still would have preferred it; I find their streaming parsing paradigm easier to use.
Subscribe to:
Posts (Atom)