ANDROID TESTING L Grewe Testing and Software Development

  • Slides: 51
Download presentation
ANDROID – TESTING L. Grewe

ANDROID – TESTING L. Grewe

Testing and Software Development Testing an important “step” in SW development

Testing and Software Development Testing an important “step” in SW development

Testing Strategy in General Start with Unit Test and end with System Tests

Testing Strategy in General Start with Unit Test and end with System Tests

Another view of testing strategies For each “level” of design we have a corresponding

Another view of testing strategies For each “level” of design we have a corresponding “kind” of testing that can exercise/test the fulfillment of the design in the code

Some Terms Units/Modules showing connectivity C A Unit Testing: Testing a module by itself.

Some Terms Units/Modules showing connectivity C A Unit Testing: Testing a module by itself. Just test A alone or E along D Integration Testing: tests groups of modules that have passed unit testing. Test A, B then A, C and so on System Testing: Full integration testing, testing of complete system Acceptance Testing: B process of testing system in its real environment with real data E

What kind of testing are we covering? ? ? Unit Testing Which is good

What kind of testing are we covering? ? ? Unit Testing Which is good because that is most of the testing you may do (see recommendation 70%) and it is the first kind of testing to do

SETTING UP FOR UNIT TESTING With Android Studio

SETTING UP FOR UNIT TESTING With Android Studio

Setup Configurations STEP 1: Run->Edit Configurations STEP 2: Hit + in Config window and

Setup Configurations STEP 1: Run->Edit Configurations STEP 2: Hit + in Config window and add Android Tests

Setup continued All test methods MUST start with the “test-” prefix or Andr Studio

Setup continued All test methods MUST start with the “test-” prefix or Andr Studio will not detect them as tests and you will get all kin weird errors and nothing will work. Step 3: Now configure Testing configuration to point to the module of your app select“All in Module” and Android Studio will automatically find any test inside your whole Module! You can also get more specific and select “Class” or even “Method” option to narrow the scope of your testing down further.

Setup finished Step 4: after saving config in Step 3 you can see it

Setup finished Step 4: after saving config in Step 3 you can see it is an option for running (now we have the app itself and the testing classes) NEXT how do we make the testing code

When you create Project –you have testing directories (test android. Test) Look at this

When you create Project –you have testing directories (test android. Test) Look at this example for a simple Hello. App app Have android. Test and test

2 KINDS OF UNIT TESTSJVM RUN (PLAIN OLD JUNIT) ANDROID RUN (INSTRUMENTATION) JVM =

2 KINDS OF UNIT TESTSJVM RUN (PLAIN OLD JUNIT) ANDROID RUN (INSTRUMENTATION) JVM = java/test Android= android. Test/

2 kinds of Unit Testing in Android: android. Test/java & Tests Stop ---why 2

2 kinds of Unit Testing in Android: android. Test/java & Tests Stop ---why 2 test directories? ? ? android. Test/java: • Used for Android classes test/java : • Used for Plain Old Java classes –that have no Android code in them

To allow running Android unit tests on the JVM, the Android Gradle plug-in creates

To allow running Android unit tests on the JVM, the Android Gradle plug-in creates a special version of the android. jar (also known as the Android mockable jar ). test/java Tests Run on computer’s JVM • Use these tests to minimize execution time when your tests have no Android framework dependencies or when you can mock the Android framework dependencies

Called android. Test or instrumentation Testing – as run on “instrument” emulator or hardware

Called android. Test or instrumentation Testing – as run on “instrument” emulator or hardware device android. Test/java Tests Run on Android emulator/hardware device • Use these tests when writing integration and functional UI tests to automate user interaction, or when your tests have Android dependencies that mock objects cannot satisfy.

If classes do not call the Android API you can use the JUnit test

If classes do not call the Android API you can use the JUnit test framework without any restrictions. If you have dependencies to the Android API these dependencies in your code must be replaced for the unit tests via a mocking framework like Mockito. android. Test test = when not making calls to Android system need to test android. Test = when need calls to Android system or test? ? ?

An Example: android. Test or test? ? ? Assume a button in an Android

An Example: android. Test or test? ? ? Assume a button in an Android activity is used to start another activity. • • (test/java) test = would determine, if the corresponding intent was issued, not if the second activity was started (android. Test/java) test = would be able to see if intent was issued AND if second activity started

CREATING A TESTING CLASS Setting up in Android Studio

CREATING A TESTING CLASS Setting up in Android Studio

Steps to generate a Test Class Step 1: Open up the class you want

Steps to generate a Test Class Step 1: Open up the class you want to create a test class for Step 2: select name of class and hit “Cntrl-Shift-T” and a pop-up will ask you to make a new test class

Steps to generate a Test Class Step 3: change name (if desire) of test

Steps to generate a Test Class Step 3: change name (if desire) of test class, select methods you wish to create test cases for NOTE: there are different Testing Libraries the Android Studio will support and generate…we are using JUnit 4 Step 3 : ALSO choose the directory test OR android. Test Choose which directory test = runs on JVM android. Test =runs on android

Steps to generate a Test Class Step 4: you will see the new Test

Steps to generate a Test Class Step 4: you will see the new Test Class in the directory you specified We choose to put it in the android. Test –so will run on Android instead of local JVM

Steps to generate a Test Class Step 5: Your application’s Build Dependencies ( build.

Steps to generate a Test Class Step 5: Your application’s Build Dependencies ( build. gradle file) should include: setup the appropriate Gradle Dependencies in your project so it knows about (in our case Junit 4) the testing library you choose in step 3 IMPORTANT: depending on whether your test cases are in androit. Test/java or test/java you will only need the corresponding dependency line (android. Test. Compile or test. Compile) THIS for JVM test/java tests dependencies { // Required for local unit tests (JUnit 4 framework) test. Compile 'junit: 4. 12‘ // whatever else you have***** }

Steps to generate a Test Class Step 5: showing for Instrumentation test (android. Test/java):

Steps to generate a Test Class Step 5: showing for Instrumentation test (android. Test/java): IMPORTANT: This for android. Test/java tests dependencies { // Required for instrumented tests android. Test. Compile 'junit: 4. 12‘ android. Test. Compile 'com. android. support: support-annotations: 24. 0. 0' android. Test. Compile 'com. android. support. test: runner: 0. 5‘ android. Test. Compile 'com. android. support. test: rules: 0. 5' // Optional -- Hamcrest library android. Test. Compile 'org. hamcrest: hamcrest-library: 1. 3' // Optional -- UI testing with Espresso android. Test. Compile 'com. android. support. test. espresso: espresso-core: 2. 2. 2' // Optional -- UI testing with UI Automator android. Test. Compile 'com. android. support. test. uiautomator: uiautomator-v 18: 2. 1. 2' // whatever else you have***** }

SPECIAL NOTE: Steps to generate a Test Class Step 6: if you get an

SPECIAL NOTE: Steps to generate a Test Class Step 6: if you get an error about the project version and test version not matching ERROR looks like This: Error: Conflict with dependency SOLUTION: add 'com. android. support: support-annotations'. Resolved versions for app (24. 2. 1) and test app (24. 0. 0) differ. the following to See http: //g. co/androidstudio/app-test-app-conflict build gradle file details. android { // whatever else you have***** configurations. all { resolution. Strategy { force 'com. android. support: support-annotations: 23. 1. 1' } } }

SPECIAL NOTE: For android. Test/java tests you need to also add this Step 5

SPECIAL NOTE: For android. Test/java tests you need to also add this Step 5 (only if android. Test instrumentation test) : add the following to your application’s Build default. Config( build. gradle file) should include: default. Config { // whatever else you have***** test. Instrumentation. Runner "android. support. test. runner. Android. JUnit. Runner" }

JVM BASED UNIT TESTS--TEST/JAVA Unit testing on JVM

JVM BASED UNIT TESTS--TEST/JAVA Unit testing on JVM

First learn coding for JVM based Unit testing ---this is the test case that

First learn coding for JVM based Unit testing ---this is the test case that will appear in test/java

Writing Test classes - Based on JUnit use plain JUnit to test a class

Writing Test classes - Based on JUnit use plain JUnit to test a class that doesn't call the Android API, JUnit Test. Case class to do unit testing on a class that doesn't call Android APIs. Use Android's JUnit extensionsto test Android components. Android JUnit extensions provide component-specific test case classes. provide helper methods for creating mock objects and methods that help you control the lifecycle of a component.

Testing PLO (plain old java object) Plain Old Java Objects (i. e. independent of

Testing PLO (plain old java object) Plain Old Java Objects (i. e. independent of frameworks like Android or J 2 EE) Test using assert*** = assert. True, assert. Equals to see if value is true or equals some value. import com. android. lab 4. Joke; //this is the class we are testing import static org. junit. Assert. *; import org. junit. After; import org. junit. Before; import org. junit. Test; This is a class that can go in test/java directory and run on JVM public class Joke. Test extends Test. Case { @Test public void test. Joke() { Joke joke = new Joke(); assert. True("m_str. Joke should be initialized to "". ", joke. get. Joke(). equals("")); assert. True("m_str. Author. Name should be initialized to "". ", joke. get. Author(). equals("")); assert. Equals("m_n. Rating should be initialized to Joke. UNRATED. ", Joke. UNRATED, joke. get. Rating()); } }

Using Junit (in test/java) Test Number. Manimulation. Function Class: Number. Manipulation. Functions. Test TEST

Using Junit (in test/java) Test Number. Manimulation. Function Class: Number. Manipulation. Functions. Test TEST Class: package computervision. grewe. helloapp; import org. junit. Test; import static org. junit. Assert. *; /** * Various Silly static methods for doing number manipulations * Created by Lynne on 9/26/2016. */ public class Number. Manipulation. Functions { /** * silly calculate number on Mars as n^2 * @param n * @return */ public static int number. Mars(int n){ return n*n; } /** * silly calculate number in Ocean * @param n * @return */ public static float number. Ocean(int n){ return ((float) n) / 20. 0 f; } } /** * Created by Lynne on 9/26/2016. */ public class Number. Manipulation. Functions. Test { @Test public void test. Number. Mars() throws Exception { int value = 3; int expected = value*value; assert. Equals ("Conversion to Mars number failed", expected, Number. Manipulation. Functions. number. Mars (value)); } @Test public void test. Number. Ocean() throws Exception { int value = 3; int expected = value/20; assert. Equals ("Conversion to Ocean number failed", expected, Number. Manipulation. Functions. number. Ocean (value), 0. 000001); } }

Running previous Test Class Results As expected it passes Number. Manipulation. Functions. Test TEST

Running previous Test Class Results As expected it passes Number. Manipulation. Functions. Test TEST Class: package computervision. grewe. helloapp; import org. junit. Test; import static org. junit. Assert. *; public class Number. Manipulation. Functions. Test { @Test public void test. Number. Mars() throws Exception { int value = 3; int expected = value*value; assert. Equals ("Conversion to Mars number failed", expected, Number. Manipulation. Functions. number. Mars (value)); } @Test public void test. Number. Ocean() throws Exception { int value = 3; int expected = value/20; assert. Equals ("Conversion to Ocean number failed", expected, Number. Manipulation. Functions. number. Ocean (value), 0. 000001); } }

Change the code so should Fail and Run it again As expected it FAILS

Change the code so should Fail and Run it again As expected it FAILS Number. Manipulation. Functions. Test TEST Class: package computervision. grewe. helloapp; import org. junit. Test; import static org. junit. Assert. *; public class Number. Manipulation. Functions. Test { @Test public void test. Number. Mars() throws Exception { int value = 3; int expected = value; assert. Equals ("Conversion to Mars number failed", expected, Number. Manipulation. Functions. number. Mars (value)); } @Test public void test. Number. Ocean() throws Exception { int value = 3; int expected = value/10; assert. Equals ("Conversion to Ocean number failed", expected, Number. Manipulation. Functions. number. Ocean (value), 0. 000001); } }

Examing the Values for test. Number. Mars when Fails Number. Manipulation. Functions. Test TEST

Examing the Values for test. Number. Mars when Fails Number. Manipulation. Functions. Test TEST Class: package computervision. grewe. helloapp; import org. junit. Test; import static org. junit. Assert. *; public class Number. Manipulation. Functions. Test { See values to understand why failed @Test public void test. Number. Mars() throws Exception { int value = 3; int expected = value; assert. Equals ("Conversion to Mars number failed", expected, Number. Manipulation. Functions. number. Mars (value)); }

INSTRUMENTATION TESTS --ANDROIDTEST/JAVA Integration testing

INSTRUMENTATION TESTS --ANDROIDTEST/JAVA Integration testing

NOW lets learn about coding for Instrumentation based Unit testing ---this is the test

NOW lets learn about coding for Instrumentation based Unit testing ---this is the test case that will appear in abdroid. Test/java

WARNING: We don’t have the time to learn really how to do the more

WARNING: We don’t have the time to learn really how to do the more complex Instrumentation Testing But, this will be a start Learning some of the pieces of Instrumentation testing but, not all

Android. Test: instrumentation tests on Android hooks into the Android component and application life

Android. Test: instrumentation tests on Android hooks into the Android component and application life cycle. called the instrumentation API and allow your tests to control the life cycle and user interaction events. Run on emulator OR Android device (not local JVM like previous Junit cases)

Instrumentation Tests use Instrumentation. Test. Runner is the base test runner for Android tests.

Instrumentation Tests use Instrumentation. Test. Runner is the base test runner for Android tests. This test runner starts and loads the test methods. Monkey. Runner: A tool that provides APIs for writing program which control an Android device or emulator outside of Android code.

There are multiple options to Instrumentation test writing OPTION 1: use Activity. Rule (newest)

There are multiple options to Instrumentation test writing OPTION 1: use Activity. Rule (newest) OPTION 2: Android. Test. Case (deprecated API 24) ALSO: various packages Mock, Espresso, etc. – not covered

OPTION 1: Activity. Rule android. support. test. rule. Activity. Test. Rule<T extends android. app.

OPTION 1: Activity. Rule android. support. test. rule. Activity. Test. Rule<T extends android. app. Activity> This rule provides functional testing of a single activity. The activity under test will be launched before each test annotated with Test and before methods annotated with Before. It will be terminated after the test is completed and methods annotated with After are finished. During the duration of the test you will be able to manipulate your Activity directly.

Example- Main. Activity. java public class Main. Activity extends App. Compat. Activity implements View.

Example- Main. Activity. java public class Main. Activity extends App. Compat. Activity implements View. On. Click. Listener { int hits = 0; @Override protected void on. Create(Bundle saved. Instance. State) { super. on. Create(saved. Instance. State); set. Content. View(R. layout. activity_main ); Button b = (Button) this. find. View. By. Id(R. id. button_DO_IT ); // register listener for button b. set. On. Click. Listener(this); } //method invoked when button is hit public void on. Click(View v) { // do something when the button is clicked this. hits++; Text. View text = (Text. View)find. View. By. Id(R. id. text. View_Message String s = "You hit me "+ this. hits; text. set. Text(s); } } LAYOUT FILE <? xml version="1. 0" encoding="utf-8" ? > <Relative. Layout xmlns: android="http: //schemas. android. com/apk/res/android" xmlns: tools="http: //schemas. android. com/tools" android: layout_width="match_parent" android: layout_height="match_parent" android: padding. Bottom="@dimen/activity_vertical_margin" android: padding. Left="@dimen/activity_horizontal_margin" android: padding. Right="@dimen/activity_horizontal_margin" android: padding. Top="@dimen/activity_vertical_margin" tools: context="computervision. grewe. helloapp. Main. Activity" > <Text. View android: layout_width="wrap_content" android: layout_height="wrap_content" android: text="Hit Button" android: id="@+id/text. View_Message" /> <Button android: layout_width="wrap_content" android: layout_height="wrap_content" android: text="Do It" android: id="@+id/button_DO_IT" android: layout_below="@+id/text. View_Message" android: layout_align. Parent. Start="true" ); android: layout_margin. Top="87 dp" /> <Edit. Text android: layout_width="wrap_content" android: layout_height="wrap_content" android: id="@+id/edit. Text_Input" android: layout_below="@+id/text. View_Message" android: layout_align. Parent. Start="true" android: text="enter name here" /> </Relative. Layout >

Example using Active. Rule import org. junit. Test; Testing UI of Activity – runs

Example using Active. Rule import org. junit. Test; Testing UI of Activity – runs and types “SAMPLE” into the edit. Text import static org. junit. Assert. *; import android. support. test. rule. Activity. Test. Rule; import android. support. test. runner. Android. JUnit 4; import android. test. suitebuilder. annotation. Large. Test; import org. junit. Rule; import org. junit. runner. Run. With; import static android. support. test. espresso. Espresso. on. View ; import static android. support. test. espresso. action. View. Actions. type. Text ; import static android. support. test. espresso. matcher. View. Matchers. with. Id; /** * Created by Lynne on 10/3/2016. */ @Run. With(Android. JUnit 4. class) @Large. Test public class Main. Activity. Test 2 { @Rule public Activity. Test. Rule<Main. Activity> m. Activity. Rule = new Activity. Test. Rule(Main. Activity. class ); /** test the Activities UI by typing into the edit. Text_Input text field */ @Test public void test. UI_write. To_edit. Test_Input() { on. View (with. Id(R. id. edit. Text_Input )). perform(type. Text ("SAMPLE" )); } }

NOW want you (< api 24) use Application. Test. Case ---now use Application. Test.

NOW want you (< api 24) use Application. Test. Case ---now use Application. Test. Case

DEPRICATED in API 24 OPTION 2 Android. Test. Case class http: //developer. android. com/reference/android/test/Android.

DEPRICATED in API 24 OPTION 2 Android. Test. Case class http: //developer. android. com/reference/android/test/Android. Test. Case. html void assert. Activity. Requires. Permission(String package. Name, String class. Name, String permissi on)Asserts that launching a given activity is protected by a particular permission by attempting to start the activity and validating that a Security. Exception is thrown that mentions the permission in its error message. void assert. Reading. Content. Uri. Requires. Permission(Uri uri, String permission)Asserts that reading from the content uri requires a particular permission by querying the uri and ensuring a Security. Exception is thrown mentioning the particular permission. void assert. Writing. Content. Uri. Requires. Permission(Uri uri, String permission)Asserts that writing to the content uri requires a particular permission by inserting into the uri and ensuring a Security. Exception is thrown mentioning the particular permission. Context get. Context() void set. Context(Context context) void test. Android. Test. Case. Setup. Properly() void setup() and teardown() extends Test. Case and Assert, which you can use to test Androiddependent objects. • Android. Test. Case offers Android-specific setup, teardown, and helper methods. • testing permissions

Application. Test class Application. Test. Case test case class to test the setup and

Application. Test class Application. Test. Case test case class to test the setup and teardown of Application objects. can be useful in verifying that the <application> element in the manifest file is correctly set up. Note, however, that this test case does not allow you to control testing of the components within your application package.

Notice the Android Studio setups an Applcation. Test class for you

Notice the Android Studio setups an Applcation. Test class for you

Many other classes in android. test Instrumentation. Class Activity. Unit. Test. Case Activity. Instrumentaiton.

Many other classes in android. test Instrumentation. Class Activity. Unit. Test. Case Activity. Instrumentaiton. Test. Case* LOOK AT METHODS……read Android guide to testing online http: //developer. android. com/tools/testing_and roid. html Testing Activities ---read this http: //developer. android. com/tools/testing/activity_testing. html

What would some real test code look like…suppose you have Activity with Spinner public

What would some real test code look like…suppose you have Activity with Spinner public class my. Activity. Test extends Activity. Instrumentation. Test. Case 2 All test methods MUST start with the “test-” prefix or { public void test() throws Exception { Android Studio will not detect them as tests and you will get all kinds of weird errors and nothing will work. // Start the main activity of the application under test—gets this from parent class m. Activity = get. Activity(); // Get a handle to the Activity object's main UI widget, a Spinner m. Spinner = (Spinner)m. Activity. find. View. By. Id(com. android. example. spinner. R. id. Spinner 01); // Set the Spinner to a known position m. Activity. set. Spinner. Position(TEST_STATE_DESTROY_POSITION); // Stop the activity - The on. Destroy() method should save the state of the Spinner m. Activity. finish(); // Re-start the Activity - the on. Resume() method should restore the state of the Spinner m. Activity = get. Activity(); How does this connect to the actual Activity class you want to test // Get the Spinner's current position int current. Position = m. Activity. get. Spinner. Position(); // Assert that the current position is the same as the starting position assert. Equals(TEST_STATE_DESTROY_POSITION, current. Position); THROUGH the constructor public Activity. Instrumentation. Test. Case 2 ( Cl ass<T> activity. Class ) where the parameter is the class you want to test

RUNNING TESTS In Android Studio

RUNNING TESTS In Android Studio

Running tests Simply run the config you setup earlier (see start of talk) OTHER

Running tests Simply run the config you setup earlier (see start of talk) OTHER OPTIONS: OPTION 2: in the Project window, right-click a test and click Run. OPTION 3: In the Code Editor, right-click a class or method in the test file and click Run to test all methods in the class. OPTION 4: To run all tests, right-click on the test directory and click Run tests.

More on your own Other apis part of android. test Testing UIs Testing Services

More on your own Other apis part of android. test Testing UIs Testing Services Testing Content. Providers More Tools integrating test frameworks such as Mockito to test Android API calls in your local unit tests, Espresso or UI Automator to exercise user interaction in your instrumented tests. You can generate Espresso tests automatically using. Espresso Test Recorder. See http: //developer. android. com/tools/testing/index. html