BDD en Objective-C. Primeras impresiones usando KIWI en xCode

bdd Desde hace un par de
semanas vengo probando y usando una librería para hacer BDD
con un proyecto para el iPad. Eso conlleva usar Objective-C y el
entorno de desarrollo xCode. Lo
primero y principal es pedir disculpas por mi atrevimiento, nunca
antes había programado en Objective-C, ni usado xCode y tampoco
anteriormente había hecho proyectos usando BDD,
así que me adentro en un mundo completamente desconocido para mi.
Mi objetivo con este post es conseguir que tú tambien te animes a
salir de la zona de confort y a disfrutar de nuevo conocimiento.
Vamos al lio.

Conceptos

Para ir abreviando, xCode es el
entorno por defecto de programación para Mac y el lenguaje para
programar aplicaciones para iPhone, iPad y Mac es Objective-C que
no es más que una extensión de C++. Así que si habéis programado en
C++ antes y usado algún IDE como Visual Studio. Netbeans o
Eclipse, esto es más de lo mismo. Tendréis que aprender las
características del entorno y para ello os aconsejo el tutorial
de la sección de desarrolladores de Apple.
BDD:
este es un concepto que me encanta, había usado TDD
antes en proyectos pequeños (podéis ver algunos en mi cuenta de
GitHub
) y ya me gustó desde el principio. TDD
es (Test Driven Development = Diseño dirigido por pruebas) deciros
que una técnica de programación que se basa en escribir las pruebas
antes que el código y que sean estas el motor del diseño de la
aplicación. Hay muchos recursos sobre TDD mis favoritos son el libro de
Carlos Blé “Diseño Ágil con TDD”
, con el que yo aprendí
qué es y cómo se aplica TDD,
y también el fantastico Blog de Javier
Gutierrez
y su
libro
al que además tengo mucho que agradecer porque me
ha ayudado directamente en este proyecto resolviendo dudas y dando
consejos. BDD
es una evolución de TDD,
cuyo objetivo no es más (ni menos) que acercar el lenguaje de TDD
a algo más natural, algo que cualquiera pueda entender y que
permite que las pruebas se expliquen por si mismas y ya que son el
motor del diseño del código sirvan como medio de comunicación entre
las partes implicadas en el proyecto. Podéis ver en el blog de Dan North
las razones de BDD
. Para mi es mucho más claro y útil BDD
que TDD, aunque para un programador o artesano del software, quizás
es más intuitivo empezar con TDD
y luego digi-evolucionar a BDD.
Yo aconsejo a cualquiera que programe que intente aplicar estos
conceptos en su día a día, pero con racionalidad, cogiéndolo poco a
poco, primero proyectos o katas pequeñas
para familiarizarse con el lenguaje y la terminología,
así como de las técnicas y pasos que hay que dar para aplicar el
proceso completo. Al principio sorprende un poco y puede que no se
le vea la utilidad, pero la tiene, tanto en proyecto grandes como
pequeños. De verdad si queréis programar con calidad, optimizar
vuestro tiempo de desarrollo y construir proyectos de futuro,
tenéis que aprender estos conceptos. No os conformeis. Por resumir
muchísimo, BDD transforma las historias
de usuario
en código, así podemos expresar ideas como:

Historia: Conducir
un coche Para poder conducir un coche
Como conductor
Quiero poder arrancar el coche
Y acelerar
Y frenar
Y girar a derecha e izquierda
Y parar el coche

Esa es nuestra historia y cada bloque
Y indica un contexto o situación que
tenemos que modelar:

Situación
1:
Quiero poder arrancar el coche
Dado un coche
Cuando me monto en el coche
Entonces quiero arrancarlo

Situación 2: Acelerar
Dado un coche arrancado
Cuando presiono el acelerador
Quiero que la velocidad aumente

Situación 3: Frenar
Dado un coche arrancado
Cuando presiono el freno
Quiero que la velocidad disminuya si
no es 0
Situación 4: Girar
a derecha e izquierda Dado un coche
arrancado y con una velocidad mayor que 0
Cuando giro el volante a derecha o
izquierda Quiero que la posición del
coche se modifique girando en la dirección
indicada

Si queréis ver un
ejemplo más orientado a estructuras de datos
, en el blog
de Dave Meehan tenéis uno igual con la historia de una Pila.

Kiwi en xCode

Ahora viene lo complicado. Sí,
vale, genial, esta forma de definir un problema está muy bien, es
estructurada y la entiende todo el mundo, pero ¿cómo pasamos esto a
código? ¿Cómo hacemos para comprobar que nuestro código hace lo que
esperamos según nuestra historia?. Para aplicar BDD, hay muchas
plataformas y entornos que permite aplicarlo en distintos
lenguajes, el más extendido es Cucumber que soporta muchos
lenguajes, y también está JBehave que funciona sobre Java. Cuando
me embarqué en este proyecto no sabía mucho ni sobre BDD,
ni sobre Objective-C y como el objetivo era una aplicación para el
iPad, busqué un poco por internet y descubrí una librería que ahora
os presento Kiwi. Con Kiwi conseguiremos pasar del texto anterior a
una estructura compilable de este estilo: #import
"Kiwi.h" SPEC_BEGIN(CocheSpecs) describe(@"Con un coche", ^{

context(@"cuando nos montamos en un
coche", ^{

pending(@"el coche debe poder
arrancarse", ^{

});

});

context(@"con un coche arrancado",
^{

pending(@"el coche
debe poder acelerarse", ^{

}); pending(@"el coche debe poder
frenarse", ^{

});

});

context(@"Cuando el coche se mueve",
^{

pending(@"el coche
debe poder girar a la derecha", ^{

}); pending(@"el coche debe poder
girar a la izquierda", ^{

});

});

}); SPEC_END
Kiwi es simplemente eso, una librería que permite
pasar los escenarios de BDD a pruebas con las que ir construyendo
nuestro software. Comparándolo con el esquema anterior Kiwi nos
permite pasar de: Historia ….

Escenario
….

Dado
Cuando
Quiero ….

A
Describe ….

Context
….

it
….

Sí, en realidad la sintaxis para un test es
it, el token pending
permite definir un test sin que se ejecute. Lo bueno de usar
pending es que nos permite hacer en un proceso
completo, pasar de nuestras historias de usuario a código sin tener
que mantener una bitácora o agenda como en otros casos (la podéis
ver en mis katas de
TDD
). Es una de las cosas que más me ha gustado de Kiwi,
porque me permite tener toda la información del proyecto de una
forma explícita y dentro del IDE. La instalación
de Kiwi
es un poco larga y liosa, descargad todo lo
necesario y seguid los pasos al pie de la letra. Yo tuve algunos
problema al no cerrar xCode cuando generas los archivos de Kiwi y
por seguir estas
instrucciones
(que corresponden a una versión
anterior) en vez de éstas
que son las correctas para la última versión
. Después de
probar el código de prueba y ver que todo está correcto podéis
empezar a usar Kiwi en vuestros proyectos con iOS

Describe y Context

La ventaja de la estructura
de bloques de Kiwi, es que puedes generar estados comunes para
todas las pruebas de un bloque (ya sea un describe o un context),
es una forma de añadir granularidad a los setting up de los test.
Así puedes añadir al código las lineas necesarias para inicializar
los contextos según necesites. Además se pueden definir nuevos
contextos anidados (dentro de otros contextos) si fuera necesario.
describe(@"Con un coche", ^{

Coche *coche = nil; context(@"cuando
nos montamos en un coche", ^{

beforeEach(^{

coche = [[Coche alloc]
init];

});

afterEach(^{

coche = nil;

}); it(@"el coche debe existir",
^{

[coche
shouldNotBeNil];

});

it(@"el coche debe poder arrancarse",
^{

[coche arrancar];
[[[coche esta_arrancado] should] beYes];

});

});

}); Aquí
se pueden ver varias cosas:

  • Hemos cambiado
    pending por it que es la
    palabra correcta para lanzar los test. Estos test serán evaluados,
    mientras que los que tengan pending aparecerán
    siempre en verde con la palabra
    Pending al final para indicar que
    están por definir.
  • Tenemos bloques
    beforeEach y afterEach
    que definen comportamiento y cambio de estados antes y después de
    cada test. Sólo se aplicarán en el nivel que estén definidos, en
    este caso el contexto “cuando nos montamos en un
    coche”
    .
  • Tenemos la estructura de
    los test de Kiwi: [sujeto should] be_loquesea,
    que es una forma muy intuitiva de “resultado de la operación”
    debería “ser 43”. Hay que tener muy en cuenta que en Kiwi sólo
    se comparan objetos, así que si queremos comparar valores
    reales, enteros o booleanos deberemos encerrarlos en un objeto,
    cosa que Kiwi permite hacer de forma muy sencilla con la función
    “theValue”

context(@"con un
coche arrancado", ^{

beforeAll(^{

coche = [[Coche alloc]
init];

});

it@"Si el coche tiene de
velocidad 10 y se acelera en 20 la velocidad final ha de ser 30],
^{

[coche
velocidad:10]; [coche acelerar:20]; [[theValue([coche velocidad])
should] equal:theValue(30)];

});

it@"Si el coche tiene de velocidad 30
y se frena en 10 la velocidad final ha de ser 20], ^{

[coche velocidad:30]; [coche
frenar:10]; [[theValue([coche velocidad]) should]
equal:theValue(20)];

});

});

Conclusiones

Para aplicar BDD (que es más que
recomendable) en un proyecto de iOS, os recomiendo que uséis Kiwi,
es fácil de usar, intuitiva y cubre todos los objetivos que
necesita BDD. Sin tener conocimientos previos de Objective-C no me
ha costado mucho ni instalarla, ni usarla, ni aplicarla en un
proyecto real. Hay cosas que me han gustado mucho, como lo fácil que
es empezar a usarlo, y el uso de la sentencia
pending para poder diferir la definición de un
test pero pudiendo pasar todas tus notas a código. Sin duda Kiwi
ayuda mucho en la adopción de BDD o en la evolución desde TDD. Yo
me he comprado el libro
para iPad de Kiwi
que es muy completo y merece la pena
como material de referencia. Habiendo probado BDD me parece que aún
sólo siendo un cambio de expresividad aporta mucho tanto en la
concepción del proyecto como en el mantenimiento o comunicación
futura. Si os dais cuenta en este ejemplo ficticio de los coches no
hemos escrito ni una linea de código de la aplicación, pero al
tener que definir los test, darle nombres explicativos y pensar en
cómo vamos a llamar a las funciones y con qué parámetros, nos hemos
preparado para poder escribir el código que cumpla con nuestros
test y tomado decisiones de diseño (nombre de las clases, funciones
necesarias, parámetros). Además si en un futuro necesitáis cambiar
el código de las clases o la relación entre ambas o cualquier cosa,
tenéis los test preparados para que sea cual sea el cambio que
hagáis o bien mantendrá todos los test en verde (poco probable) o
estos os indicarán de forma sencilla, explicativa y comprensible
qué parte del código ha cambiado de comportamiento y en qué medida.
Esa es la potencia y objetivo de BDD, ayudarnos a desarrollar
código de calidad, fácil de mantener y fácil de cambiar o extender.
Espero no haberos cansado mucho y tampoco haberme quedado corto.
Ojalá os sirva mi experiencia para hacer mejores programas y
continuar aprendiendo, como dice el incombustible Angel Medinilla
KAIZEN!!!
Referencias: Para mi proyecto yo he usado las siguiente
referencias:

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s