How to create parametrized test cases in JUnit 4 and Kotlin for Android?

Following this amazing tutorial, we can implement it in Kotlin language in this way:

First of all convert the EmailIdUtility class into Kotlin:

object EmailIdUtility {
    fun isValid(email: String): Boolean {
        val regex =
            "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$"
        val pattern = Pattern.compile(regex)
        val m = pattern.matcher(email)
        return m.matches()
    }
}

Then convert the EmailIdValidatorTest into Kotlin

@RunWith(value = Parameterized::class)
class EmailIdValidatorTest(
    private val email: String,
    private val expected: Boolean)
{
    @Test
    fun testIsValidEmailId() {
        val actual = EmailIdUtility.isValid(email)
        assertEquals(expected, actual)
    }

    companion object {
        @JvmStatic
        @Parameterized.Parameters(name = "{index}: isValid({0})={1}")
        fun data(): Iterable<Array<Any>> {
            return arrayListOf(
                arrayOf("[email protected]", true),
                arrayOf("[email protected]", true),
                arrayOf("[email protected]", true),
                arrayOf("mary@testdomaindotcom", false),
                arrayOf("mary-smith@testdomain", false),
                arrayOf("testdomain.com", false)
            ).toList()
        }
    }
}

Remember to add @JvmStatic in the data() method, otherwise you will get the error: java.lang.Exception: No public static parameters method on class com.example.testapp.dev.EmailIdValidatorTest


EASIER WAY

If you can use another library (working in Android too) I suggest you to add JUnitParams to your test dependencies, in Android it could be:

testImplementation  "pl.pragmatists:JUnitParams:1.1.1"

Then you could convert the above class in this way:

@RunWith(JUnitParamsRunner::class)
class EmailIdValidatorTest {

    @Test
    @Parameters(value = [
        "[email protected], true",
        "[email protected], true",
        "[email protected], true",
        "mary@testdomaindotcom, false",
        "mary-smith@testdomain, false",
        "testdomain.com, false"
    ])
    fun testIsValidEmailId(email: String, expected: Boolean) {
        val actual = EmailIdUtility.isValid(email)
        assertEquals(expected, actual)
    }
}

which for me is a lot easier than the JUnit way.

For more examples on how to use JUnitParams you can check the link.

With JUnit 5 this is a lot easier but currently JUnit 5 is not supported for Android tests if you don't use Android-JUnit 5 too.


I know you're using JUnit 4, but if you consider to update to JUnit 5, you can use @TestFactory annotation to execute parametrized unit test.

In your case that would result in a test class like this:

import org.junit.jupiter.api.DynamicTest
import org.junit.jupiter.api.TestFactory

internal class EmailIdValidatorTest {

    @TestFactory
    fun `test email id validity`() =
        listOf(
            "[email protected]" to true,
            "[email protected]" to true,
            "[email protected]" to true,
            "mary@testdomaindotcom" to false,
            "mary-smith@testdomain" to false,
            "testdomain.com" to false
        ).map {
            dynamicTest("email ${it.first} should be ${if (it.second) "valid" else "not valid" }") {
                val actual = EmailIdUtility.isValid(it.first)
                assertEquals(expected, actual)
            }
        }

}