Add a tutorial example for new generated tests. (#207)
diff --git a/docs/tutorial.md b/docs/tutorial.md
index 2c64dae..17ea199 100644
--- a/docs/tutorial.md
+++ b/docs/tutorial.md
@@ -294,3 +294,81 @@
To learn more about Mobly Snippet Lib, including features like Espresso support
and asynchronous calls, see the [snippet lib examples]
(https://github.com/google/mobly-snippet-lib/tree/master/examples).
+
+
+# Example 6: Generated Tests
+
+A common use case in writing tests is to execute the same test logic multiple
+times, each time with a different set of parameters. Instead of duplicating the
+same test case with minor tweaks, you could use the **Generated tests** in
+Mobly.
+
+Mobly could generate test cases for you based on a list of parameters and a
+function that contains the test logic. Each generated test case is equivalent
+to an actual test case written in the class in terms of execution, procedure
+functions (setup/teardown/on_fail), and result collection. You could also
+select generated test cases via the `--test_case` cli arg as well.
+
+
+Here's an example of generated tests in action. We will reuse the "Example 1:
+Hello World!". Instead of making one toast of "Hello World", we will generate
+several test cases and toast a different message in each one of them.
+
+You could reuse the config file from Example 1.
+
+The test class would look like:
+
+
+**many_greetings_test.py**
+
+```python
+from mobly import base_test
+from mobly import test_runner
+from mobly.controllers import android_device
+
+
+class ManyGreetingsTest(base_test.BaseTestClass):
+
+ # When a test run starts, Mobly calls this function to figure out what
+ # tests need to be generated. So you need to specify what tests to generate
+ # in this function.
+ def setup_generated_tests(self):
+ messages = [('Hello', 'World'), ('Aloha', 'Obama'),
+ ('konichiwa', 'Satoshi')]
+ # Call `generate_tests` function to specify the tests to generate. This
+ # function can only be called within `setup_generated_tests`. You could
+ # call this function multiple times to generate multiple groups of
+ # tests.
+ self.generate_tests(
+ # Specify the function that has the common logic shared by these
+ # generated tests.
+ test_logic=self.make_toast_logic,
+ # Specify a function that creates the name of each test.
+ name_func=self.make_toast_name_function,
+ # A list of tuples, where each tuple is a set of arguments to be
+ # passed to the test logic and name function.
+ arg_sets=messages)
+
+ def setup_class(self):
+ self.ads = self.register_controller(android_device)
+ self.dut = self.ads[0]
+ self.dut.load_snippet(
+ 'mbs', 'com.google.android.mobly.snippet.bundled')
+
+ # The common logic shared by a group of generated tests.
+ def make_toast_logic(self, greeting, name):
+ self.dut.mbs.makeToast('%s, %s!' % (greeting, name))
+
+ # The function that generates the names of each test case based on each
+ # argument set. The name function should have the same signature as the
+ # actual test logic function.
+ def make_toast_name_function(self, greeting, name):
+ return 'test_greeting_say_%s_to_%s' % (greeting, name)
+
+
+if __name__ == '__main__':
+ test_runner.main()
+```
+
+Three test cases will be executed even though we did not "physically" define
+any "test_xx" function in the test class.