Tomasz Polanski - Automated mobile testing 2016 - Testing: why, when, how

  • View
    655

  • Download
    3

  • Category

    Mobile

Preview:

Citation preview

TESTING

Tomek Polanskitpolansk

WHY?WHEN?HOW?

“Too much time pressure with making visible changes.

Customer doesn't appreciate tests enough.”

“To make iterations as fast as possible I would not use tests for prototypes or early

MVPs.”

“Specs are too volatile, tests would just need to be updated constantly.”

“Writing tests is hard, they might be difficult to understand.”

“Nobody else in the project uses them.

They weren't done or were broken when I got involved.”

Time and budget“Too much time

pressure with making visible changes”

Instant changes Return on investment

vs

Speed

“Not for prototypes or early MVPs”

Time

Pro

gres

s

Prototype

Minimum Viable

ProductLovable

by Henrik Kniberg

Constant ChangeThe

“Specs are too volatile”

Programming is hard

https://deeguns.files.wordpress.com/2013/07/computerman.jpg

urbanattitude.fr/wp-content/uploads/2015/03/BER_08.jpg

Architecture

“Tests are hard and difficult to understand”

Maintenance

“Missing/broken tests”

What should unit tests look like?

Fast

Reliable

Simple to understand

@Testpublic void get_whenElementExists() {

List<String> list = Collections.singletonList(DEFAULT);

assertThat(get(list, 0)).isEqualTo(DEFAULT);}

@Testpublic void get_whenIndexTooBig_returnNull() {

List<String> list = Collections.singletonList(DEFAULT);

assertThat(get(list, 1)).isNull();}

@Testpublic void get_whenIndexTooSmall_returnNull() {

List<String> list = Collections.singletonList(DEFAULT);

assertThat(get(list, -1)).isNull();}

Simple to understand?

Arrange Act Assert

Test setup

@Testpublic void test() {

List<Language> list = Arrays.asList(GERMAN, ENGLISH);Mockito.when(mDataModel.getSupportedLanguages())

.thenReturn(list);Mockito.when(mDataModel.getGreetingByLanguageCode(LanguageCode.EN))

.thenReturn("Hi!");

// The rest of the test}

Arrange builder

class ArrangeBuilder {

ArrangeBuilder withLanguages(Language... languages) {Mockito.when(mDataModel.getSupportedLanguages())

.thenReturn(Arrays.asList(languages));return this;

}

ArrangeBuilder withGreetings(LanguageCode code, String greeting) {Mockito.when(mDataModel.getGreetingByLanguageCode(code))

.thenReturn(greeting);return this;

}}

@Testpublic void test() {

List<Language> list = Arrays.asList(GERMAN, ENGLISH);Mockito.when(mDataModel.getSupportedLanguages())

.thenReturn(list);Mockito.when(mDataModel.getGreetingByLanguageCode(LanguageCode.EN))

.thenReturn("Hi!");

// The rest of the test}

@Testpublic void test() {

new ArrangeBuilder().withLanguages(GERMAN, ENGLISH).withGreetings(LanguageCode.EN, "Hi!");

// The rest of the test}

Arrange builder

Simple to write

Is it all?

Do I have enough tests?

static boolean isEven(int number) {return number % 2 == 0;

}

static boolean isEven(int number) {return number % 2 == 0 ? true : false;

}

What’s the code coverage?

@Testpublic void isTwoEven() {

assertThat(isEven(2)).isTrue();

}

static boolean isEven(int number) {if ( number % 2 == 0 ) {

return true;} else {

return false;}

}

What’s the code coverage?

Observable<Boolean> isEven(int number) {return Observable.just(number)

.map(num -> num % 2 == 0);}

@Testpublic void isTwoEven() {

TestSubscriber<Boolean> ts = new TestSubscriber<>();

isEven(2).subscribe(ts);

ts.assertValue(true);}

@Testpublic void isTwoEven() {

TestSubscriber<Boolean> ts = new TestSubscriber<>();

isEven(2).subscribe(ts);}

Do I have too many tests?

Do I have too much code?

public class Translation {

public final String mText;

public Translation(String text) {mText = text;

}

public String text() {return mText;

}} @AutoValue

public abstract class Translation {

public abstract String text();

public static Translation create(String text) {return new AutoValue_Translation(text);

}}

.public class Translation {

private final String mText;

public Translation(String text) {mText = text;

}

public String text() {return mText;

}

@Overridepublic int hashCode() {

return mText != null ? mText.hashCode() : 0;}

@Overridepublic boolean equals(Object o) {

if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;

Translation that = (Translation) o;

return mText != null ? mText.equals(that.mText) : that.mText == null;

}}

.@Testpublic void valueEquality() {

String value = "text";Translation first = Translation.create(value);Translation second = Translation.create(value);

assertThat(first).isEqualTo(second);}

@AutoValuepublic abstract class Translation {

public abstract String text();

public static Translation create(String text) {return new AutoValue_Translation(text);

}

@Overridepublic int hashCode() {

// ...}

@Overridepublic boolean equals(Object o) {

// ...}

}

What is this code here?

Observable<String> getCurrentLanguage() {return getSystemLanguage()

.skip(1)

.first();}

Observable<String> getCurrentLanguage() {return getSystemLanguage()

// .skip(1).first();

}

Test Driven Development

Less Code Less Tests Peace of mind

Be playful Don’t be dogmatic

Find a test mentor

“99 little bugs in the code

99 little bugs in the code

Take one down, patch I around

117 little bugs in the code”

“Stop breaking things!”Tracy Rolling

Thank you!

tpolansk

Recommended