Auto-tools/Projects/Robocop/WritingTests: Difference between revisions

 
(9 intermediate revisions by 3 users not shown)
Line 1: Line 1:
= What's this? =
Robotium is a test framework created to make it easy to write powerful and robust automatic black-box test cases for Android applications. Robocop provides a wrapper around Robotium making it even easier to write and execute UI tests for native Fennec.
 
New tests should probably use the UITest base class - see the documentation at [[Mobile/Fennec/Android/UITest|UITest]]. Most of the information below will also be relevant to users of UITest (though the information should probably be curated).


Robotium is a test framework created to make it easy to write powerful and robust automatic black-box test cases for Android applications. Robocop provides a wrapper around Robotium making it even easier to write and execute UI tests for native Fennec.
== Creating a new test ==
These tests will extend BaseTest.


= Creating a new test =
The best way to create a new Robocop test is to copy and modify an existing one -- see mobile/android/base/tests.


The best way to create a new Robocop test is to copy and modify an existing one -- see mobile/android/base/tests.  
(We are currently upgrading our tests from Robotium 3.6 to 4.2 [{{bug|912590}}], so the APIs used in the tests may be out of date. It might be helpful to take a look at the [http://code.google.com/p/robotium/wiki/Changelog Robotium changelog] to see some of the new API methods.)


Create a new file in the test directory named test[YourFeature].java.in.
Create a new file in the test directory named test[YourFeature].java.in.
Line 20: Line 23:
</pre>
</pre>


For convenience, you can also extend one of the provided abstract classes, like BaseTest. This derives from ActivityInstrumentationTestCase2 but also provides a bunch of boilerplate and utility functions.
For convenience, you can also extend one of the provided abstract classes, like BaseTest, PixelTest, or AboutHomeTest. BaseTest derives from ActivityInstrumentationTestCase2 but also provides a bunch of boilerplate and utility functions.
<pre>
<pre>
public class testMyFeature extends BaseTest
public class testMyFeature extends BaseTest
Line 32: Line 35:
</pre>
</pre>


If you extend BaseTest, the setUp() and tearDown() are provided for you, but you can still override them and do additional setup/teardown if needed; just make sure you call super.setUp() and super.tearDown() in your overiddes as necessary.
If you extend one of the provided abstract classes, the setUp() and tearDown() are provided for you, but you can still override them and do additional setup/teardown if needed; just make sure you call super.setUp() and super.tearDown() in your overiddes as necessary.


Finally, add your new test file to the test manifest: mobile/android/base/tests/robocop.ini:
Finally, add your new test file to the test manifest: mobile/android/base/tests/robocop.ini:
Line 44: Line 47:
</pre>
</pre>


== Creating a new Content Provider test ==
=== Creating a new Content Provider test ===


We have infrastructure for testing content providers in an isolated environment. This means that we ensure that any updates to the databases behind content providers will not affect or be affected by Firefox.
We have infrastructure for testing content providers in an isolated environment. This means that we ensure that any updates to the databases behind content providers will not affect or be affected by Firefox.
Line 65: Line 68:
After this is called, ''mProvider'' will point to an isolated instance of your content provider and you can make insert/query/update/delete calls on it as expected. For more details and sample code on how to implement Content Provider tests, see testBrowserProvider.java.in.
After this is called, ''mProvider'' will point to an isolated instance of your content provider and you can make insert/query/update/delete calls on it as expected. For more details and sample code on how to implement Content Provider tests, see testBrowserProvider.java.in.


= APIs  =
== APIs  ==
Robotium itself provides a rich API through the Solo class - javadocs for Solo are available at [1].
Robotium itself provides a rich API through the Solo class - [http://robotium.googlecode.com/svn/doc/index.html javadocs] [1] for Solo are available.


"Robocop" provides an additional API to make common tasks easier. The main interfaces are Actions, Elements, and Driver.  
"Robocop" provides an additional API to make common tasks easier. The main interfaces are Actions, Elements, and Driver.  
Line 118: Line 121:
Finally, an evolving set of test base classes - BaseTest, PixelTest, etc - can be leveraged for some types of tests.
Finally, an evolving set of test base classes - BaseTest, PixelTest, etc - can be leveraged for some types of tests.


= Tips =
== Tips ==
=== Event timing ===
=== Event timing ===
A recurring issue when writing UI tests is the timing of events. To enter a URL, you need to click on the awesome bar and then send the key events for the text. If you click() and then immediately sendKeys(), the text probably won't get to the awesome bar. If you sleep() briefly before and after clicking, the task will probably succeed...but how long are those sleep() calls? Will the test still work on other devices, reliably? Avoid the temptation to scatter sleep() throughout your test. Whenever possible, wait for events or other feedback to verify the UI is in the required state before proceeding. For example, many tests will want to wait for startup before starting the test: driver.waitForGeckoEvent("Gecko:Ready").
A recurring issue when writing UI tests is the timing of events. To enter a URL, you need to click on the awesome bar and then send the key events for the text. If you click() and then immediately sendKeys(), the text probably won't get to the awesome bar. If you sleep() briefly before and after clicking, the task will probably succeed...but how long are those sleep() calls? Will the test still work on other devices, reliably? Avoid the temptation to scatter sleep() throughout your test. Whenever possible, wait for events or other feedback to verify the UI is in the required state before proceeding. For example, many tests will want to wait for startup before starting the test: driver.waitForGeckoEvent("Gecko:Ready").
=== Use waitForTest instead of sleep() ===
=== Use waitForCondition instead of sleep() ===
If you cannot find an event to wait for and you are still tempted to sleep(), consider using waitForTest() instead. waitForTest() gives you a simple way to poll for a condition for a specified maximum amount of time, with short sleep()'s in between polls. This provides the advantage that the test can proceed as soon as the condition is met, reducing test time.
If you cannot find an event to wait for and you are still tempted to sleep(), consider using waitForCondition() instead. waitForConditon() gives you a simple way to poll for a condition for a specified maximum amount of time. This provides the advantage that the test can proceed as soon as the condition is met, reducing test time.
 
=== Activities ===
Most tests will access UI views using FennecNativeDriver.findElement, which takes an activity as an argument. Some tests will only interact with one activity, but others may need to use multiple activities. For instance, when there are multiple tabs, there may be multiple awesome bar activities; use the wrong activity and you'll be accessing an unexpected element / view! See testNewTab for an example with multiple activities.


=== Logging ===
=== Logging ===
Robocop logs to both logcat and a file log via Assert.dumpLog (or FennecNativeDriver.log). Test code can use these, or log as a side-effect of Assert.is, Assert.ok, etc. Do not call android.util.Log.i/w/e/etc directly.
Robocop logs to both logcat and a file log via Assert.dumpLog (or FennecNativeDriver.log). Test code can use these, or log as a side-effect of Assert.is, Assert.ok, etc. Do not call android.util.Log.i/w/e/etc directly.
'''Robocat''' is a command line tool to transform the JSON robocop dumps into logcat into a human-readable format: https://github.com/pocmo/Robocat


=== Indirect Database Operations ===
=== Indirect Database Operations ===
Line 178: Line 180:
Note that the test is therefore dependent on screen size and orientation, as well as Robotium scrolling behavior.
Note that the test is therefore dependent on screen size and orientation, as well as Robotium scrolling behavior.


= More Information =
== Useful links ==
 
#[[Mobile/Fennec/Android/UITest|Our UITest base class documentation]]
[1] http://code.google.com/p/robotium/
#Latest Robotium javadocs: http://robotium.googlecode.com/svn/doc/index.html
 
#Robotium project page: http://code.google.com/p/robotium/
[2] https://github.com/jayway/robotium/tree/master/robotium-solo/src/main/java/com/jayway/android/robotium/solo
#Robotium changelog for versions: http://code.google.com/p/robotium/wiki/Changelog
 
#Robotium GitHub repo: https://github.com/jayway/robotium/tree/master/robotium-solo/src/main/java/com/jayway/android/robotium/solo
[3] http://robotium.googlecode.com/svn/doc/index.html
118

edits