Necesito algo similar al escenario C# NUnit TestCase con resultados esperados fijos.
Ya encontré esta pregunta en SO que tiene excelentes soluciones, pero son solo para Java y, como se sugiere en algunas de las respuestas, seguí este tutorial , pero simplemente convertirlo a Kotlin no funciona.
@RunWith(value = Parameterized.class) public class EmailIdValidatorTest { private String emailId; private boolean expected; public EmailIdValidatorTest(String emailId, boolean expected) { this.emailId = emailId; this.expected = expected; } @Parameterized.Parameters(name= "{index}: isValid({0})={1}") public static Iterable<Object[]> data() { return Arrays.asList(new Object[][]{ {"mary@testdomain.com", true}, {"mary.smith@testdomain.com", true}, {"mary_smith123@testdomain.com", true}, {"mary@testdomaindotcom", false}, {"mary-smith@testdomain", false}, {"testdomain.com", false} } ); } @Test public void testIsValidEmailId() throws Exception { boolean actual= EmailIdUtility.isValid(emailId); assertThat(actual, is(equalTo(expected))); } }Entonces, ¿cuál es la forma correcta de escribir pruebas unitarias parametrizadas de Kotlin con JUnit?
Siguiendo este increíble tutorial, podemos implementarlo en lenguaje Kotlin de esta manera:
En primer lugar, convierta la clase EmailIdUtility en 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() } } Luego convierta EmailIdValidatorTest en 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("mary@testdomain.com", true), arrayOf("mary.smith@testdomain.com", true), arrayOf("mary_smith123@testdomain.com", true), arrayOf("mary@testdomaindotcom", false), arrayOf("mary-smith@testdomain", false), arrayOf("testdomain.com", false) ).toList() } } }Recuerde agregar
@JvmStaticen el métododata(), de lo contrario obtendrá el error: java.lang.Exception: No hay un método de parámetros estáticos públicos en la clase com.example.testapp.dev.EmailIdValidatorTest
UNA MANERA MÁS FÁCIL
Si puede usar otra biblioteca (que también funcione en Android), le sugiero que agregue JUnitParams a sus dependencias de prueba, en Android podría ser:
testImplementation "pl.pragmatists:JUnitParams:1.1.1"Entonces podría convertir la clase anterior de esta manera:
@RunWith(JUnitParamsRunner::class) class EmailIdValidatorTest { @Test @Parameters(value = [ "mary@testdomain.com, true", "mary.smith@testdomain.com, true", "mary_smith123@testdomain.com, 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) } } que para mí es mucho más fácil que la forma JUnit .
Para obtener más ejemplos sobre cómo usar JUnitParams, puede consultar el enlace.
Con JUnit 5 esto es mucho más fácil , pero actualmente JUnit 5 no es compatible con las pruebas de Android si no usa Android-JUnit 5 también.
Sé que está usando JUnit 4, pero si considera actualizar a JUnit 5, puede usar la anotación @TestFactory para ejecutar la prueba unitaria parametrizada.
En su caso, eso daría como resultado una clase de prueba como esta:
import org.junit.jupiter.api.DynamicTest import org.junit.jupiter.api.TestFactory internal class EmailIdValidatorTest { @TestFactory fun `test email id validity`() = listOf( "mary@testdomain.com" to true, "mary.smith@testdomain.com" to true, "mary_smith123@testdomain.com" 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) } } }