Slide 1

Slide 1 text

Tips and Tricks for Testing Lambda Expressions in Android David Carver CareWorks Tech Google Plus: David Carver Github: kingargyle

Slide 2

Slide 2 text

Agenda ● Anonymous Classes and Lambdas ○ Definitions ○ Use in Android Applications ■ Lambdas in Android ● Retro Lambda ● Jack and Jill ● The Problems ● Tips and Tricks

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Unit Testing vs Integration Testing Unit Tests try to test the smallest portion of code individually and independently … for proper operation. Integration Tests test blocks of code as a group. It occurs after unit testing and before validation testing.

Slide 5

Slide 5 text

About Anonymous Classes and Lambdas

Slide 6

Slide 6 text

Anonymous Classes As defined by Java In a Nutshell, “an anonymous class is defined and instantiated in a single succinct expression using the new operator”

Slide 7

Slide 7 text

Where are Anonymous Classes Commonly Used in Android? ● Runnables ● View Listeners ○ OnClickListener, OnLongClickListener, OnFocusChangeListener, OnDragListener, OnTouchListener, etc ● Comparators ● Handler Callbacks ● Loaders ○ OnLoadCanceledListener ○ OnLoadCompleteListener

Slide 8

Slide 8 text

What Are Lambda Expressions? Microsoft MSDN, July 20, 2015 A lambda expression is an anonymous function that you can use to create delegates or expressions….you can write local functions that can be passed as arguments or returned as the value of the function.

Slide 9

Slide 9 text

What Are Lambda Expressions? Another way to pass code blocks around, but in a more compact syntax. Lambda encourage you to do functional (what you want down, not specifically how it is done) programming instead of an imperative (procedural, how it should be done).

Slide 10

Slide 10 text

Lambdas vs Anonymous Classes Lambdas allow a cleaner syntax for Anonymous Classes that contain a single method that needs to be implemented .

Slide 11

Slide 11 text

Lambda onClickListener implementation Lambda syntax for an onClickListener representation.

Slide 12

Slide 12 text

Android and Lambdas ● RetroLambda - https://github.com/orfjackal/retrolambda ○ Backports the Java 8 support for Lambdas ○ Allows the use Lambdas all the way back to Java 5. ○ Generates code at compile time ○ Gradle Plugin - https://github.com/evant/gradle-retrolambda ● Jack and Jill - http://tools.android.com/tech-docs/jackandjill ○ Android specific compiler ○ Natively supports Java 8 and Lambdas ○ Only supports back to Java 7 ■ No Java 6 support for older devices ○ Will be the standard android compiler going forward.

Slide 13

Slide 13 text

So What is the Problem? Lambdas as used in Java currently, are a cleaner syntax for single method anonymous classes. ● Trying to write tests leads to writing integration tests ● Leads to duplication of Code ● Can lead to hard to maintain code ○ Multiple inline overrides embedded multiple levels deep. ● Testing code that requires a Framework or other layers to work leads to tests that need more setup. ○ Can lead to longer execution time of your tests ○ More difficult to setup tests

Slide 14

Slide 14 text

Performance Lambda Expressions are not as optimized by the compiler currently as standard imperative ways of accomplishing the same thing. Imperative is still faster in the following areas: ● Iterators ● For Each Benchmarks are tricky and can be misleading, but be careful going hog wild with lambdas as they can introduce slow points in your code. http://blog.takipi.com/benchmark-how-java-8-lambdas-and-streams-can-make-your-code-5-times-slower/

Slide 15

Slide 15 text

Anonymous Classes plague Graphical User Interface work. They are convenient. However, hard to unit test. Lambdas can be used many places that you would implement an Anonymous class. They suffer the same testing problem as Anonymous Classes. It leads to integration testing and not unit testing.

Slide 16

Slide 16 text

HOW DO WE BRING ORDER OUT OF CHAOS?

Slide 17

Slide 17 text

AVOID USING ANONYMOUS CLASSES!

Slide 18

Slide 18 text

AVOID USING LAMBDAS!

Slide 19

Slide 19 text

DO NOT OVER USE LAMBDAS BECAUSE THEY ARE CONVENIENT.

Slide 20

Slide 20 text

DO WHAT IS RIGHT. NOT WHAT IS EASY.

Slide 21

Slide 21 text

You are going to use them anyways right?

Slide 22

Slide 22 text

Tips and Tricks

Slide 23

Slide 23 text

Where are Lambdas Commonly Used in Android? ● RXJava and RXJava for Android ○ Anywhere the Action class/interface would normally be implemented. ○ Anywhere where anonymous inline overrides would have been used. ○ If you are doing RX… you are probably using Lambdas otherwise you go insane. ● Implementation of Interfaces ○ Handlers ○ Runnables ○ Listeners ○ Any place you could use an anonymous class with a single method. All of these places are also where you typically have Unit Testing pain points.

Slide 24

Slide 24 text

What is RXJava and RX Android? A library for composing asynchronous and event-based programs by using observable sequences. It is an implementation of ReactiveX (Reactive Extensions). https://github.com/ReactiveX/RxJava/wiki

Slide 25

Slide 25 text

RXJava Syntax for Java 7

Slide 26

Slide 26 text

RXJava Syntax for Java 8

Slide 27

Slide 27 text

Implement Concrete Class from Interface ● Simple POJO ● Typically the fastest to execute ● Typically the least complicated to setup ● Can be reused in other places in your application. Many Android examples use Anonymous Classes. Stop following these examples.

Slide 28

Slide 28 text

Implement the Interface on a View/Fragment/Activity This is fine .... until your class starts becoming a GOD class that wants to do everything. Avoid GOD classes… they become a nightmare to test.

Slide 29

Slide 29 text

Easier View Listener Testing

Slide 30

Slide 30 text

Robolectric and Butterknife ● Robolectric ○ Unit Test Framework that runs on your computer ■ No Device needed ■ No Simulator ■ Simulates Android ■ Runs on your machine. ● ButterKnife ○ Developed by Jake Wharton ○ Part of the Square Development Stack ○ Generates Code based on Annotations ■ @BindView, @BindInt, @BindBoolean ■ @OnClick, @OnLongClick

Slide 31

Slide 31 text

ButterKnife onClick Binding Example

Slide 32

Slide 32 text

ButterKnife onClick Binding Example

Slide 33

Slide 33 text

ButterKnife Testing Advantages ● No Anonymous classes ● Lambdas are not necessary ● Less Likely to lead to an Integration Test ○ Allows for a pure unit test without executing more code than necessary ● Simpler tests ○ Leading to faster execution of the tests ● Cleaner Code leading to easier maintenance ● Can Bind onClicks to multiple views allowing for easier code re-use.

Slide 34

Slide 34 text

Testing Lambdas in RXJava ● RXJava allows for easier implementation of Async Tasks ○ File operations ○ Database Acccess ○ Remote Procedure Calls ○ Any type of Background Tasks ○ Can support Event Bus style notifications ● Lambdas can make writing RXJava Observables cleaner ○ No Messy inline override syntax ● However, RXJava leads to more Integration Style Tests ● Tests are harder to setup, and more complicated to verify and isolate.

Slide 35

Slide 35 text

Common RXJava Test Situations ● Subscribers and Error conditions ● Subjects ● Map Flatteners ● Joins The simplest way to test these is to extract the functionality to a method, and test the code that is intended to be executed separately.

Slide 36

Slide 36 text

Extract to Method

Slide 37

Slide 37 text

Extract to Method Extracting this out allows for testing of the expected behavior of this code without executing the subscribe directly. It also keeps your code potentially cleaner.

Slide 38

Slide 38 text

RXJava TestSubscriber ● Allows you to execute the subscribe, and error portions of an RXJava Observable. ● Provides the simplest method for executing the least amount of code possible. ● Use in combination with Mockito/EasyMock to provide mocks for the Observables that are being subscribed too. ● This is still an Integration Test ○ Requires RXJava Framework to execute in order to test the conditions and code in the Lambda expression. ○ Less Complicated though than trying to Mock Out the RXJava Framework itself.

Slide 39

Slide 39 text

RXJava Testing Error Conditions

Slide 40

Slide 40 text

RXJava TestSubscriber - code under test

Slide 41

Slide 41 text

RXJava TestSubscriber - subscribe

Slide 42

Slide 42 text

RXJava - Testing Subjects with Schedulers

Slide 43

Slide 43 text

Summary ● Leverage Lambdas ○ Make sure you are using for the right reasons, not because you can. ○ They can provide cleaner code, but can make it more complicated to test. ● Prefer implementing your Interfaces as re-usable classes ○ Easier to strictly unit test ○ Reduce code duplication ● Leverage Butterknife when possible for binding click events ○ Allows simpler tests ○ Cleaner test setup and execution ● Consider extracting lambdas that contain complicated code to either Classes or methods.

Slide 44

Slide 44 text

Resources ● RXJava - https://github.com/ReactiveX/RxJava ● RXJava for Android - https://github.com/ReactiveX/RxAndroid ● RetroLambda - https://github.com/orfjackal/retrolambda ● ButterKnife - http://jakewharton.github.io/butterknife/ ● Robolectric - https://github.com/robolectric/robolectric ● Mockito - http://site.mockito.org/ ● Testing RX Java Observables - https://labs.ribot.co.uk/unit-testing-rxjava-6e9540d4a329#.9ydk0xq9b ● Testing Lambda Expressions - http://radar.oreilly.com/2014/12/unit-testing-java-8-lambda-expressions-and-strea ms.html

Slide 45

Slide 45 text

Resources