Slide 1

Slide 1 text

Calculon A Java DSL for Android functional testing © 2010 Matthias Käppler www.qype.com

Slide 2

Slide 2 text

My fortune cookie says... Every half-way complex app should be backed by an automated test suite!

Slide 3

Slide 3 text

Tests should be... Easy to write.

Slide 4

Slide 4 text

Tests should be... Easy to read!

Slide 5

Slide 5 text

Sorry, I don't speak binary public void whatInHeavensNameDoesThisEvenTest() { final Button b = (Button) getActivity().findViewById(R.id.b); ActivityMonitor monitor = getInstrumentation().addMonitor( BarActivity.class.getCanonicalName(), null, false); getInstrumentation().runOnMainSync(new Runnable() { public void run() { b.performClick(); } }); getInstrumentation().waitForIdleSync(); assertTrue(getInstrumentation().checkMonitorHit(monitor, 1)); }

Slide 6

Slide 6 text

What a mess!

Slide 7

Slide 7 text

Calculon to the rescue!

Slide 8

Slide 8 text

Calculon to the rescue! assertThat(R.id.button).click().starts(BarActivity.class);

Slide 9

Slide 9 text

Calculon is... … a testing library for Android.

Slide 10

Slide 10 text

Calculon is... … deployed as a JAR.

Slide 11

Slide 11 text

Calculon is... … a DSL*. *as far as that's possible in Java.

Slide 12

Slide 12 text

Calculon is... … open source!

Slide 13

Slide 13 text

Testing with Calculon Tests with Calculon are written as functional Activity tests. ActivityInstrumentationTestCase2

Slide 14

Slide 14 text

Testing with Calculon public class FooTest extends FunctionalTest { public FooTest() { super("com.example", FooActivity.class); } public void testStuff() { ... } }

Slide 15

Slide 15 text

Assertions public void testStuff() { // testing against activities assertThat()... assertThat(getActivity())... assertThat(someOtherActivity)... // testing against views assertThat(R.id.some_button)... assertThat(someButton)... // of course all Junit assertions work as well assertEquals(...) assertNotNull(...) ... }

Slide 16

Slide 16 text

Activity Assertions public void testStuff() { // testing for an orientation assertThat().inPortraitMode(); // testing for views assertThat().viewExists(R.id.some_button); // testing for input actions assertThat().keyDown(KeyEvent.KEYCODE_BACK)... // testing for custom predicates assertThat().satisfies(new Predicate() { public boolean check(Activity target) { return target.isTaskRoot(); } }); }

Slide 17

Slide 17 text

View Assertions public void testStuff() { // testing for view state assertThat(R.id.button).isVisible(); assertThat(R.id.button).isGone(); // testing for input actions assertThat(R.id.button).keyDown(KeyEvent.KEYCODE_BACK)... assertThat(R.id.button).click()... assertThat(R.id.button).longClick()... // testing for custom predicates assertThat(R.id.button).satisfies(new Predicate() { public boolean check(View target) { return target.getVisibility() == View.VISIBLE; } }); }

Slide 18

Slide 18 text

Action Assertions public void testStuff() { // testing for actions that launch a new activity assertThat(R.id.b1).click().starts(BarActivity.class); // testing for actions that finish an activity assertThat(R.id.b2).keyDown(KeyEvent.KEYCODE_Q).finishesActivity(); // testing for actions that change something assertThat(R.id.b3).click().implies(R.id.b2).isGone(); assertThat(R.id.b4).click().implies(getActivity()).inLandscapeMode(); assertThat(R.id.b5).click().implies(new Predicate() { public boolean check(Model target) { return target.someAttribute() == 5; } }); }

Slide 19

Slide 19 text

Thanks! git://github.com/kaeppler/calculon.git $ git clone