Prácticas
Las siguientes prácticas presentan la forma de trabajar con Eclipse y Counterclockwise.
Práctica 01
Se darán los pasos requeridos para la creación de un proyecto en Clojure usando a Counterclockwise en Eclipse.
Accede a File > New > Clojure project y en la ventana New Clojure project, rellena los campos en base a la siguiente información:
- Project name: practica01
- Create in:
C:\plf\clojure\proyectos
- Leiningen template: default
Al finalizar, obtendrás el proyecto practica01 en la vista Package Explorer de Eclipse:
Observaciones:
- El archivo
core.clj
ya tiene código de Clojure. - El nodo Leiningen dependencies lista los paquetes de Java (extensión jar) que se están usando para este proyecto, uno de ellos es Clojure 1.6.0.
- El archivo
project.clj
es el archivo de configuración de este proyecto.
El contenido de
project.clj
en este momento es:(defproject practica01 "0.1.0-SNAPSHOT" :description "FIXME: write description" :url "http://example.com/FIXME" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :dependencies [[org.clojure/clojure "1.6.0"]])
Como se puede observar en el archivo
project.clj
se indica el uso de la versión de Clojure, 1.6.0. En estos momentos la versión más reciente de Clojure es la 1.9.0.Para hacer uso de la versión 1.9.0 de Clojure en este proyecto sustituye la cadena de carácteres
"1.6.0"
por"1.9.0"
en el archivoproject.clj
. Al momento de guardar los cambios Eclipse actualizará el nodo Leiningen dependencies.Modifica el archivo
core.clj
en la línea(ns practica01.core)
quedando de la siguiente manera:(ns practica01.core (:require [clojure.repl :as repl]) (:require [clojure.string :as str]) (:require [clojure.set :as set]))
Carga en el REPL al archivo
core.clj
dando click derecho sobre él y selecciona Clojure > Load file in REPL:Lo anterior abrirá la vista REPL y podrás ingresar lo siguiente en él:
(foo "Hey!")
Para evaluar el anterior código aprieta el juego de teclas
Ctrl + Enter
:
Práctica 02
Se darán los pasos requeridos para la creación de un archivo JAR ejecutable a partir de un proyecto de Clojure en Eclipse mediante Leiningen.
Crea el proyecto
practica02
.El contenido del archivo
project.clj
con lo siguiente:(defproject practica02 "0.1.0-SNAPSHOT" :description "FIXME: write description" :url "http://example.com/FIXME" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :dependencies [[org.clojure/clojure "1.9.0"]] :main practica02.core :profiles {:uberjar {:aot :all}})
Modifica el contenido del archivo
core.clj
con lo siguiente:(ns practica02.core (:require [clojure.repl :as repl]) (:require [clojure.string :as str]) (:require [clojure.set :as set]) (:gen-class)) (defn mensaje [] "Hola mundo!") (defn -main "Función principal" [& args] (println (mensaje)))
Aprieta el juego de teclas
Alt + L
seguido de la teclaL
, obtendrás el siguiente recuadro en el cual modificarás<task>
poruberjar
y aprieta la teclaEnter
:Observarás unos mensajes en la vista Console de Eclipse indicandote la compilación y creación del archivo JAR ejecutable
practica02-0.1-standalone.jar
. Puedes acceder al directorioC:\plf\clojure\proyectos\practica02\target
y ejecutarlo desde la línea de comandos (cmd
) con:C:\plf\clojure\proyectos\practica02\target> java -jar practica02-0.1-standalone.jar
Práctica 03
Se abordará el tema de testing unitario (unit testing en ingles) en un proyecto de Clojure, haciendo uso de una
tarea de Leiningen (lein test
) en Eclipse.
El test unitario, para la Programación Funcional y los temas que nos interesan en esta materia, se entendería como la verificación del correcto resultado emitido por una función.
Escribir un test unitario implica definir una unidad (una función) sobre la cual se ha de llevar a cabo un test (una verificación). Un test unitario verifica que una función tenga o cumpla ciertas propiedades o hechos. Cuando una función no tenga o cumpla ciertas propiedades o hechos diremos que el test ha fallado y que la función tiene un error de programación.
Crea el proyecto
practica03
.Modifica el contenido del archivo
core.clj
con lo siguiente:(ns practica03.core (:require [clojure.repl :as repl]) (:require [clojure.string :as str]) (:require [clojure.set :as set])) (defn el-primer-positivo [xs] (first (filter pos? xs)))
En este paso se ha establecido la unidad a probar, la función
el-primer-positivo
.Modifica el contenido del archivo
core_test.clj
con lo siguiente:(ns practica03.core-test (:require [clojure.test :refer :all] [practica03.core :refer :all])) (deftest tests-para-el-primer-positivo (testing "Debe regresar el número 3" (is (= (el-primer-positivo [ 3 -4 -3 5 6]) 3)) (is (= (el-primer-positivo [-3 -7 3 -2 4]) 3)) (is (= (el-primer-positivo [-6 -8 -1 -4 3]) 3))) (testing "Debe regresar el número 0" (is (= (el-primer-positivo []) 0)) (is (= (el-primer-positivo [-7 -2 -5 -1 -8]) 0)) (is (= (el-primer-positivo ["Hola" " " "mundo" "!"]) 0))))
En este paso se han definido las pruebas a realizar sobre la unidad haciendo uso de la macro deftest.
Ejecuta los test apretando el juego de teclas
Alt + L
seguido de la teclaL
.Obtendrás el siguiente recuadro en el cual modificarás
<task>
portest
y apretarás la teclaEnter
:Observarás unos mensajes en la vista Console de Eclipse indicandote los resultados obtenidos de la ejecución de los test:
Observaciones
De la ejecución de los test (lein test
) se puede observar que un test ha fallado:
(is (= (el-primer-positivo []) 0)
Este test establece que dada una secuencia vácia, la función el-primer-positivo
ha de regresar el número 0.
La función el-primer-positivo
no cumple esta propiedad al generar una excepción:
FAIL in (tests-para-el-primer-positivo) (core_test.clj:11)
Debe regresar el número 0
expected: (= (el-primer-positivo []) 0)
actual: (not (= nil 0))
...
...
...
ERROR in (tests-para-el-primer-positivo) (Numbers.java:96)
Debe regresar el número 0
expected: (= (el-primer-positivo ["Hola" " " "mundo" "!"]) 0)
actual: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number
...
...
...
Ran 1 tests containing 6 assertions.
2 failures, 1 errors.
Tests failed.
Por otro lado, se puede observar que la ejecución del test indica expected como lo esperado y actual como lo obtenido.
Pregunta: ¿Qué ha de modificarse en la función el-primer-positivo
para que cumpla esta propiedad?.
Observa lo siguiente:
=> (filter
(fn [x]
(and (number? x) (pos? x)))
["Hola" " " "mundo" "!"])
()
Una vez corregida la unidad a probar de acuerdo a la definición de pruebas puede uno observar la ejecución exitosa de dichas pruebas:
Consideraciones
- El test unitario o prueba unitaria es una práctica recomendable dentro del desarrollo de software actual.
- Por cuestiones de prácticidad o de ámbito laboral al test unitario se le suele ver asociado a la programación orientada a objetos
y apegado a un extenso marco teórico-práctico, los cuales no abordaremos:
- Unit Test: La importancia de usar tests unitarios por Manel Pérez Mata
- Test Driven Development por Alfredo Chavez
- Principios del Desarrollo Guiado por Pruebas por Jorge González
- Los tests unitarios suelen girar entorno a las preguntas:
- ¿Qué pasará si los datos de entrada a la función no son los esperados?.
- ¿Qué deberá regresar una función ante datos de entrada válidos?
Fuente: Example-based Unit Testing in Clojure por Eric Normand