ViewSelector makes unit testing Android UIs easier with CSS-style selectors. It can express complex assertions about the UI with little code and without manually fussing around with views.
// These traditional assertions ... ListView view = (ListView) activity.findViewById(R.id.groceries); assertEquals(2, view.getChildCount()); assertEquals("milk", ((TextView) view.getChildAt(0)).getText()); assertEquals("cereal", ((TextView) view.getChildAt(1)).getText()); // ... can be expressed as: assertThat(selection("ListView#groceries TextView", activity)) .attribute("text").containsExactly("milk", "cereal");
It's compatible with both Android tests and Robolectric (1.2 & 2.x) tests. It was inspired by the very handy assert_select in Rails and Android's own UiSelector.
Currently under development.
Releases are available from Maven Central. Add this dependency to your pom.xml:
<dependency> <groupId>com.nikhaldimann</groupId> <artifactId>android-view-selector</artifactId> <version>1.0-beta-1</version> <scope>test</scope> </dependency>
If contrary to all that is good and reasonable you're not using Maven, you can download the lastest JAR with dependencies (android-view-selector-RELEASE-jar-with-dependencies.jar) from Sonatype.
import static com.nikhaldimann.viewselector.ViewSelectorAssertions.assertThat; import static com.nikhaldimann.viewselector.ViewSelectorAssertions.selection; ... // Assert that rootView has 5 descendant views that are TextViews assertThat(selection("TextView", activity)).hasSize(5); // Assert that there are 4 TextViews that are descendants of the view with id // "container" and all are visible with a width of 100 pixels assertThat(selection("#container ImageView", activity)) .hasSize(4) .isVisible() .hasWidth(100); // Assert that the TextViews which are direct children of a LinearLayout with // id "groceries" have text "milk", "cereal" (in that order) assertThat(selection("LinearLayout#groceries > TextView", activity)) .attribute("text").containsExactly("milk", "cereal");
The second argument to
selection() can be an activity or any
If you're already statically importing a different FEST-style
assertThat method, you can
statically import ViewSelector's
assertThatSelection to avoid conflicts:
import static com.nikhaldimann.viewselector.ViewSelectorAssertions.assertThatSelection; ... // Equivalent to the first assertion above assertThatSelection("TextView", activity).hasSize(5);
You may also consult these two full examples of tests using ViewSelector:
A very simple unit test based on
ActivityUnitTestCase, demonstrating how to test fairly static UIs.
A functional test based on
ActivityInstrumentationTestCase2, demonstrating how to test more dynamic UIs.
Selector semantics mirror those of CSS very closely. These selectors are supported so far:
||... all views|
||... views of type
||... views with id
||... views of type
Notes on Attribute Matching
The attribute selectors are implemented by calling corresponding getters on the views.
For example, the selector
getTag() on views to find out whether that
attribute exists. Naming conventions for boolean attributes are respected, e.g.,
[isShown] will call
getIsShown()) on views.
Selectors with attribute matching (e.g.,
[tag=foo]) support some primitive
value types other than strings in a natural way:
- The values
falsewhen used with a boolean attribute will be interpreted as booleans rather than strings. Example:
- Integer values used with integer attributes will be interpreted as integers.
However, due to limitations in the CSS parsing library used the numbers
have to be enclosed in quotes. Example:
Note that attribute matching for some attributes might not behave as you expect if you're using Robolectric because of the shadowing techniques it uses.
Distributed under an MIT license.