Sök…


Anmärkningar

Espresso

Espresso cheat sheet hjälper dig att skriva dina tester och vad du vill testa:

https://google.github.io/android-testing-support-library/docs/espresso/cheatsheet/

Den officiella dokumentationen är alltid en bra plats för referens:

https://google.github.io/android-testing-support-library/docs/espresso/index.html

Avancerade förslag på espressomaterial från Google: https://www.youtube.com/watch?v=isihPOY2vS4

Felsökning

  • När du försöker bläddra måste du först stänga tangentbordet:

Se upp: att inte använda "Espresso" -versionen kommer inte att göra någonting när den används utanför en ViewAction. Det kanske inte är uppenbart om du har en import till ViewAction-versionen eftersom de har exakt samma metodnamn.

ViewActions.closeSoftKeyboard;
Espresso.closeSoftKeyboard();
  • När du kör tester tillsammans i en svit snarare än individuellt, ska du vara medveten om att aktiviteten från det föregående testet fortfarande kan köras. Lita inte på att det tidigare testets onDestroy () kallas innan de aktuella testerna onResume (). Det visar sig att detta faktiskt är ett fel : http://b.android.com/201513

Ställ in Espresso

build.gradle till nästa beroenden i build.gradle filen i din Android-appmodul:

dependencies {   
    // Android JUnit Runner     
    androidTestCompile 'com.android.support.test:runner:0.5'
    // JUnit4 Rules
    androidTestCompile 'com.android.support.test:rules:0.5'
    // Espresso core
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
    // Espresso-contrib for DatePicker, RecyclerView, Drawer actions, Accessibility checks, CountingIdlingResource
    androidTestCompile 'com.android.support.test.espresso:espresso-contrib:2.2.2'
    //UI Automator tests
    androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.2.2'
}

Ange AndroidJUnitRunner för testInstrumentationRunner parametern i build.gradle filen.

android {

  defaultConfig {
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
  }

}

Lägg till detta beroende för att tillhandahålla avsiktligt håna stöd

androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2.2'

Och lägg till den här för support för webbvisningstest

// Espresso-web for WebView support
androidTestCompile 'com.android.support.test.espresso:espresso-web:2.2.2'

Skapa Espresso Test Class

Placera nästa java-klass i src / androidTest / java och kör den.

public class UITest {

  @Test public void Simple_Test() {
    onView(withId(R.id.my_view))         // withId(R.id.my_view) is a ViewMatcher
        .perform(click())                // click() is a ViewAction
        .check(matches(isDisplayed()));  // matches(isDisplayed()) is a ViewAssertion
  }

}

Öppna Stäng DrawerLayout

public final class DrawerLayoutTest  {

  @Test public void Open_Close_Drawer_Layout() {
    onView(withId(R.id.drawer_layout)).perform(actionOpenDrawer());
    onView(withId(R.id.drawer_layout)).perform(actionCloseDrawer());
  }

  public static ViewAction actionOpenDrawer() {
    return new ViewAction() {
      @Override public Matcher<View> getConstraints() {
        return isAssignableFrom(DrawerLayout.class);
      }

      @Override public String getDescription() {
        return "open drawer";
      }

      @Override public void perform(UiController uiController, View view) {
        ((DrawerLayout) view).openDrawer(GravityCompat.START);
      }
    };
  }

  public static ViewAction actionCloseDrawer() {
    return new ViewAction() {
      @Override public Matcher<View> getConstraints() {
        return isAssignableFrom(DrawerLayout.class);
      }

      @Override public String getDescription() {
        return "close drawer";
      }

      @Override public void perform(UiController uiController, View view) {
        ((DrawerLayout) view).closeDrawer(GravityCompat.START);
      }
    };
  }
  
}

Espressos enkla UI-test

UI-testverktyg

Två huvudverktyg som idag mest används för UI-test är Appium och Espresso.

Appium Espresso
blackbox-test vit / grå box testning
vad du ser är vad du kan testa kan ändra appens inre funktioner och förbereda den för testning, t.ex. spara data i databasen eller delade föredrag innan testet körs
används mest för att integrera tester från slutet till slut och hela användarflöden testa funktionaliteten på en skärm och / eller flöde
kan abstraheras så testskrivna kan köras på iOS och Android Endast Android
väl stött väl stött
stöder parallella tester på flera enheter med selenät Parallelltestning är inte uteslutet, plugins som Spoon finns förrän sant Google-support kommer ut

Hur man lägger till espresso i projektet

dependencies {
  // Set this dependency so you can use Android JUnit Runner
  androidTestCompile 'com.android.support.test:runner:0.5'
  // Set this dependency to use JUnit 4 rules
  androidTestCompile 'com.android.support.test:rules:0.5'
  // Set this dependency to build and run Espresso tests
  androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
  // Set this dependency to build and run UI Automator tests
  androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.2.2'
}

OBS ! Om du använder senaste supportbibliotek, anteckningar etc. måste du utesluta de äldre versionerna från espresso för att undvika kollisioner:

    // there is a conflict with the test support library (see http://stackoverflow.com/questions/29857695)
    // so for now re exclude the support-annotations dependency from here to avoid clashes
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2') {
        exclude group: 'com.android.support', module: 'support-annotations'
        exclude module: 'support-annotations'
        exclude module: 'recyclerview-v7'
        exclude module: 'support-v4'
        exclude module: 'support-v7'
    }
    // exclude a couple of more modules here because of <http://stackoverflow.com/questions/29216327> and
    // more specifically of <https://code.google.com/p/android-test-kit/issues/detail?id=139>
    // otherwise you'll receive weird crashes on devices and dex exceptions on emulators
    // Espresso-contrib for DatePicker, RecyclerView, Drawer actions, Accessibility checks, CountingIdlingResource
    androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.2.2') {
        exclude group: 'com.android.support', module: 'support-annotations'
        exclude group: 'com.android.support', module: 'design'
        exclude module: 'support-annotations'
        exclude module: 'recyclerview-v7'
        exclude module: 'support-v4'
        exclude module: 'support-v7'
    }
    //excluded specific packages due to https://code.google.com/p/android/issues/detail?id=183454
    androidTestCompile('com.android.support.test.espresso:espresso-intents:2.2.2') {
        exclude group: 'com.android.support', module: 'support-annotations'
        exclude module: 'support-annotations'
        exclude module: 'recyclerview-v7'
        exclude module: 'support-v4'
        exclude module: 'support-v7'
    }

    androidTestCompile('com.android.support.test.espresso:espresso-web:2.2.2') {
        exclude group: 'com.android.support', module: 'support-annotations'
        exclude module: 'support-annotations'
        exclude module: 'recyclerview-v7'
        exclude module: 'support-v4'
        exclude module: 'support-v7'
    }

    androidTestCompile('com.android.support.test:runner:0.5') {
        exclude group: 'com.android.support', module: 'support-annotations'
        exclude module: 'support-annotations'
        exclude module: 'recyclerview-v7'
        exclude module: 'support-v4'
        exclude module: 'support-v7'
    }
    androidTestCompile('com.android.support.test:rules:0.5') {
        exclude group: 'com.android.support', module: 'support-annotations'
        exclude module: 'support-annotations'
        exclude module: 'recyclerview-v7'
        exclude module: 'support-v4'
        exclude module: 'support-v7'
    }

Annat än denna import är det nödvändigt att lägga till Android instrumentation testrunner för att build.gradle android.defaultConfig:

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

Enhetsinställning

För icke-flagnigt test rekommenderas att du ställer in följande inställningar på dina enheter:

  • Utvecklaralternativ / Inaktivera animationer - minskar testens fläcklighet
  • Utvecklaralternativ / Håll dig vaken - om du har dedikerade enheter för test är detta användbart
  • Utvecklaralternativ / Loggerbuffertstorlekar - ställ in på högre antal om du kör mycket stora testsviter på din telefon
  • Tillgänglighet / Touch & Hold-fördröjning - länge för att undvika problem med att trycka på espresso

Ganska inställning från den verkliga världen ha? Tja nu när det är ur vägen låter oss ta en titt på hur man ställer in ett litet test

Skriva testet

Låt oss anta att vi har följande skärm: Liten skärm för espressotest Skärmen innehåller:

  • textinmatningsfält - R.id.textEntry
  • -knappen som visar snackbar med typad text när du klickar på - R.id.shownSnackbarBtn
  • snackbar som ska innehålla användartypad text - android.support.design.R.id.snackbar_text

Låt oss nu skapa en klass som testar vårt flöde:

/**
* Testing of the snackbar activity.
**/
@RunWith(AndroidJUnit4.class)
@LargeTest
public class SnackbarActivityTest{
    //espresso rule which tells which activity to start
    @Rule
    public final ActivityTestRule<SnackbarActivity> mActivityRule = 
        new ActivityTestRule<>(SnackbarActivity.class, true, false);


    @Override
    public void tearDown() throws Exception {
        super.tearDown();
        //just an example how tear down should cleanup after itself
        mDatabase.clear();
        mSharedPrefs.clear();
    }
    
    @Override
    public void setUp() throws Exception {
        super.setUp();
        //setting up your application, for example if you need to have a user in shared
        //preferences to stay logged in you can do that for all tests in your setup
        User mUser = new User();
        mUser.setToken("randomToken");
    }
    
    /**
    *Test methods should always start with "testXYZ" and it is a good idea to 
    *name them after the intent what you want to test
    **/
    @Test
    public void testSnackbarIsShown() {
        //start our activity
        mActivityRule.launchActivity(null);
        //check is our text entry displayed and enter some text to it
        String textToType="new snackbar text";
        onView(withId(R.id.textEntry)).check(matches(isDisplayed()));
        onView(withId(R.id.textEntry)).perform(typeText(textToType));
        //click the button to show the snackbar
        onView(withId(R.id.shownSnackbarBtn)).perform(click());
        //assert that a view with snackbar_id with text which we typed and is displayed
        onView(allOf(withId(android.support.design.R.id.snackbar_text), 
        withText(textToType))) .check(matches(isDisplayed()));
    }
}

När du märkte att det finns 3-4 saker du kanske märker kommer ofta:

onView (withXYZ) <- viewMatchers med dem kan du hitta element på skärmen

utför (klicka ()) <- viewActions, du kan utföra åtgärder på element du tidigare hittat

check (matchningar (isDisplayed ())) <- viewAssertions, checkar du vill göra på skärmar som du hittade tidigare

Alla dessa och många andra kan hittas här: https://google.github.io/android-testing-support-library/docs/espresso/cheatsheet/index.html

Det är det, nu kan du köra testet antingen med högerklicka på klassens namn / test och välja Kör test eller med kommando:

./gradlew connectedFLAVORNAMEAndroidTest

Upp navigering

@Test
public void testUpNavigation() {
    intending(hasComponent(ParentActivity.class.getName())).respondWith(new Instrumentation.ActivityResult(0, null));

    onView(withContentDescription("Navigate up")).perform(click());

    intended(hasComponent(ParentActivity.class.getName()));
}

Observera att detta är en lösning och kommer att kollidera med andra vyer som har samma innehållsbeskrivning.

Utför en åtgärd på en vy

Det är möjligt att utföra ViewActions på en vy med perform-metoden.
ViewActions tillhandahåller hjälpmetoder för de vanligaste åtgärderna, som:

ViewActions.click()
ViewActions.typeText()
ViewActions.clearText()

För att till exempel klicka på vyn:

onView(...).perform(click());
onView(withId(R.id.button_simple)).perform(click());

Du kan utföra mer än en åtgärd med ett samtal:

onView(...).perform(typeText("Hello"), click());

Om vyn du arbetar med är belägen i en ScrollView (vertikal eller horisontell), överväg föregående åtgärder som kräver att vyn ska visas (som click() och typeText() ) med scrollTo() . Detta säkerställer att vyn visas innan du fortsätter till den andra åtgärden:

onView(...).perform(scrollTo(), click());

Hitta en vy med onView

Med ViewMatchers du hitta vy i den aktuella visningshierarkin.

För att hitta en vy använder onView() metoden onView() med en visningsmatchare som väljer rätt vy. onView() returnerar ett objekt av typen ViewInteraction .

Till exempel är att hitta en vy från dess R.id lika enkelt som:

onView(withId(R.id.my_view))

Hitta en vy med en text:

onView(withText("Hello World"))

Espresso anpassade matchare

Espresso har som standard många matchare som hjälper dig att hitta vyer som du behöver göra några kontroller eller interaktioner med dem.

De viktigaste finns i följande fuskark:

https://google.github.io/android-testing-support-library/docs/espresso/cheatsheet/

Några exempel på matchare är:

  • withId (R.id.ID_of_object_you_are_looking_for);
  • withText ("Viss text du förväntar dig att objekt ska ha");
  • isDisplayed () <- kontroll är vyn synlig
  • doesNotExist () <- kontrollera att vyn inte finns

Alla dessa är mycket användbara för vardagligt bruk, men om du har mer komplexa vyer kan dina anpassade matchare göra testerna mer läsbara och du kan återanvända dem på olika platser.

Det finns två vanligaste matchartyper som du kan utöka: TypeSafeMatcher BoundedMatcher

Implementering av TypeSafeMatcher kräver att du kontrollerar förekomsten av vyn du hävdar mot, om det är rätt typ matchar du några av dess egenskaper mot ett värde som du angav till en matcher.

Skriv till exempel säker matcher som validerar en bildvy med korrekt dragbarhet:

public class DrawableMatcher extends TypeSafeMatcher<View> {

    private @DrawableRes final int expectedId;
    String resourceName;
    
    public DrawableMatcher(@DrawableRes int expectedId) {
        super(View.class);
        this.expectedId = expectedId;
    }

    @Override
    protected boolean matchesSafely(View target) {
        //Type check we need to do in TypeSafeMatcher
        if (!(target instanceof ImageView)) {
            return false;
        }
        //We fetch the image view from the focused view
        ImageView imageView = (ImageView) target;
        if (expectedId < 0) {
            return imageView.getDrawable() == null;
        }
        //We get the drawable from the resources that we are going to compare with image view source
        Resources resources = target.getContext().getResources();
        Drawable expectedDrawable = resources.getDrawable(expectedId);
        resourceName = resources.getResourceEntryName(expectedId);

        if (expectedDrawable == null) {
            return false;
        }
        //comparing the bitmaps should give results of the matcher if they are equal
        Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
        Bitmap otherBitmap = ((BitmapDrawable) expectedDrawable).getBitmap();
        return bitmap.sameAs(otherBitmap);
    }


    @Override
    public void describeTo(Description description) {
        description.appendText("with drawable from resource id: ");
        description.appendValue(expectedId);
        if (resourceName != null) {
            description.appendText("[");
            description.appendText(resourceName);
            description.appendText("]");
        }
    }
}

Användningen av matchen kan lindas så här:

  public static Matcher<View> withDrawable(final int resourceId) {
    return new DrawableMatcher(resourceId);
}

 onView(withDrawable(R.drawable.someDrawable)).check(matches(isDisplayed()));

Begränsade matchare är liknande du behöver inte göra typkontrollen, eftersom det görs automatiskt för dig:

 /**
 * Matches a {@link TextInputFormView}'s input hint with the given resource ID
 *
 * @param stringId
 * @return
 */
public static Matcher<View> withTextInputHint(@StringRes final int stringId) {
    return new BoundedMatcher<View, TextInputFormView>(TextInputFormView.class) {
        private String mResourceName = null;

        @Override
        public void describeTo(final Description description) {
            //fill these out properly so your logging and error reporting is more clear
            description.appendText("with TextInputFormView that has hint ");
            description.appendValue(stringId);
            if (null != mResourceName) {
                description.appendText("[");
                description.appendText(mResourceName);
                description.appendText("]");
            }
        }

        @Override
        public boolean matchesSafely(final TextInputFormView view) {
            if (null == mResourceName) {
                try {
                    mResourceName = view.getResources().getResourceEntryName(stringId);
                } catch (Resources.NotFoundException e) {
                    throw new IllegalStateException("could not find string with ID " + stringId, e);
                }
            }
            return view.getResources().getString(stringId).equals(view.getHint());
        }
    };
}

Mer om matcher kan läsas upp på:

http://hamcrest.org/

https://developer.android.com/reference/android/support/test/espresso/matcher/ViewMatchers.html

Övergripande Espresso

Inställning Espresso:

androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
androidTestCompile 'com.android.support.test:runner:0.5'

ViewMatchers - En samling av objekt som implementerar Matcher<? super View> gränssnitt. Du kan skicka en eller flera av dessa till onView metoden för att hitta en vy i den aktuella visningshierarkin.

ViewActions - En samling ViewActions som kan skickas till ViewInteraction.perform() (till exempel click() ).

ViewAssertions - En samling ViewAssertions som kan skickas ViewInteraction.check() metoden ViewInteraction.check() . För det mesta använder du matchningspåståendet, som använder en View-matcher för att hävda tillståndet för den valda vyn.


Espresso fuska blad från Google

ange bildbeskrivning här


Ange text i EditText

onView(withId(R.id.edt_name)).perform(typeText("XYZ"));
        closeSoftKeyboard();

Utför Klicka på Visa

 onView(withId(R.id.btn_id)).perform(click());

Kontrollera vy visas

 onView(withId(R.id.edt_pan_number)).check(ViewAssertions.matches((isDisplayed())));

Gruppera en samling testklasser i en testsvit

Du kan organisera utförandet av dina instrumenterade enhetstester som definierar en svit .

/**
 * Runs all unit tests.
 */
@RunWith(Suite.class)
@Suite.SuiteClasses({MyTest1.class , 
         MyTest2.class, 
         MyTest3.class})
public class AndroidTestSuite {}

Sedan i AndroidStudio kan du köra med gradle eller ställa in en ny konfiguration som:

ange bildbeskrivning här

Testsviter kan häckas.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow