He estado escribiendo algunas pruebas unitarias para algún código nuevo en el trabajo, y lo envié para una revisión del código. Uno de mis compañeros de trabajo hizo un comentario sobre por qué estaba poniendo variables que se usan en varias de esas pruebas fuera del alcance de la prueba.
El código que publiqué fue esencialmente
import org.junit.Test;
public class FooUnitTests {
@Test
public void testConstructorWithValidName() {
new Foo(VALID_NAME);
}
@Test(expected = IllegalArgumentException.class)
public void testConstructorWithNullName() {
new Foo(null);
}
@Test(expected = IllegalArgumentException.class)
public void testConstructorWithZeroLengthName() {
new Foo("");
}
@Test(expected = IllegalArgumentException.class)
public void testConstructorWithLeadingAndTrailingWhitespaceInName() {
final String name = " " + VALID_NAME + " ";
final Foo foo = new Foo(name);
assertThat(foo.getName(), is(equalTo(VALID_NAME)));
}
private static final String VALID_NAME = "name";
}
Sus cambios propuestos fueron esencialmente
import org.junit.Test;
public class FooUnitTests {
@Test
public void testConstructorWithValidName() {
final String name = "name";
final Foo foo = new Foo(name);
}
@Test(expected = IllegalArgumentException.class)
public void testConstructorWithNullName() {
final String name = null;
final Foo foo = new Foo(name);
}
@Test(expected = IllegalArgumentException.class)
public void testConstructorWithZeroLengthName() {
final String name = "";
final Foo foo = new Foo(name);
}
@Test(expected = IllegalArgumentException.class)
public void testConstructorWithLeadingAndTrailingWhitespaceInName() {
final String name = " name ";
final Foo foo = new Foo(name);
final String actual = foo.getName();
final String expected = "name";
assertThat(actual, is(equalTo(expected)));
}
}
Donde todo lo que se requiere dentro del alcance de la prueba, se define dentro del alcance de la prueba.
Algunas de las ventajas que argumentó fueron
- Cada prueba es independiente.
- Cada prueba se puede ejecutar de forma aislada o agregada, con el mismo resultado.
- El revisor no tiene que desplazarse a donde se declaren estos parámetros para buscar cuál es el valor.
Algunas de las desventajas de su método que argumentaba eran
- Aumenta la duplicación de código
- Puede agregar ruido a la mente de los revisores si hay varias pruebas similares con diferentes valores definidos (es decir, prueba con
doFoo(bar)resultados en un valor, mientras que la misma llamada tiene un resultado diferente porquebarse define de manera diferente en ese método).
Además de la convención, ¿hay otras ventajas / desventajas de usar cualquiera de los métodos sobre el otro?