Upload
roman-mazur
View
352
Download
1
Embed Size (px)
DESCRIPTION
Про інструменти TDD та автоматизацію тестів на Android.
Citation preview
TDD, ти де?
xor eax, eaxmov frametimer, eaxmov frameid, 1mov damage, ~99cmp frametimer, 7push 1
$ SET SOURCEFORMAT"FREE"IDENTIFICATION DIVISION.PROGRAM-ID. ShortestProgram.
PROCEDURE DIVISION.DisplayPrompt. DISPLAY "I did it". STOP RUN.
Колись програмістам набридло писати двійковий код...
Колись програмістам набридло самим збирати та розгортати свої творіння...
GNU Make
Якщо ви робите якусь річ втретє, ви вже мали її автоматизувати
А як щодо тестів?
Автоматизація тестів
Android SDK JUnit 3
protected void setUp() { super.setUp(); emailView = getActivity().findViewById(R.id.login_email);}
public void testLogin() { assertNotNull(emailView);}
Запускається на пристрої
Групи тестів
@SmallTestpublic void testFastAction() { }
@MediumTestpublic void testLongerScenario() { }
@LargeTestpublic void testFullUseCase() { }
Не все так просто
зробити щось в основному потоці
getInstrumentation().runOnMainSync(new Runnable() { @Override public void run() { emailView.setText("email"); }});
Не все так просто
дочекатися всіх операцій в основному потоці
getInstrumentation().waitForIdleSync();
@FlakyTest(tolerance = 3)
Android Test Kit
onView(withId(R.id.my_view)) .perform(click()) .check(matches(isDisplayed()));
Покращення (с)
Spoon.screenshot(activity, "initial_state");/* Normal test code... */Spoon.screenshot(activity, "after_login");
Додаємо знімки екрана
Spoon
Spoon
buildscript { repositories { mavenCentral() } dependencies { classpath 'com.stanfy.spoon:spoon-gradle-plugin:0.9.+' }}apply plugin: 'spoon'
Spoon Gradle Plugin
$ gradle spoon
dependencies { instrumentTest 'org.easytesting:fest-assert-core:2.0M10' instrumentTest 'com.squareup:fest-android:1.0.+'}
Fluent assertions
assertThat(person.getFriends()).isNotEmpty();assertThat(emailView).isVisible();assertThat(emailView).hasText(person.getEmail());
Це все не TDD...
це лише автоматизація (UI) тестів
Для запуску тестів потрібно
1. скомпілювати
2. перетворити в dex
3. упакувати
4. встановити на пристрій час
Для запуску тестів потрібно
1. скомпілювати
2. перетворити в dex
3. упакувати
4. встановити на пристрій
на JVM
Так можна будувати TDD
Однак на робочій машині з JVM немає Android Runtime
throw new RuntimeException("Stub!");
Robolectric@RunWith(RobolectricTestRunner.class)public class DbManagerTest {
private DbManager dbManager;
@Before public void initDbManager() { dbManager = new DbManager(Robolectric.application); }
@Test public void cleanupShouldNotRemoveUsedRecords() { ... }
}
Robolectric with Gradlebuildscript { repositories { mavenCentral() } dependencies { classpath 'com.squareup.gradle:gradle-android-test-plugin:0.9.+' }}apply plugin: 'android-test'
dependencies { testCompile 'junit:junit:4.11' testCompile 'org.robolectric:robolectric:2.3-SNAPSHOT'}
Robolectric with Gradle
dependencies { testCompile fileTree(dir: "$buildDir/exploded-bundles", include: "*/classes.jar") testCompile fileTree(dir: "$buildDir/exploded-bundles", include: "*/libs/*.jar")}
якщо компілятор скаже, що не може знайти щось із aar
RemoteApi api = mock(RemoteApi.class);when(api.get("param")).thenReturn("some value");// some logic...verify(api).get("param");
Robolectric - це не моки
Додамо Mockito
Таким є наш щоденний арсенал
Mattock
buildscript { repositories { mavenCentral() } dependencies { classpath 'com.stanfy.mattock:gradle-plugin:1.0' }}apply plugin: ‘mattock’
$ gradle androidTest
запуск JUnit 4 тестів на Android-пристроях
Тепер ніби все
Але є ще багато всякого
Robotium
І ще...
Heliumнам набридло робити одне й те саме…
service { name 'Twitter API' description 'Piece of Twitter API' version 1.1
location "https://api.twitter.com/${version}"
get "/users/show.json" spec { name 'Get user profile' parameters { user_id long optional screen_name 'string' optional include_entities boolean optional } response "UserProfile" }}