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.

  1. 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:

    images/02.png

    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 archivo project.clj. Al momento de guardar los cambios Eclipse actualizará el nodo Leiningen dependencies.

  2. 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]))
    
  3. Carga en el REPL al archivo core.clj dando click derecho sobre él y selecciona Clojure > Load file in REPL:

    images/03.png

    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:

    images/04.png

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.

  1. Crea el proyecto practica02.

  2. 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}})
    
  3. 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)))
    
  4. Aprieta el juego de teclas Alt + L seguido de la tecla L, obtendrás el siguiente recuadro en el cual modificarás <task> por uberjar y aprieta la tecla Enter:

    images/06.png

    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 directorio C:\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
    

    images/07.png

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.

  1. Crea el proyecto practica03.

  2. 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.

  3. 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.

  4. Ejecuta los test apretando el juego de teclas Alt + L seguido de la tecla L.

    Obtendrás el siguiente recuadro en el cual modificarás <task> por test y apretarás la tecla Enter:

    images/09.png

    Observarás unos mensajes en la vista Console de Eclipse indicandote los resultados obtenidos de la ejecución de los test:

    images/08.png

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:

images/10.png

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:
  • 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