Testing in Android

Unit Testing

  • It is used to refer to simple tests. like - simple business logic test independent of any fragment or activity.

Library Used

  • testImplementation "com.google.truth:truth:1.0.1"

  • use import com.google.common.truth.Truth.assertThat instead of import org.junit.Assert.*

Implementation

  • Use a class. Inside that class create one function that returns boolean values based on different input given.
object RegistrationUtil {

    private val existingRollNos = listOf("123", "456")

    fun validateRegistrationInput (
        student_name: String,
        roll_no: String,
    ) : Boolean {
        if(student_name.isEmpty() || roll_no.isEmpty()) {
            return false
        }
        if(roll_no in existingRollNos) {
            return false
        }

        return true
    }
}
  • to generate a test class you need to right-click on class -> generate -> provide test class name and lib -> press ok.

  • Inside the test class, you can create diff test funcs using @Test annotation. Inside func provide diff inputs to validation func store that response in variable and check that response against desired value using assertThat method.

class RegistrationUtilTest {

    @Test
    fun `empty name return false`() {
        val result = RegistrationUtil.validateRegistrationInput(
            "",
            "678"
        )
        assertThat(result).isFalse()
    }
}
  • That's it you are done now run the tests. If you get the same response as the desired result. Your test will pass otherwise it will fail.

  • In the above example it will return false if the student name or roll is not given or roll already exist.

Good test

  • A good test is one that is completely independent of other test cases. eg - It will not share any global variable or like each test case will define its own variable.

@Before and @After

  • Jnuit provides this method in order to reduce code for each test case. Suppose there is a code common for every test case. Then you can define a setup function and annotate it with @Before. It will execute the code before every test case and your test case will run normally. Similarly, @After has teardown fun and you can write code that you want to run after every test case. like - destroying objects, the closing of room database, etc.
class ResourceComparerTest {

    private lateinit var resourceComparer: ResourceComparer

    @Before
    fun setup() {
        resourceComparer = ResourceComparer()
    }

    @After
    fun teardown() {

    }

    @Test
    fun stringResourceSameAsGivenString_returnsTrue() {
//        resourceComparer = ResourceComparer()
        val context = ApplicationProvider.getApplicationContext<Context>()
        val result = resourceComparer.isEqual(context, R.string.app_name, "testing")
        assertThat(result).isTrue()
    }
}

Function Naming

  • In a unit test, we can write long func names with spaces in between
@Test
fun `empty name return false`()
  • We cannot do this in other Tests there we have to name func like we normally do
@Test
fun insertShoppingItem()

Refrences