Facultad de Informática
Trabajo Final Integrador de la
Especialización en Ingeniería de Software
Estado del arte y tendencias en
Test-Driven Development
Autor: Moisés Carlos Fontela
&' * ()
Estado del arte y tendencias en
Test-Driven Development
Autor
! + ," ,
Palabras clave
! - ! " " ! " ! !
" ! " ,
Resumen
! ' " ! " " '
- ! " "
, ! - ! . " " ,
. " / . 0" - " " 0"
. ! " 0" "
-" , 1 . 0" " " .
0" , 2 3 - .
. " / " " ,
. " " " " !
&' 4 ()
Índice
' 5555555555555555555555555555555555555555555555555555555555555 6
7 8 9 5555555555555555555555555555555555 :
7 " 555555555555555555555555555555555555555555555555 %*
7 " ;& 555555555555555555555555555555555555555555555555555555 %(
< = 55555555555555555555555555555555555555555555555555555555555555555555 %(
> = 555555555555555555555555555555555555555555555555555555555555555555555 %)
> , < 55555555555555555555555555555555555555555555555555555555555555555555555555 %?
= " " 5555555555555555555555555555555555555555 %:
7 ' 555555555555555555555555555555555555555555 #%
5555555555555555555555555555555555555555555555555555555555555 ##
! " # $ %&& ''
555555555555555555555555555555555555555555555555555555555555 ## 9 " " = @ 555555555555555555555555555555555555555555555555555555555555 #*
" 55555555555555555555555555555555555555555555555555555555555555 #6
(&& ')
& " " " 5555555555555555555555555555555555555555555555555555555555555555 #?
7 " 555555555555555555555555555555555555555555555555555555555555555 #:
7 " 55555555555555555555555555555555555555555555555555555 #:
( * +
A"/ " 55555555555555555555555555555555555555555555555555555555555555555555555555 *$ " 555555555555555555555555555555555555555555555555555555555555555555 *$
, (&& - - ./
B 0" . / 555555555555555555555555555555555555555555555555 *%
B 55555555555555555555555555555555555555555555555555555555555555 **
B 0" / > 555555555555555555555555555555555555555555555 **
B " 55555555555555555555555555555555555555555555555555555 *(
< " . 555555555555555555555555555555555555555555555555555555555555 *(
(&& ! 0
(&&
-C " 9 555555555555555555555555555555555555555555555555555555555 *6
0" " 55555555555555555555555555555555555555555555555555555555555555 *?
" D 555555555555555555555555555555555555555555555555 *?
" ' ' 9 555555555555555555555555555555555555555555555 *:
1 (&& - ! +
- (&&
E 555555555555555555555555555555555555555555555555555555555555555555555555555555 (% " 555555555555555555555555555555555555555555555555555555555555555555555555555555 (# " 5555555555555555555555555555555555555555555555555555555555555555555555 (*
2
&' 6 ()
Introducción
TDD como práctica metodológica
% F G " '
-! 0" " # H > 8 I " . D
& *F;&G J%K,
>' ! " " ' =
• <" = " . . !
" 0" "
,
• = " ,
• E ( = - !
-" ! " " ,
" " 4=
%
! L " " M, " ' ! " / ,
#
! " ' " , . " '
/ %:)$! " 0" ." " " ,
*
! L& D M, " ' ;&! " / ,
(
B " / L M " / / L M! 0" "
L& ' M ,
4
0" L " M " .
, < ! " " "
&' ? ()
" " ' =
• 7 " ." ! "
" ,
• 7 " / " ! "
" " ,
! " " ,
• " "
" , / ' . . 0"
0" " ,
• "
" 3 ,
• 7 " "
-0" ! . ! ,
B " ! 0" ! 0" = L@" "
" " " 0" M J#K, 1 = L " " "
0" ' ! M J*4K,
0" " " " " !
" " 0" " , " 0"
" " ! " D !
&' : ()
@ 0" . " ' - ! " F
G! 0" " "
! 0" " ,
! " D 0" - , > 8 J%K
0" " " " ! "
- ! ' 0" .
' " ' ,
! " . . " ! 0" "
" ! " ! " 0"
. " . 0" " 4$N "
,
< 0" ! ' "
! / 0" , / " "
;&! " " !
' ,
La aparición de los frameworks y el corrimiento de TDD a UTDD
6- ! " " "
,
" ' ! 8 " " = 9
8 O9 O , 7 " " '
. ! 0" / D9 ,
B = . . 0" .
" ! . . 0" . 0" " ,
! 0" " L M,
! " 0" " / - " !
, " . 0" " " !
" ' ! 0" 0" " "
/ " "
F @9 ( O9 ! "
0" " G, @ 0" " " " "
! " ! ' "
,
" " 0" 0" " !
0" - ! " . " " , < !
. " = O9 ! 9 ! @9 ! , 2 " > 8
" J#K " " , & 0"
0" " D " . " " ,
0" ! ! 9 . /D ,
" . ! ' =
• 7 " " "
/ " ,
)9 " . " ! 0" L9 M, "
&' %$ ()
• 7 " P 0" /
. ,
• 7 " " 0" '
! ,
• 7 " " " ' " 0"
0" ,
! / " ' =
• 0" - " ! "
" , B " ' 9 0" " "
" " / " / " ,
• E ! " . . 0" 0" "
" 6! . - ,
• @ " " ,
• " ' ! "
, 7 ,
• ' " " !
- " D " " ,
< " " " "
9 =
6
;& J%K 0" - ! 0" "
0" " ! 0" "
&' %% ()
" 0" ! " " !
0" ,
" 0" " ? ,
" 8 D9 " " " "
0" " =
• " ,
• ,
• 0" . 0"
" ! 0" "
,
• ! ,
& ! " " !
O9 0" " =
import org.junit.*;
import static org.junit.Assert.*;
? 7 ' L M .
&' %# ()
public class PruebaCuentaBancaria {
private final int NUMERO_VALIDO = 1234; private final int NUMERO_INVALIDO = -1234;
@Test
public void debeCrearUnaCuentaValidaConDatosSuministrados( ) { CuentaBancaria cuenta = crearCuentaValida();
assertEquals ("El número de cuenta se guardó mal",
NUMERO_VALIDO, cuenta.getNumero() ); assertEquals ("El nombre del titular se guardó mal",
"Carlos", cuenta.getTitular() ); assertEquals ("El saldo no comenzó siendo cero",
0, cuenta.getSaldo() ); }
@Test (expected = IllegalArgumentException.class)
public void creacionConNumeroInvalidoDebeArrojarExcepcion ( ) { CuentaBancaria cuenta =
new CuentaBancaria (NUMERO_INVALIDO, "Carlos"); }
@Test (expected = IllegalArgumentException.class)
public void creacionConTitularVacioDebeArrojarExcepcion ( ) { CuentaBancaria cuenta =
new CuentaBancaria (NUMERO_VALIDO, ""); }
@Test (expected = IllegalArgumentException.class)
public void creacionConTitularNuloDebeArrojarExcepcion ( ) { CuentaBancaria cuenta =
new CuentaBancaria (NUMERO_VALIDO, null); }
@Test
public void depositoDebeIncrementarSaldo ( ) { int montoDepositado = 100;
CuentaBancaria cuenta = crearCuentaValida(); int saldoPrevio = cuenta.getSaldo();
cuenta.depositar(montoDepositado);
assertEquals("El depósito funcionó mal",
saldoPrevio + montoDepositado, cuenta.getSaldo() ); }
@Test (expected = IllegalArgumentException.class)
public void depositoConMontoNegativoDebeArrojarExcepcion ( ) { CuentaBancaria cuenta = crearCuentaValida();
cuenta.depositar(-100); }
@Test
public void extraccionDebeDisminuirSaldo ( ) { CuentaBancaria cuenta = crearCuentaValida(); int montoDepositado = 100;
int montoAextraer = 50;
cuenta.depositar(montoDepositado); cuenta.extraer (montoAextraer);
assertEquals("La extracción funcionó mal",
&' %* ()
@Test (expected = IllegalArgumentException.class)
public void extraccionConMontoNegativoDebeArrojarExcepcion ( ) { CuentaBancaria cuenta = crearCuentaValida();
cuenta.extraer(-100); }
@Test (expected = SaldoInsuficiente.class)
public void extraccionConSaldoInsuficienteDebeArrojarExcepcion( ) { CuentaBancaria cuenta = crearCuentaValida();
cuenta.depositar(50); cuenta.extraer(100); }
private CuentaBancaria crearCuentaValida() {
return new CuentaBancaria (NUMERO_VALIDO, "Carlos"); }
}
@ 0" ! " '
D ! 0" ! " ,
. " . 0"
" ' ! , 2 ,
Los primeros intentos de pruebas de integración
0" " . 9 0" "
0" - ! ,
" " "
! ' ,
0" . ! 0"/
" 3 , 7 '
" " ! " 0" ,
< ! " " 0" " "
! ,
< " "
! 0" 0" Q J%(K ! 0" :=
• F ! L MG= 0" 0"
" " ! 0" " " , & ! " "
/ " ' ! / " " ,
• F ! L "- MG= 0" !
" " 0"
' , & ! 0"
" ,
• F ! L MG= " 0"
0" ' ! " " ,
• F ! L MG= 0"
,
:
Q . " " " ! " . "
0" . . . " " F J%4KG! ! " 0" " .
! . 0" "
&' %( ()
• F ! L MG= 0"
" , & ! " "
- ,
@ 0" 0" " " " 0" '
! " , " ! 0" '
" " " " ! "
" " ,
& ! " ! " 0" ' ,
0" "
0" " , 2 "
" " " ,
Q" . " 0" . 3 , <
" 0" " " " "
" D , & ! / /
,
& " " ! 0" " / ! " " / 8 0"
" " 0" " ,
La visión de las pruebas de cliente de XP
" H > 8 ;&! " " ' 0"
/ ' ! 0" "
" " 0" ,
" . 0" > 8 0" ,
! 0" " " ! 0" > 8
" , 7 " 0" " / 8
" %$! / " ! " / !
- " ! " ,
2 0" 8 " " . "
! D ! / " 0" "
" ,
" / ! 0" " . 0"
8 D9 ! / " !
- ! 0" " " " ! 0"
0" , / ,
El punto de vista de los requerimientos y del
comportamiento
ATDD: TDD ampliado
< %% F< G " ' - 0"
" " ,
%$
H > 8 9 ! " ! " . R ! O9 ,
%% ! L " " M, " ' < ! "
&' %4 ()
! " " ! 0" " !
" " " ! " ,
7 0" ! " ! " "
" " ! " " " ' !
" ,
< 0" " F 0"
. 9 " G=
7 " 0" / 0"
! 0" / 0"/ 0"/, & 0"
0" ! 0" ,
7 " "
,
< ! < " " / ' , "
" " < = <
&' %) ()
7 " 0" - !
' ! 0" "
, < ! ! "' . . "
0" ! = . 0" "
" ' " , < !
0" 0" %# !
" ,
" 0"/ D " " , 7 "
/ " " ! " 0"
! " ,
BDD: TDD mejorado
" 0" ! @ . J( 4K .
> . " %*F> G,
7 " @ .! 0" " "
%(
J)K F G! 0" ! / " !
/ , ! " ' '
, 2 "
! " " " !
" ,
< ' ! @ . " 0" " /
0" - ! , . . ! "
0" . 0" " " " " !
" / ! 0" '
,
7 . 0" " > ! " " . /
! " / ' !
0" " " ,
& / > ' ! " "
0" F " G " / , > !
/ " ! . 0"
/ " , 7 " 3
" / ,
3 , 0" 0" " " "
" , @ 0"
' , < ' ! . " "
! ,
" " 0" " ! . ' !
" ! 0" "
" ! " 0" 0" , 7 !
0" " . " 0" . " !
,
%#
L M! ! " "
" " ! " 0" . ,
%* ! L " M, " ' > ! " / ,
%(
&' %6 ()
" > ! " "
@ . " " ! F < " !
" G=
> ! ! " " , ! =
• 7 0" 0" > " ! " "
" , " " ,
• 7 0" 0" > . . J6K,
7 ' ! " 0" > / ! 0" ! 0"
. 0" ! " 0" , <
! 0" " . ,
& ! " F " . " / !
G=
As a [X] Como [X]
I want [Y] Deseo [Y]
&' %? ()
2 " " ! S " ;
0" " ,
> ' ! @ . " 0" " !
! D =
Given [un contexto inicial]
When [ocurre un evento]
Then [asegurar que se obtiene lo siguiente]
2 . > " " , & !
O> . ! . > O !
! ! 3 ,
7 . " >
, 0"
" . ' , " L"
" M J6K,
& " > ! ' < ! . " " > !
' . , ' . " "
" ! 0" D ! " ! !
,
BDD vs. ATDD
< > ' ' ! " #$$# "
#$$*,
2 " F> " !
0" < " G! " " ,
! 0" " " !
" " ,
! ' < > , ! " '
. ,
Q 0" > ! .
< 0" " /
, " . " ! 0"
" ' ! " "
, 8 " < "
" " ' ! . "
" ! " F" # G! "
" > , & 0" " 0" . > " !
" ! 0" "
' = " ! . < ,
7 0" ! > < " / 0" "
0" - 0" ! 0"
" , 2 9 " / - ! >
" - ! < " 0" , < /
0" " ! "
/ ! ' " / ' ,
! 9 " - ! 0" < >
&' %: ()
7 > < ' " =
• Q
• "
• Q " = ! " " ! !
• Q 0"
• "
• 9 " " 3 ! ' "
• " ! "
•
-7 0" > < "
! > Q ! " - " ,
3 / J?K! 0" - " , " " 0" !
" " " ! !
0" " " " "
" %4,
7 " . " ! D I " . J:K! 0"
' 0" " ! 3 !
! ' '
, 7 H 8 J%$K 0"
' ! ' ' ,
0" ' ! < > ,
STDD: ejemplos como pruebas y pruebas como ejemplos
A" . " " H > 8 J%K > < ! " "
/ . " %) F G,
L M! 0" Q" J#(K H 8 '
. " ! ' " ,
7 " " ! 0"
! . 0" / ,
< ! . " " ! 0"
, 7 " " "
" ! " , 7 ! "
! " ! 0" " , " !
! 0"
, " . 0"
! 0" 0" 0"
,
! . 0" 0" ! " !
0" , 0" " .
%4
. " " " "
-! " " . J*#K! 0" " "
F G,
%) ! L " . " M, " ' ! "
&' #$ ()
! - 0"
,
0" ! " ' =
• . " ,
• D D ! !
,
• ' ! ' ,
• 0" ! " ! " ,
• " ,
@ 0" " ,
" . ! " ! / " "
" " " ! 0" "
- ,
0" ! ' " =
• . L " M ! " !
! , " . D ! !
0" ,
• 0" " , E !
" " " ,
. ! 0" " " ,
• - " " , E !
" - ! " " " "
/ , " ! .
! / ,
• " " ! " ! . ,
0" ! =
• " ,
• " '
! 0" " " " / ,
• ! 0"
" ,
• " ' ! " "
! ,
" ! " ,
! ' " " 3 '
! " " " J)K, / "
0" 0" 0" ." ! 0" "
. 0" " , . 0" .
" 0" ' 0" 0" " . 0"
" " ,
Q' ' 0" " / 0" D
" ! . ! . !
" ,
! " !
&' #% ()
" " ! " ! " " ! . 0" 0"/
" ,
. =
• > Q 8 "- L M%6 J#$K! 0"
' . " ' ! / . "
L " M%?J#%K,
• R I R " J%:K! . . L 0" M%:,
• R 8 < J%*K = Q 8!
L M! L 0" " " M#$ '
L " ' M#%,
Q' ' ! " 0" " /
" 0" , 2 0" ! > 8
J%#K! L ' " "
0" " M,
Limitaciones de la práctica de especificar con ejemplos
0" D , ! . 0" 0"
0" " D " 0"
, & ! 0"
- " !
0" " " ! 0"
" ! " 0" " ,
< " 0" 0"
, ! ! J%*K!
##
! " ,
& ! 0" " , &
! " 3 ! 0"
" " , " '
" / - ,
1 ' " 0" " 0"
' 0" ! " " " , 2
,
0" ! 0"/
" =
• = " ! . . 0" ,
• = " ,
• = " ,
• Q = " ! ,
%6
L > D M,
%?
L>" M,
%:
L> 8 D 0" M
#$
L E 0" M,
#%
L< < M
##! F ! L MG / 0" " 0" . "
&' ## ()
• = " !
D ,
• E = " " ,
• @ " = " " ,
• = " " ,
• C D " " = " ,
• C = " ,
• = " ,
• < " = " !
D ,
Formatos de las especificaciones
B 0" .
= ! D ! , " !
! . . " ,
7 " " " " " ! " 0"
" " ! 0"
" " ' ,
D " " !
0" " " 0" " , & !
0" " ,
" ! 0" " D " !
, & ! . "
" 0" ! !
0" " " " ' ,
" ! "
" " ' ! " " " , ! "
. " "
/ ,
& ! . 0" " 0" " ! "
0" / . ,
El foco en el diseño orientado a objetos: NDD
El problema del comportamiento
" ! 8, 2
" ' ! " "
,
<. ! " ! ! . " /
' 0" ,
! 0" " " ! 0" "
! " " "
=
&' #* ()
// depósito de 1000 pesos:
cuentaBancaria.setSaldo ( cuentaBancaria.getSaldo ( ) + 1000 );
// si el cliente y la sucursal están en la misma localidad: if ( cliente.getDomicilio().getLocalidad().equals(
sucursal.getDomicilio().getLocalidad() ) ) { ... }
! 0" " ' ! 0" D /
=
punto.moverHorizontalPixeles ( 2 );
cuentaBancaria.depositar ( 1000 );
if ( cliente.estaEnMismaLocalidad (sucursal) ) { ... }
" " $ #*! 0"
" ! " ,
0" . "
" " 0" , & ! "
,
7 8 9 " !
!
" " , <. !
,
" ! " " " "
0" " , & ! T0"/ "
0" " ! "
" U . 0" "
" ,
" " ! . 0" 0" 0" " " "
! . 0" / " 0" !
" , !
" ! " ,
Una propuesta de solución: NDD
" " ! 11& 7< #$$(!
" " J##K! 0" 0"
/ ! '
" " " ! 3 9 ,
! ' @ #( F@ G,
& ! " . " "
@ J#*K! " " > , " !
" " J%?K " , / "
! . " % ! " 0"
#*
& 11& 7< %:??! 7 ! & "
, C . =VV , , ", "V .V V V V ??
, . =VV , , ", "V. V V7 ,. ,
#(
&' #( ()
0" 0" " " , & ! "
! ' @ ,
" " " - "
" ! =
• Q / ,
• & " ,
• E " ,
• ,
C / ! " 9 ! 0" !
0" 0"/ ' " "
" " ,
0" 0" " "
! . "
" ! @
0" , ! 9 !
0" @ / 0" ! " !
" 3 , 7 @ ! 0" / .
. Q 8! " ,
& ! " " " 9 =
&' #4 ()
&' #) ()
' ( 0" ) " *% + '
) " *% + (! 0" 8 ,
" " / @ =
• D 0" 0"
,
• E ! " ,
• D 0" " ,
• 0" ,
• C D ,
! ! "
" / " , . . . Q 8 #,
import org.junit.*;
import org.junit.runner.RunWith;
import org.jmock.integration.junit4.*; import org.jmock.*;
@RunWith(JMock.class)
public class PruebaInteraccion {
private final Mockery contexto = new JUnit4Mockery(); private final CuentaBancaria cuenta =
new CuentaBancaria (1234, new Cliente ("Carlos"));
@Test
public void deberiaPagarCreditoAsociado ( ) { final int MONTO_A_PAGAR = 5000;
// vinculación de objetos Cuenta y Credito:
cuenta.setCreditoAsociado(contexto.mock(Credito.class));
// expectativas:
contexto.checking(new Expectations() {{
oneOf(cuenta.getCreditoAsociado()).pagar(MONTO_A_PAGAR);
}});
// método que se va a probar:
cuenta.pagarCredito(MONTO_A_PAGAR); }
}
/ , - ! 0" ! " 0"
/ " " ! " /
! , @ 0" " ! "
. " 0" F Q 8 0" ! "
8 ! " . G,
9 @ " , ! 0"
. ! / " 0" "
&' #6 ()
" " !
0" . 0" . ! 0" " , 7
0" . 0" " ' ! 0" D
,
B " " " " @ =
• R 0" , 7
" 0" ' " " ' ,
• ! 0"
" ! " #4,
• R ,
• " " , !
0" ,
• " / " , "
! " " - ' ,
• " " . " " ! " 0"
,
Discusión sobre pros y contras
9 " " / 0" ! !
' 0" " ! "
, 2 0" ! "
, < ! "
,
7 . 0" "
" , 2 ! 0" " ! "
,
& ! 0" @ " " ! 0"
" ! ,
/ 0" " " !
0" !
,
! ,
0" @ 0"
, ! . "
8 " / " D #)! 0"
" / ! " " , ! 0"
@ = ' 0" 9 ! 0" 3 0"
" " 0" . ' " " "
0" ,
< ! @ " D "
,
1 " ! ! 0" " 0"
,
#4
<" 0" D " 0" " "
,
#) 7 L D M F / L MG 0" "
&' #? ()
& ! . 0" D , 0" ! 0" /
" , ! " .
" . " "
" , ! " 9 ,
Pruebas de interacción y TDD
Pruebas e interfaz de usuario
' F ! < ! > ! ! @ G "
! - , @ . "
" " " ! ,
" E 8 Q" I " . J:K 0" .
" " " " ! 0" / " "
" " . " , / @ . J*K! R 8 < J%*K!
@ & J%?K / 0"/ ! 0"
' ! ! "
" ,
< ! " 0" " " " " "
" ! " . /
/ ' 0" H > 8 ;& J%K,
! . " 0" " " " " ." , &
! " ! ! " !
' " , 2 " " 0" "
,
& ' " = ! 0"
" ! D. ! /
" " " ! /
" " ,
& - " ! " " 0"
" / " " " , ! "
! 0" "
" " " ,
! " " " ,
! 0" D . "
" ' , . . ! . / 0" D "
" " ,
. " " "/ "
! . 0" " " . "
, ' =
" " " " ' !
' ,
& ! . . . " " 0"
" " ! 7 <#6 J#)! #6 #?K,
/ Q J#4K,
#6
&' #: ()
La falta de una visión integral
! ! " / ! 0" "
" " " " !
,
! " ! . "
! ! " " ,
0" " " " ' ,
& " ! " ' ! "
D ,
" ! " " ! 0" ! .
" " , ! " ! /
" ! " ,
! . 0" " " , 2 0" " " /
! ! / " ,
& 0" . . " > , '
" , J%%K,
! " " . " " ! .
" , . . ! " "
0" ' " . ! ' 0" !
0" " " /
" " ,
Limitaciones de las pruebas de interacción
7 " " ! " 0"
. " = L " ' M#?, 7 0" "
" " ! =
• =
" " ! 0" . 0" " " ,
• = 3 0" - " " "
0" " ,
• = " . 0" "
! " 0" / ! 0" . 0" . 0"
,
• D = " 0" ! " "
D ,
! ' D " " " /
" " 0" ' 0" . ,
" ! . " " 0" "
" =
• " ! " " !
,
• . " " ' "
,
#?
&' *$ ()
• 0" " ' ' 0" ! . 0"
F " 0"
> ! " 0" " @ G,
Tipos de pruebas y automatización
Qué automatizar
< . " !
" , ! ! " 0" "
" ,
0" " . " !
' " , & ! R Q J%(K "
! 0" " " 0" " =
• & " = D .
" ,
• & " = - D
0" W " / ,
• & " " = - D
,
• & " " = " F " G
" " " ,
• & " D = "
,
• & " = " !
" ! ! " ! ,
7 Q 0" / 0" " "
" " ! 0" ' . " ,
! ! ! " ! "
" , 7 3 " " " .
! 0" " " "
. D9 " , ! " "
D ! . " ,
Q' ' " ! " " " !
! " ! ! 0"
" ." " " '
" = ! " " 0" 0" " ,
Formas de automatización
<. ! 0" " . ,
" ! 0" " "
, 9 " 0" " . "
, " ! . "
=
• Q " " ! " " " " ."
&' *% ()
7 " / " " 3 ! 0"
0" -,) / " " ,
7 " 0" " =
• " F " J%(KG
• " " . " F 3
% J%(KG
@ . . . " / " , !
" . ' " 0" !
" / " " ,
" ,
7 . D9 " " 0" "
/ -,) ,
D ! 0" " " " ! "
0" " " " ,
& . " , & ! / -,) "
" . 0" !
/ " , 2 / " " /
. " " ,
Herramientas de TDD más allá de xUnit
Herramientas que hacen énfasis en la legibilidad
9 " " " " 0"
! 0" F - ! 0" G 0" 0"
" " . ,
2 " " 0" " ! " '
,
& ! ! 9 O9 *! 0" " D
" " 0" "
, 1 0" / " "
0" ! ' ' ! 0" !
0" " ,
" @9 ! " !
. , O9 ( " ! "
O 4,
& ! " O9 *=
public class PruebaCuentaBancaria extends TestCase {
// la clase debe derivar de TestCase
...
// el método debe empezar con la palabra “test”: public void testDepositoDebeIncrementarSaldo ( ) {
int montoDepositado = 100;
CuentaBancaria cuenta = crearCuentaValida(); int saldoPrevio = cuenta.getSaldo();
&' *# ()
assertEquals("El depósito funcionó mal",
saldoPrevio + montoDepositado, cuenta.getSaldo() ); }
... }
" O9 ( =
public class PruebaCuentaBancaria {
...
@Test
public void depositoDebeIncrementarSaldo ( ) { int montoDepositado = 100;
CuentaBancaria cuenta = crearCuentaValida(); int saldoPrevio = cuenta.getSaldo();
cuenta.depositar(montoDepositado);
assertEquals("El depósito funcionó mal",
saldoPrevio + montoDepositado, cuenta.getSaldo() ); }
... }
! " . "
' D #:, ! ' B ! .
O9 ( Q 8 #,
! " ! " " D ! 0" "
,
& ! " O9 =
assertEquals (x, y);
" D B =
assertThat (x, equalTo (y) );
< ! " " 3 " ! . ' 0"
B 0" ' 0" "
' ! ! 0" " " ! 0" " "
" ! 0" " 3 " ! 0"
" 0" ! 3 " !
,
& B 0" " , & !
" O9 " 0" " " =
assertTrue( universidades.contains("UNLP") ||
universidades.contains("Universidad Nacional de La Plata") );
#:C " L . M! " L .M! 0" L. " M,
&' ** ()
& B 0" ' =
assertThat(universidades, or( contains("UNLP"),
contains("Universidad Nacional de La Plata") ));
" " " , & !
0" " ! 0" " " 3
" ! " =
assertThat(Math.sqrt(-1), is(notANumber()));
O9 " ! B " . "
) . -. ,
< D B ! . . " ,
Herramientas para crear dobles
' ! ! 0"
! " 8 0"
,
B . " . 8 ! ,
0" 3 . " 0"
" , 7 ! . 0" 0"
8 ' 0" "
0" , 7 0" '
' ! " "
Q 8! ! ' " O =
private void initiallyLoads(Object value) { checking(new Expectations() {{
oneOf (clock).time(); will(returnValue(loadTime)); oneOf (loader).load(KEY); will(returnValue(value)); }});
}
private void cacheHasNotExpired() { checking(new Expectations() {{
oneOf (clock).time(); will(returnValue(fetchTime));
allowing (reloadPolicy).shouldReload(loadTime, fetchTime); will(returnValue(false));
}}); }
&" 0" 0" ! , 7
0" " O " 0"/ . !
,
Herramientas que ponen el énfasis en BDD y STDD
B " . . 0" " "
0" , " .
&' *( ()
7 " ! J%(K! . 0" " " ,
! 0" 0" . 0" 0" "
0" ! 0" . 0" " =
! ! " ,
Herramientas para pruebas de interacción
B " . . " / " " ,
D . % J%(K, 7 " '
" ! D . / , & / 3 ! " "
" 0" " " ,
& " " ! . . D = . " . 0" "
, 2 " " 8! /
" ,
" . " " "
" , < ! "
= 0" " " ,
0" ! " ! " 0" 0" " ! 0"
3 ,
<. ! " " " . !
. " , & 0" H 8 J:K 8
" . < ,
Algunas herramientas específicas
" 0" . 0" . " !
" ' , ! " " " ' ,
Herramienta Tipo de
TDD Estrategia de prueba Formato pruebas Se accede a través de Observaciones
Fit ATDD y
STDD
Scripted Test
Tablas API, con ayuda de código de vinculación desarrollad o por programad or
Desarrollado por Ward Cunningham. Bueno para resultados calculables, los flujos se pueden construir con la API FitLibrary, aunque complica una herramienta sencilla.
FitNesse ATDD y
STDD Scripted Test Tablas en wiki API con ayuda de código de vinculación desarrollad o por programad or
&' *4 ()
Herramienta Tipo de
TDD Estrategia de prueba Formato pruebas Se accede a través de Observaciones
JBehave BDD y
STDD Scripted Test Texto con plantilla de user story
API Primera herramienta de BDD para Java. Es una extensión de JUnit. Corre bien en conjunto con IDEs. Muy amigable para desarrolladores. No requiere código para vincular
especificaciones con pruebas. Menos amigable para perfiles no técnicos.
RSpec BDD y
STDD Scripted Test Texto con plantilla de user story
API Primera herramienta de BDD para Ruby, muy similar en pros y contras a JBehave
Concordion BDD y
STDD Scripted Test Texto libre en HTML API, mediante código de vinculación entre pruebas y especificaci ón
Es una extensión de JUnit. Corre bien en conjunto con IDEs. Muy amigable para desarrolladores. Relativamente amigable para perfiles no técnicos. Hay versiones para .NET, Ruby y Python.
TextTest ATDD y
STDD Scripted Test Texto en una interfaz gráfica
GUI o API Especial para probar workflows y regresiones. Para cualquier lenguaje.
easyb BDD Scripted
Test
Texto con plantilla de user story
API Basado en Groovy
Cucumber BDD Scripted
Test
Texto con plantilla de user story
API Basado en Ruby y RSpec, tiene una extensión para Java llamada Cuke4Duke
Selenium Interacción Recorded
Test Editable en varios lenguajes de programaci ón Interfaz web
Para aplicaciones web
CubicTest Interacción Recorded
Test Editable en formato gráfico Interfaz web Usa Selenium
StoryTestIQ Interacción Recorded
Test Editable en formato wiki Interfaz web Usa Selenium
HttpUnit Interacción Scripted
Test
Texto Interfaz web
TDD y enfoques metodológicos
" 0" 0" ;&! D ,
! . " ! " " . " 0" .
. / " ,
9 " " " - 0"
-, & " " ! " ' ! " " "
' ! 0" , &
! 0" / !
-" " . !
&' *) ()
<. ! T "' 0" U 7 0" . " . ,
! ,
J%4K . 0" / L - " . M,
! " " ! " ,
" 0" 0" " . 3 , @
" ! " " ,
0" > ! " 0" / = 0"/! " 0"
, @ ! D . " " " J:K,
@ J%?K ! . < 9 ! "
" 0" " " , /
" " " J%?K,
7 " 0" 0" / 0" " 0"
! " ' " / ' ! 0" " "
0" - " ! ,
9 " - " 0" Q J%(K
, 0 ! " . " " 0"
, 7 D - 0" Q " 0" #
J%(K ' ' > ! " >
0" 0" " " "
, & " 0" "
-J%6K,
7 < J#)! #6 #?K ' I ! " 0"
' " , 7
0" " , < " ! " " "
I ! 0" ! " 0"
! " " , I
0" " " " '
" 0" ! 0"
,
I " " " !
" ! 0" " 9 !
. . ' "
-" -" ,
" " " " ,
0" D 0" ' ! >
" " ! " @ & J%?K
" 9 ' , " "
0" "/ ! " " , & " " ! " 0" ' !
0" . " ,
Q J%(K " 0" $ 0" . "
! . " " 0" " !
" " ,
Q" . . . . " " " ,
&' *6 ()
" " " , & "
' ! " " ,
" " " !
! " " ,
! D " = ! > F "
9 @ " - G! '
W ! " " " ,
" / " " 0" . 0"
D ,
Estudios del uso de TDD en la práctica
Validez de los estudios sobre UTDD
. . ! " " / "
9 , & ! D " . " 9
" , ! ! 0" ' ' H
> 8! #$$# J#K! 0" . " !
" " ,
7 ! , " ! 0" " 0" .
. . , & !
0" ! " !
' 3 ' ! " " 0" " ' ,
& " " ! 0"
" , B "
0" D " " !
" " D W
" " , & !
" ! " ! ! "
,
" " ! . " 0" . ! !
" 3 =
! " . " " ,
9 0" ! " "
" , " . . ,
! " D 0" " '
0" " , 2 0"
0" ' " " ,
1 0" "
! " ' " ' ! D
" , . . ! " " "
" D 0" . "
" , & . 0" . ! ! 0"/
" " " 0" . "
" ,
& ! " 0" " 0"
" ! ! " , @ !
" . ! " , < !
&' *? ()
D L 0" - M! 0" '
D , & . . . !
' ,
Trabajos que fueron analizados
7 ' 0" . . =
• " " " J#:K! 0" D " "
" 0" " (? 0" D
' ,
• 9 " ( " " ! >Q Q !
" " ' ' , 9 0"
' J*$K,
• 9 D " - !
0" " " " !
' 4 - D
O ! 0" " J*%K,
• D " O Q J**K,
• 9 0" ! " " "
;& ! " 0"
-" ' . 0" " J*(K,
• 2 . " #$ 0" . " ! 0"
,
Conclusiones extraídas de la evidencia analizada
7 " " " =
• " D ! /
" " 0" " " 0"
! . " ($N :$N,
/ . " " 0" ! ' "
%?N 3 J*$K,
• " ! . " ! %4N
*4N! " 0" " " "
" = ' D 0" '
" ! ! 0" 0" " " ,
B 0" ! !
" ! " ' , 2 "
0" " ! 0"
- , & " " ! ' ,
• " 0" . 0" " !
! / " " ,
" 0" . ! ! 0" "
/ - ! " - ! "
" ! . - = "/
,
• " " "
" ! "
&' *: ()
• " "
,
• " ! J*(K . - !
. " " - " ,
B / " 0" ,
=
• 0" " . . "
0" . " ,
• 7 " !
"
' " " ' " ,
• " " . ! ." ! ! .
! " ' ,
• 7 " 0" "
0" " , " " !
" 0" . ,
• . ! "
. " " !
" 0"
0" ' , A" ' . . 0"
" " 0" . !
" " , 7 D
! "
J*)K 0" F " G ($
' 0" ,
< ! . " 0" ! . !
" , & =
• E " " ! .
" " ! 0" ,
' " " 0" /
" " ! 0"
, " ! ! "
,
• 7 D ! " 0"
" " 0" ! . "
" 0" ! " 0"
! " " 0" '
,
• @ . " .
" ,
• " . D ! '
! " - !
0" " ' ,
Estudios sobre variantes de TDD más allá de UTDD
. D 9 ! .
&' ($ ()
" 0" . " & 8 Q " J*6K! 0"
0" . " F #$$:G . 3 "
' " , 0"/
" ! (: " ,
7 ' =
• E ! " " 0" "
" ! " 0" / . " 0" 0"
" " , 7 0" " 0"
" " ,
• E ! ' ! "
/ 0" !
" ! 0"
,
• " " ! 0" "
" ! . . / 0" " "
! " ,
• " " ! . "
" 0" , ! 0"
. "
0" ,
• Q" . " . "
" ! 0" . 0" 0" ,
• " 3 . " ! "
" ! . " !
. " ,
• ,
" . 0" " " " !
! " " ! ,
• Q" . " . - ! " "
0" " ' !
,
Limitaciones de TDD y prácticas afines
" 0" ' ! " , & ! "
" " " 0" " " =
• & " " ! 0"
. " " , 7 0" " 0" ! . "
" ! .
0" , "
" ' " " ! " "
,
• & - " " " ! " " . . .
. . " ! ' , & " " ! !
" 0" " 0" ' ,
• & , / "
! " " . " " .
&' (% ()
" , D . " "
,
• & " " , <" " " " 0" "
" " ! . " !
!
" & 3 ! ! ,! 0"
0" "
,
B " ,
"
-F> 9 *$! H > 8 J%KG! "
! 0" " - ! " 0" , <
D " " ,
D " . ' . 9 0" ! ' 0"
' ' " , " " ! "
= . ,
" 9 " " " "
' ! " " . . 0" " " 0"
" %$$N " , " 0" 9
. , A" ' 'D H > 8 J%K!
L 0" 0" " 0" " M, ! " /
0" " " FL M L MG! " " ,
" " ' " ,
7 " 0" " " " " D
0" " " , 7 0" . 0" . 0" ! " 0" " ' ! "
." ! " " , 1 !
0" " " " ! /
' ,
Prácticas relacionadas con TDD
Refactoring
E " / . " ;& 0"
"/ ! " ,
! ! " / - ,
9 - "/ "
" ! 0" " . . "
" - ,
7 " " 0" " / " " 1 8 O .
J*?K,
7 =
• " " " . 0" "
D ! " - 0" " 0" " .
" " " 3 0" " ,
*$
&' (# ()
• 7 " D D " " '
! 0" 0" D
" 0" ,
7 ' ! . ! , <
!
" - ,
< ' " ! " " , &
! " 0" " "
-! " / 0" - ,
! 0"
" = 0" . " F
" G! 0" / . ,
<. ! " . - !
. " , T 0" " " '
- U 2 ! T0"/ 0"
" " U
>" ! " ! " , "
" ! 0" ! " ' ' "
0" ! ' ' " "
-" ,
! 0" ! 0" "
! 0" " > ! < , 7 " '
" 0" , 7
" ! " "
-! 0" , 2 3 " !
" " ! ,
' ', " !
/ " ! " " , & ! T "'
" " U " ! "
" , ! " ' 0"
" " " ! 0" D !
" " " ! ,
Debugging
" " / 0" " "
, !
" " " ,
7 " = '
" D " " 0" . ,
. . ! " ! 3 "
" " " " D ,
& D 'D 0" ! " " !
" " 0" ! / ,
! 0" " " " D !
&' (* ()
! = 0"
" ,
3 " 0" .
= " ! " ' " ! "
" ." , < ! " 0"
" 0" ! " 0" ." ! " ,
Integración continua
7 " " ' " > 8 ;& J%K " " "
J*:K, " ! " "
! ! " " "
! " 3 ! , D
" . . ! ! ' ! 0"
' ,
7 " " =
. " " ,
Conclusiones
" & J%?K! 0" L " / 0"
" ! - " 3 . M! 0" "
,
7 0" ! " 3 & J%?K! =
• 0" ,
• < . ' !
,
• @ " " 0" . ,
• @ " " ,
• D ' " ,
• @ "' ! "
,
<. ! . " . , 9 ' - !
. 0" " " " 0" ,
> - ! ' . 0"
/ , @ " 0" ,
7 0" " 0" . = " ! 0"
! D ! 0" " " , 9 @ "
! 0" > " D ,
! ! D " / 0" " D
, 7 . " ! 0" D
" . " 3 , < ! 9 ! .
" " !
0" !
. " " ,
9 " " ' " " 0" "
0" " *%=
*%
&' (( ()
Tipo de
prueba Técnica de TDD relacionada Pregunta que responde Observaciones
Aceptación STDD, ATDD, BDD
¿Funciona el sistema de acuerdo a los requerimientos?
No debe pecar por defecto ni por exceso respecto de los requerimientos
Integración NDD ¿Cada parte del sistema interactúa correctamente con las demás partes?
Tiene que ver con el bajo acoplamiento y las interfaces entre módulos
Unitarias UTDD ¿Las clases hacen lo que deben hacer y es conveniente trabajar con ellas?
&' (4 ()
Bibliografía y referencias
J%K H > 8! L D & D = . M! < I
& ! %:::,
J#K H > 8! L = > D M! < I & ! #$$#,
J*K @ .! LI. X M! . =VV , ., V . V!
" #$%%,
J(K @ .! L " > M! . =VV , ., V " V!
" #$%%,
J4K @ .! L " > M! > ! #$$)! J(K,
J)K ! L = 8 D . B M!
< I & ! #$$*,
J6K < R ! L > E . UM! . =VV . , V#$$6V$?V#?V
. V! " #$%%,
J?K > Q ! L U U YM!
. =VV , , V V " V#$$(V ,. ! " #$%%,
J:K E 8 Q" I " . ! L = 8
M! & B ! #$$4,
J%$K 7 H 8 ! L = < O M! Q
&" ! #$$6,
J%%K F3 " G! L& 1 M!
. =VV , , V V " V 8 V& 1 ! " #$%%,
J%#K 8 &, > 8 O ,! L . Q . Q Q .= !
< F# GM! < I & ! %::4,
J%*K R 8 < ! L> . " R , D
M! @ " ! #$$:,
J%(K R Q ! LD9 & M! < I & ! #$$6,
/ . =VVD" , V " #$%%,
J%4K Q ! LQ 8 < X " M!
. =VV , V V 8 < " ,. ! " #$%%,
J%)K ! Q 8 ! @ & ! O I ! LQ 8 E ! @ 1 M!
11& 7< #$$(! C " ! ',
J%6K 8 < " ! Q 8 ! O . " ! L O# & ! = > & ! & B ! #$$*,
J%?K ! @ & ! LR 1 1 ! R" M!
< I & ! #$%$,
J%:K , R " ! R Q, I ! L D E 0" = A" >
M! B " ! %:?:,
J#$K > Q 8! L> " 1 M!. =VV , D , V V V 8
" , ! " #$%%,
J#%K > Q 8! L D . " . D M! . =VV , D , V
V#$$*V$?V#%V! " #$%%,
J##K ! @ & ! Q 8 ! O I ! LQ 8 E ! 1 M!
11& 7< #$$(! / . =VV , 8, V #$$), "
#$%%,
J#*K ! @ & ! L 7 " O M!
11& 7< #$$)! / . =VV , 8, V #$$), "
&' () ()
J#(K E 8 Q" ! LQ < & E 0" .
M! #4! )? 64 F#$$?G,
J#4K R Q ! E . > . ! O < ! L< E 9 E
Z & 8M! 11& 7< #$$*,
J#)K O" >" ! R" E ! E 7" ! O" ' R ! L .
@ E 0" . > I < .M!
& . . %% . < !
C ! 7@ ! #$%$,
J#6K E 7" ! R ! R" E ! L " C
& E 0" I < M! & . % I 8 . .
I E 0" FI E #$%$G,
J#?K E 7" ! O" >" ! O" ' R ! R" E ! L< D "
. < I < M! & .
< QV *# F #$%$G,
J#:K < " ! " 8! 8" &" 88 ! L 7 "
< M! !
C C ! > ! R ! /
. =VV , , ., V D, . U . [ " Z [#*)6 " #$%%,
J*$K @ . @ ! Q . Q D ! . " . >. ! 7 " I !
LE A" . " . = E " D
" " M! O " ! C " %*! @" *! O" !
#$$?! #?: *$#! \ >" Q ! 77 #$$?! /
. =VV ., , V " V " V V 5 , " #$%%,
J*%K R ! < ! / D R ! Q & ! < C !
L " < = D .
& M! $) & . #$$) < QV "
,
J*#K . ! L " F > . GM!
. =VV , , V < , D " #$%%,
J**K & 88 < . ! < B . ! O". O]] ! L >" <
. " . . " = < " Q
M! & & ! #$$4! C "
%?$V#$$4! ##6 #(*! 1 = %$,%$$6V$ *?6 #44:$ 65%(! / . =VV ,
, V " V V < <R 7 #,65 %,$, " #$%%,
J*(K 7 S. ! ." "8 <8 " ! H " H ! " . Q 8 ! L >
I & M! D
& < & ! 6 . ! ;&
#$$)! 1" "! ! " #$$),
J*4K . ! L & M! . S ! #$$%,
J*)K I B" . ! LQ . & M! < I ! %:?:,
J*6K . & 8! 8 Q " ! L< 7 " E M!
" ! 9 ! 7 " @ >"
& ! #$%$! C " (?! & #! #$? #%*! 1 = %$,%$$6V:6? * )(# %*$4( $5#$!
C ! /
. =VV , ," , V" V&" V& 8Q " ;&#$%$, " #$%%,
J*?K I , 1 8 ! E . , O . ! LE = < < <
8 1 1 M! & . " 1
1 & . & < F 11&&<G! %::$!
< Q,
J*:K Q ! L " " M!