============ Testing Apps ============ Unit Testing ============ ``Unit tests`` are referred to as “local unit tests”. The tests run without a device or an emulator attached. However, unit tests cannot test the UI for your app without mocking objects such as an Activity. In your Android Studio project, source files for local unit tests are stored at *module-name/src/test/java/*. ``Instrumented unit`` tests are tests that run on physical devices and emulators, they provide more fidelity than local unit tests, but they run much more slowly. Source files for instrumented tests are stored at *module-name/src/androidTest/java/*. Unit Testing Example -------------------- This example shows a function that verifies the format of email address and a unit test for the function. #. First, create a new project, write a program that verifies the correctness of email addresses' format, returns true if the email address has the correct address, otherwise return false. .. code-block:: kotlin class EmailValidation { val emailPatternString ="""[a-zA-Z0-9\+\.\_\%\-]{1,256}\@[a-zA-Z0-9][a-zA-Z0-9\-]{0,64}(\.[a-zA-Z0-9][a-zA-Z0-9\-]{0,25})+""" fun invalidateEmail(email: String): Boolean = email.matches(Regex(emailPatternString)) } #. Then create a local unit test class, it should be written as a ``JUnit 4`` test class. To create a basic JUnit 4 test class, create a class that contains one or more test methods. A test method begins with the ``@Test`` annotation and contains the code to exercise and verify a single functionality in the component that you want to test. In our example, there are several cases that should be considered: .. code-block:: kotlin import org.junit.Assert.* import org.junit.Test class EmailValidationTest{ val emailValidator:EmailValidation = EmailValidation() @Test fun correctEmail() { assertTrue(emailValidator.invalidateEmail("name@email.com")) } @Test fun correctEmailSubDomain() { assertTrue(emailValidator.invalidateEmail("name@email.co.uk")) } @Test fun invalidEmailNoTld() { assertFalse(emailValidator.invalidateEmail("name@email")) } @Test fun invalidEmailDoubleDot() { assertFalse(emailValidator.invalidateEmail("name@email..com")) } @Test fun invalidEmailNoUsername() { assertFalse(emailValidator.invalidateEmail("@email.com")) } @Test fun emptyString() { assertFalse(emailValidator.invalidateEmail("")) } } #. Now run the test to check if all tests are passed. If a test is passed, the test will be labeled with a *green tick*, otherwise, it will be labeled *red*. .. figure:: unit_test.jpg :scale: 30% :align: center #. Here are some methods for verifying results: ``assertEquals(expected, actual)``, verifies whether the value of expected is the same as actual. ``assertArrayEquals(expected, actual)``, verifies if the actual array is the same as expected. ``assertFalse(actual)``, verify that the returned value is false. ``assertNotNull(actual)``, verify that the returned value is not null. ``assertNull(actual)``, verify that the returned value is null. ``assertTrue(actual)``, verify that the returned value is true. ``assertThat(actual, matcher)``, verify that returned value meets the conditions in matcher. Espresso Tests ============== Espresso is a framework that allows us to write tests on the user interface. Espresso Testing works basically in three blocks: * ViewMatchers – allows to find an item in the view * ViewActions – allows to execute actions on the elements * ViewAssertions – validate a view state This example creates a simple app that a user can type message in a *TextBox*, click a *button*, then the message entered will be displayed. #. Add the following dependencies to ``build.gradle`` file. .. code-block:: groovy androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' androidTestImplementation 'androidx.test:runner:1.1.0' androidTestImplementation 'androidx.test:rules:1.1.0' #. Create a simple app where it contains a ``EditText`` for user to type in, a ``button`` to click, and once the button is clicked, the message will be shown on the screen in a ``TextView``. Example code: .. code-block:: xml