JUnit Parameterized: Execute a single test with multiple combinations of inputs

Chetan Gaikwad
4 min readNov 11, 2022

Table of content:

  • What are Parameterized Tests and its benefit?
  • How to use Parameterized Test?
  • Conclusion

What are Parameterized Tests and its benefit?

The parameterized test enables you to execute a single test with different combinations of inputs.

Consider a student class with data member names and scores. This class also has a member function to calculate the grade of the student depending on the scores.

class Student(
val name: String,
private val score: Float
) {
fun getGrade(): String {
return when {
score <=50 -> "C"
score >50 && score <=60 -> "B"
score >60 && score <=75 -> "A"
score >75 && score <=100 -> "A+"
else -> "F"
}
}
}

getGrade() decides the grade of the student by comparing the student’s score with the different score ranges. Pretty simple right

Now let's consider writing tests for the student class.

internal class StudentTest {

@Test
fun `getGrade method Should return valid grade`() {
//Given
val student = Student("Don", 45F)

//when
val result = student.getGrade()

//then
Assert.assertEquals(result, "C")
}
}

If we consider the above test we have just tested a single case of the getGrade() method. If we have to test all the cases of getGrade() method then either we have to write 5 tests for each case or we can test all the cases in a single test by creating 5 different Student objects with different scores.

Let’s try to implement the latter solution

internal class StudentTest {

@Test
fun `getGrade method Should return valid grade`() {
//Given
val student = Student("Don", 45F)
val student2 = Student("Jon", 55F)
val student3 = Student("Mon", 65F)
val student4 = Student("Con", 85F)
val student5 = Student("Ron", 28F)

//when
val result = student.getGrade()
val result2 = student2.getGrade()
val result3 = student3.getGrade()
val result4 = student4.getGrade()
val result5 = student5.getGrade()

//then
Assert.assertEquals(result, "C")
Assert.assertEquals(result2, "B")
Assert.assertEquals(result3, "A")
Assert.assertEquals(result4, "A+")
Assert.assertEquals(result5, "F")
}
}

Here you saw that to cover all the cases of the getGrade() method we have to add a lot of boilerplate code.

Here come the Parameterized tests.

How to use Parameterized Test?

Dependency: I will be using JUnitParams library for writing Parameterized tests. Add the dependency to the build.gradle file

testImplementation "pl.pragmatists:JUnitParams:1.1.1"

In order to support parameterized tests add a class-level annotation

@RunWith(JUnitParamsRunner::class)

Add all the input as a parameter for the given test method

@Parameters(
"Don, 45, C",
"Jon, 55, B",
"Mon, 65, A",
"Con, 85, A+",
"Ron, 28, F",
)

Now create a test method and provide method parameters corresponding to the above parameter list.

@Parameters(
"Don, 45, C",
"Jon, 55, B",
"Mon, 65, A",
"Con, 85, A+",
"Ron, 28, F",
)
@Test
fun `getGrade method Should return valid grade`(
name: String,
marks: Float,
grade: String
) {
val student = Student(name, marks)
Assert.assertEquals(student.getGrade(), grade)
}

The final class looks like

@RunWith(JUnitParamsRunner::class)
internal class StudentTest {

@Parameters(
"Don, 45, C",
"Jon, 55, B",
"Mon, 65, A",
"Con, 85, A+",
"Ron, 28, F",
)
@Test
fun `getGrade method Should return valid grade`(
name: String,
marks: Float,
grade: String
) {
val student = Student(name, marks)
Assert.assertEquals(student.getGrade(), grade)
}
}

Till now we have seen only primitive data types as a parameter, what If we have to support class objects as a parameter? Well, we can also use objects as a parameter as follows.

@Suppress("unused")
private fun parametersForGetGradeTest(): Array<Any> {
return arrayOf(
arrayOf(
Student("Don", 45),
"C"
),
arrayOf(
Student("Jon", 55),
"B"
)
)
}

In the above code, we have created a method that returns an array of arrays and each inner array contains 2 objects—one Student object and another the expected value.

We can give this array as an input to the test method as follows

@Parameters(method = "parametersForGetGradeTest")
@Test
fun `getGrade method Should return valid grade`(
student: Student,
grade: String
) {
Assert.assertEquals(student.getGrade(), grade)
}

Source code: https://github.com/gaikwadChetan93/MyPlayground

Conclusion: We can write efficient, more readable, and effective tests with the parameterized tests if we have to cover multiple cases of a given logic.

Let’s Connect

For any query, suggestion, or improvement on my blog ping me

--

--