Tomasz Polanski - Automated mobile testing 2016 - Testing: why, when, how
-
Upload
tomasz-polanski -
Category
Mobile
-
view
653 -
download
3
Transcript of Tomasz Polanski - Automated mobile testing 2016 - Testing: why, when, how
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