En este video, voy a mostrarle cómo
crear un paquete, una clase, y describir tests.
La primera cosa a hacer es abrir el system browser.
El system browser permite navegar paquetes.
Aqui estan los paquetes.
La primera cosa a hacer es crear un paquete.
Vamos a cliquear en “Add package”, "MyCounter".
Como hay muchos packages y no queremos
siempre verlos, es bueno filtrarlos.
Tenemos nuestro package "MyCounter".
Y ahi, definimos una classe que llamamos
"Counter" y tiene una variable de instancia “count”.
El pequeño ícono naranja significa que el código no ha sido guardado.
Aqui, compilamos el código con la acción "Accept".
Y aqui, la clase "Counter" ha sido compilada.
el sistema busca un poco y dice que hay
buenos comentarios. Vamos a ver esto luego. Por el momento, no nos interesa.
Hay un signo de exclamación en rojo porque no hemos escrito
un comentario. Entonces, vamos primero a escribir
el commentario:
"Soy un simple contador…”
Vamos a escribir un pequeño ejemplo para que el lector entienda
como funcionará: Counter new,
Counter increment, increment, Counter
count. Aqui debe ser igual a 2.
De nuevo, el texto no ha sido guardado y vamos a compilarlo.
Ha sido guardado. Ya no tenemos contador.
Ahora, vamos a definir accessors.
Generalmente ponemos accessors in el protocolo "accessing".
Escribimos: "count retorna count".
Y de la misma manera, escribimos
aNumber, hacemos un setter.
Ves, modifiqué el método count.
Puedes pensar que lo hemos perdido, pero no, porque
cada vez que cambio un método usando un nombre diferente,
crea un nuevo método.
Compilo el nuevo método, y tengo "count".
Ahora, realmente queremos probar y escribir nuestro primer pequeño programa.
Abro un Playground.
Creo un contador, voy a otra línea.
Pongo un valor:
C count 7. Si pregunto por su valor, ¿Qué va a
retornar? Retornará 7.
Ahora, lo que realmente nos gustaría escribir
es un test porque así no podemos ejecutarlo
y nos gustaría ejecutarlo automáticamente.
Creamos una clase de test.
Cómo creamos una clase de test en Pharo?
Cambiamos la super clase, decimos que hereda de
TestCase y definimos una clase de test
llamada CounterTest.
Ahora, voy a compilarla.
Tengo una nueva clase CounterTest en mi sistema.
Voy a definir un nuevo método, voy a agregar
un protocolo llamado tests.
Allí puedo definir un nuevo método.
Los métodos de test deben siempre empezar por "test"
y estar en una clase que hereda de TestCase.
Vamos a llamarlo "testCounterisSetAndRead"
for ejemplo. Casi tenemos nuestro test. Ya tenemos
casi todo escrito.
Vamos a indentarlo un poco mejor.
Creo mi contador.
Y ahora, escribo "self assert
equals 7". Esta oración es
estrictamente equivalente a "self assert C count equals 7".
Es mas conveniente, cuando te equivocas
el retorno es más inteligente cuando usas la primera oración.
Compilamos.
Ahora, puedo ejecutar mi test,
mi test esta en verde. Cuando tienes un test y esta en verde,
es el momento correcto de guardar tu producción, tu código.
En Pharo, puedes guardar la imagen.
Aqui, esto es lo que hago, voy a salvar la imagen, pero la imagen
no es satisfactoria..
Me gustaría mostrarte como puedes salvar código
en un sistema de versionado.
Aqui, como todavía no se si vas a tener un acceso a internet,
voy a hacerlo en mi cache local.
Ves, tengo este directorio apuntando hacia
todos estos paquetes en los que puedo trabajar
los tenga cargados o no.
Allí, el sistema nos muestra que
varios paquetes con modificaciones no ha sido salvados.
No nos importan los primeros 2, pero vemos que
MyPackage tiene una estrella. Eso significa que hay código en
la imágen que no ha sido salvado.
Aqui es lo que voy a hacer: vamos a hacer Save,
elijo el repositorio.
cliqueo en save.
Escribo "primera version con accessors y un
test en verde".
Acepto. Ahora ha sido guardado un paquete.
Voy a chequear.
Puedo abrir este directorio. Si miro, contiene
muchos paquetes que han sido cargados por el sistema.
Pero en particular, si filtro, encuentro
mi paquete con sus versiones.
Te recomiendo guardar, cada vez que agregas
nueva funcionalidad, y eso es lo que vamos a hacer.
Ahora vamos a definir
un test antes de implementarlo.
Vamos a escribir un test para ver cual es el incremento
de un
contador. "TestIncrement" ¿Qué queremos obtener?
Queremos decir “Creo
un contador,
le asigno un valor por defecto,
luego incremento dos veces este contador.
“¿Qué debo chequear?”
Debo chequear que el contador
tiene el valor correcto.
Compilo. Mi test
esta en rojo porque no implementé counter.
Las operaciones en counter incrementar y decrementar.
Agrego "operations increment".
¿Qué hacemos?
Hacemos "self count 2: self count +
1". Si usamos sistematicamente accessors
internamente o no, depende, es una cuestión de estilo.
De la misma manera, ya que esta muy cerca,
vamos a definir "decrement".
viste que para increment, hay un test así que puedo
ejecutarlo y mi test esta en verde.
Así que tengo 2 test que funcionan bien.
Si voy a mi clase de test, todos mis tests estan en verde.
¿Qué voy a hacer ahora?
Salvo. Voy a salvar de nuevo.
Voy a escribir "Agregado incrementar y decrementar".
Ahora si miro, tengo 2 versiones
de mi paquete.
Voy a escribir un test para "decrement"
porque no hay razón para no hacerlo.
"decrement", por ejemplo
podría atribuir el valor 2 si quiero
y decrementarlo 2 veces. Debería obtener 0.
Mi test esta verde así que
voy a salvar.
Ahora, lo que queremos es que si miro
y escribo "Counter new" y luego
"Print it", muestra un contador cuyo valor no se,
así que no es muy útil.
Nos gustaría modificar este comportamiento.
Para hacer esto, vamos a agregar un método
llamado ”PrintOn", en el protocolo Printing.
Print on es un método llamado
por el sistema cada vez que haces PrintStream.
Tiene aStream como argumento.
¿Qué hacemos?
Decimos que nos gustaría tener un contador.
Típicamente, uso las funciones de arriba.
Ahora lo que voy a hacer, me gustaría
agregar un pequeño
texto
por ejemplo "con valor" y "self count".
HAgo esto porque es un número, así que tengo que
obtener una representación textual.
Escribo "cr".
Compilo.
El sistema me dice que puedo mejorarlo, pero no importa…
Por el momento no nos interesa.
Puedo escribir "Counter new".
Miro, dice que es un contador con un valor nil.
Eso es normal porque no lo he inicializado todavía.
Ahora vamos a agregar la initialización.
Para hacer esto, empezamos escribiendo un test.
Digo: “Al momento de la creación, quiero que el valor
sea 0.
¿Qué voy a hacer?
Voy a escribir “self assert”
Chequeo que "Counter new
count = 0".
Ahí, ¿De qué nos damos cuenta?
Mi test es falso. ¿Por qué?
Porque si hago esto, obtengo nil.
Como es una clase y no tengo acceso a
las variables de instancia de la clase CounterTest,
puedo seleccionar la expresión y ejecutarla directamente.
Una vez que tengo este test que no es válido,
¿Qué debo hacer?
Voy a agregar un método initialize en el protocolo initialisation.
¿Y allí qué hago?
Escribo "super initialize", y voy a
decir "count 2 points = 0".
Este método es usado cada vez que uso el método “new”.
Ahora puedo mirar mis tests, es verde.
De la misma manera, si escribo "count", obtengo 0.
Una vez mas, vamos a salvar: "agregado printOn"
"agregado initialize + tests".
Ahora lo que es interesante es que
puedo ver toda mi historia.
Puedo ver y navegar la historia.
Si cliqueo en "versión", puedo ver la diferencia entre estos 2 sistemas.
Cambios entre la versión 3 y la versión 4
son ”initialize" "printOn" y el test.
Si quiero la diferencia entre
la versión 2 y la versión 4,
tengo todos estos cambios.
Ahora, nos queda una cosa por hacer, me gustaría
cambiar un poco la manera en que los objetos son creados.
Empiezo creando un test que va a clarificar
que quiero obtener. Voy a definir un test
llamado "AlternateClassCreation".
¿Qué queremos obtener?
Digamos que quiero estar seguro que
Counter withValue: 19
Si hago increment en él
y pregunto por su valor, debe retornar 20,
Ok.
Hagamos un paréntesis aqui, es mejor.
Así que, una vez más, el test falla,
y el asistente me dice: "envias un mensaje desconocido".
Debes darte cuenta que el mensaje withValue
no esta siendo enviado a un objeto, sino a una clase.
Esto quiere decir que tengo que definir este mensaje
en la clase. Así que selecciono la clase.
Ahora voy al nivel de clase y agrego
un protocolo llamado creación de instancias
withValue: aNumber ¿Qué debo hacer?
La primera cosa a hacer es
crear un contador, una variable contador,
contador, lo hago lentamente,
self new Así creo un contador
y escribo self count: aNumber
Y retorno este contador.
Podemos hacerlo de una manera más corta
pero por el momento vamos a hacerlo simplemente.
Compilo mi método.
Y ahora significa que puedo enviar mensajes.
Ves, cuando cliqueo en este botón,
voy al nivel de clase. Voy desde el nivel de clase
al nivel de instancia.
Aqui estaba en el nivel de clase y aqui vuelvo a los
mensajes enviados a instancias.
¿Qué significa esto? Significa que si hago
Counter withValue: 18, ¿Qué obtendré?
Obtendré una instancia de la clase Counter.
Obtengo un contador con valor 18.
Y ahi puedo hacer decrement.
Si refresco, obtengo 17.
Ahora si miro mi test,
todos mis tests estan bien, así que voy una vez más
a salvar y listo.
Agregada API de creación de instancias y tests.
Listo por ahora.