• Ir al contenido principal
  • Skip to secondary menu
  • Ir a la barra lateral primaria
  • Ir al pie de página
  • Inicio
  • Secciones
    • Ciencia de datos
    • Criptografía
    • Herramientas
    • Noticias
    • Opinión
  • Programación
    • JavaScript
    • Julia
    • Matlab
    • Python
    • R
  • Boletín
  • Contacto
  • Acerca de Analytics Lane
  • Tienda
    • Libros
    • Equipamiento de oficina
    • Equipamiento en movilidad
    • Tiendas afiliadas
      • AliExpress
      • Amazon
      • GearBest
      • GeekBuying
      • JoyBuy

Analytics Lane

Ciencia e ingeniería de datos aplicada

  • Ciencia de datos
  • Criptografía
  • Python
  • Matlab
  • R
  • Julia
  • JavaScript
  • Herramientas
  • Opinión
  • Noticias

Estructurar el proyecto TypeScript y pruebas unitarias (3º parte – Creación de una librería TypeScript)

diciembre 2, 2020 Por Daniel Rodríguez Dejar un comentario

Una vez vistas las ventajas de TypeScript y cómo configurar el proyecto vamos a ver los pasos para estructurar el proyecto TypeScript. Además, en esta ocasión veremos cómo introducir pruebas unitarias con Jest, un framework que facilita la creación de pruebas que pueden ser escritas directamente en TypeScript.

Estructurar el proyecto TypeScript

En la entrada anterior definimos que el código fuente de nuestro proyecto TypeScript se almacenará en la carpeta src. Una carpeta que tendrá una estructura similar a la que usamos a la hora de crear librerías en JavaScript. Así, si migramos un proyecto existen de JavaScript a TypeScript el primer paso solo será copiar todo el código y cambiar la extensión de los archivos .js por .ts. Al ser TypeScript un superconjunto de JavaScript cualquier código del segundo es válido en el primero.

Migración de las funciones de jslane

Esto lo podemos ver si queremos migrar las funciones creadas cuando explicamos cómo crear una librería JavaScript. Librería a la que llamamos jslane. En la que todo el código se encontraba en el archivo array.js.

(function() {
  'use strict';

  const array = exports;

  // Sum of an array
  array.sum = function(arr) {
    let result = 0;

    for (let i = 0; i < arr.length; ++i) {
      result += arr[i];
    }

    return result;
  };

  // Mean of an array
  array.mean = function(arr) {
    return array.sum(arr) / arr.length;
  };

  // Summary of an array
  array.summary = function(arr) {
    return {
      sum: array.sum(arr),
      mean: array.mean(arr)
    };
  };

  // Multiply all values by a scalar
  array.multiply = function(arr, value) {
    const result = arr.slice();

    if (value === undefined) {
      return result;
    }

    for (let i = 0; i < arr.length; ++i) {
      result[i] = arr[i] * value;
    }

    return result;
  };
})();

Código que se puede traducir a TypeScript de la siguiente manera.

export interface Summary {
    sum: number
    mean: number
}

export function sum(arr: number[]): number {
    let result: number = 0;

    for (let i = 0; i < arr.length; ++i) {
        result += arr[i];
    }

    return result;
}

// Mean of an array
export function mean(arr: number[]): number {
    return sum(arr) / arr.length;
}

// Summary of an array
export function summary(arr: number[]): Summary {
    return {
        sum: sum(arr),
        mean: mean(arr)
    };
}

// Multiply all values by a scalar
export function multiply(arr: number[], value: number): number[] {
    const result = arr.slice();

    if (value === undefined) {
        return result;
    }

    for (let i = 0; i < arr.length; ++i) {
        result[i] = arr[i] * value;
    }

    return result;
}

Ahora ya no es necesario usar el modificador 'use strict'; al principio del código ni asignar las funciones a la variable exports. Lo que deja un código más limpio. Para indicar que cualquier componente del módulo se exporta simplemente se tiene que usar el modificado export antes de una función o variable, lo que hemos hecho en las cuatro funciones.

Además de estos se han indicado los tipos de datos number[] para los vectores y number para los escalares. Así, en caso de intentar pasar un tipo de variable incorrecta el compilador nos avisará en tiempo de ejecución. Así podernos ver que se puede estructurar el proyecto TypeScript se hace de una forma más sencilla que en el caso de JavaScript.

La interface Summary

En el ejemplo podemos ver algo especial, la función summary devuelve un tipo de dato que no es primitivo, es un objeto. Un objeto que podemos definir mediante una interfaz. Un elemento de TypeScript que nos permite saber exactamente qué propiedades puede tener un objeto. Así evitamos sorpresas. Sabemos los valores que se pueden pasar a un objeto y que recibimos exactamente.

Al igual que los objetos, es habitual que el nombre de las interfaces se escriba con mayúsculas al principio. La definición se crea con la palabra reservada interface seguido del nombre. A continuación, se abre corchete y se indica los elementos que pude contener un objeto que verifiqué la interfaz.

Aunque no lo hemos usado en el ejemplo, una interfaz puede tener valores opcionales. Valores que pueden o no existir. Para crear un valor opcional, simplemente se tiene que situar después del nombre y antes del tipo, el signo de interrogación ?. Por ejemplo, se podría agregar un tipo power opcional a la interfaz ya definida.

export interface Summary {
    sum: number
    mean: number
    power?:number
}

Pruebas unitarias con Jest

Ahora podemos crear pruebas unitarias para evaluar qué el código funciona correctamente. Para ello vamos a usar Jest. Una framework que ofrece varias ventajas como la posibilidad de escribir las pruebas en TypeScript e incluir la medición del grado de cobertura. En este caso necesitamos instalar las siguientes dependencias

npm install jest ts-jest @types/jest --save-dev

El primer paquete es el framework Jest, el segundo es un preprocesador para poder crear las pruebas unitarias en TypeScript en lugar de JavaScript. Finalmente, el tercero son los archivos de tipos de Jest para que los conozca el compilador de TypeScript.

module.exports = {
    globals: {
        'ts-jest': {
            tsconfig: 'tsconfig.json'
        }
    },
    moduleFileExtensions: ['ts', 'js'],
    transform: {
        '^.+\\.(ts)$': 'ts-jest'
    },
    testEnvironment: 'node'
};

Ahora necesitamos crear un archivo de configuración para Jest llamado jest.config.js y que debemos situar en la raíz del proyecto. En nuestro caso, como queremos escribir las pruebas en TypeScript, debemos indicar a ts-jest cuál es el archivo de configuración de TypeScript y la extensión de los archivos. Un archivo de configuración puede ser el siguiente.

Primera prueba con Jest

Ahora se puede crear una carpeta tests, ubicación por defecto donde busca los archivos con las pruebas Jest, y escribir la primera prueba. Por ejemplo, una para la función suma en el archivo array.test.ts. Siendo necesario usar la extensión test.ts para indicar que es una prueba unitaria.

import { sum } from '../src/array'

test('Sum the values of an array', () => {
    expect(sum([1, 2])).toBe(3);
});

En este caso se puede ver que las pruebas son similares, pero más sencillas que con Mocha. Ahora no es necesario importar por separado expect ni indicar la finalización de la prueba con la función done(). Lo que nos deja un código mucho más compacto. Para lanzar las pruebas solamente se tiene que usar el comando jest si se ha instalado la dependencia globalmente, en caso contrario tendremos que escribir npx jest. Lo que nos debería indicar que hemos pasado todas las pruebas.

Medir el grado de cobertura

Una de las ventajas de Jest sobre Mocha es que no es necesario instalar nada para lanzar las pruebas unitarias. Solamente se tiene que indicar la opción --collectCoverage para obtener estas al ejecutar las pruebas. Así, si ejecutamos el comando jest --collectCoverage veremos que en nuestro caso solamente tenemos una cobertura del 50%.

 PASS  tests/array.test.ts
  ✓ Sum the values of an array (2 ms)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |      50 |        0 |      25 |      50 |                   
 array.ts |      50 |        0 |      25 |      50 | 18,23,31-41       
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.916 s, estimated 2 s

Los resultados tienen la misma interpretación que los del paquete nyc usado en las pruebas de JavaScript. Sería necesario comprobar las líneas que no tienen cobertura y conseguir que los niveles de esta se aproximen al 100% del código.

Excluir carpetas en la compilación

Ahora que hemos creado la carpeta de tests es aconsejable excluir esta de la compilación en el archivo tsconfig.json. Debido a que se almacenan archivos TypeScript que no es necesario compilar. Para ello se puede añadir una nueva propiedad, al mismo nivel que `compilerOptionx llamda exclude en la que indicamos las carpetas que deseamos que el compilador ignore. Actualmente debemos omitir los archivos que se encuentran tanto bajo node_modules como tests.

{
  "compilerOptions": {
    ...
  },
  "exclude": [
    "node_modules", "tests"
  ]
}

Configuración de los scripts

Ahora podremos crear tres scripts en el archivo package.json con los que compilar (build), probar (test) y medir el grado de cobertura (coverage). Además es aconsejable agregar TypeScript como dependencia de desarrollo para que cuando lo distribuyamos no dependa que esta se encuentre instalada globalmente. Para lo que escribiremos en el proyecto

npm install typescript -save-dev

Y en el archivo package.json escribiremos los scripts.

  "scripts": {
    "build": "npx tsc",
    "coverage": "npx jest --collectCoverage",
    "test": "npx jest"
  },

Lo que nos puede facilitar el trabajo de depuración, aunque por el momento los comandos son bastante sencillos.

Conclusiones

Hemos visto cómo estructurar el proyecto TypeScript migrando el código que tengamos escrito en JavaScript. Además de configurar Jest como Framework de pruebas unitarias, el cual ofrece ciertas ventajas sobre Mocha como poder escribir las pruebas en TypeScript, simplificar el código y obtener el grado de cobertura con una simple opción.

Imagen de M W en Pixabay

¿Te ha parecido de utilidad el contenido?

¡Puntúalo entre una y cinco estrellas!

Puntuación promedio 0 / 5. Votos emitidos: 0

Ya que has encontrado útil este contenido...

¡Síguenos en redes sociales!

¡Siento que este contenido no te haya sido útil!

¡Déjame mejorar este contenido!

Dime, ¿cómo puedo mejorar este contenido?

Contenido relacionado

Archivado en:JavaScript Etiquetado con:TypeScript

Interacciones con los lectores

Deja una respuesta Cancelar la respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

I accept the Terms and Conditions and the Privacy Policy

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Publicidad


Barra lateral primaria

Suscríbete a nuestro boletín

Suscríbete al boletín semanal para estar al día de todas las publicaciones.

Política de Privacidad

¡Síguenos en redes sociales!

  • facebook
  • github
  • telegram
  • pinterest
  • rss
  • tumblr
  • twitter
  • youtube

Publicidad

Tiendas afiliadas

Ayúdanos realizando tus compras sin coste adicional con los enlaces de la tienda. ¡Gracias!

Entradas recientes

Usar dispositivos USB en VirtualBox

enero 15, 2021 Por Daniel Rodríguez Dejar un comentario

Eliminar elementos en matrices de Matlab

enero 13, 2021 Por Daniel Rodríguez Dejar un comentario

NumPy

NumPy: Crear matrices vacías en NumPy y adjuntar filas o columnas

enero 11, 2021 Por Daniel Rodríguez Dejar un comentario

Publicidad

Es tendencia

  • Seleccionar filas y columnas en Pandas con iloc y loc bajo Python
  • ¿Cómo eliminar columnas y filas en un dataframe pandas? bajo Python
  • Excel en Python Guardar y leer archivos Excel en Python bajo Python
  • Unir y combinar dataframes con pandas en Python bajo Python
  • Operaciones de filtrado de DataFrame con Pandas en base a los valores de las columnas bajo Python

Publicidad

Lo mejor valorado

5 (3)

Ordenar una matriz en Matlab en base a una fila o columna

5 (3)

Automatizar el análisis de datos con Pandas-Profiling

5 (5)

Diferencias entre var y let en JavaScript

5 (6)

Operaciones de filtrado de DataFrame con Pandas en base a los valores de las columnas

5 (3)

Unir y combinar dataframes con pandas en Python

Publicidad

Comentarios recientes

  • Daniel Rodríguez en Calculadora de probabilidades de ganar a la lotería
  • abel en Calculadora de probabilidades de ganar a la lotería
  • David Arias en Diferencias entre regresión y clasificación en aprendizaje automático
  • Juan Aguilar en Archivos JSON con Python: lectura y escritura
  • Camilo en Contar palabras en una celda Excel

Publicidad

Footer

Secciones

  • Ciencia de datos
  • Criptografía
  • Herramientas
  • Noticias
  • Opinión

Programación

  • JavaScript
  • Julia
  • Matlab
  • Python
  • R

Analytics Lane

  • Acerca de Analytics Lane
  • Boletín de noticias
  • Contacto
  • Lo más popular
  • Tienda

Tiendas Afiliadas

  • AliExpress
  • Amazon
  • BangGood
  • GearBest
  • Geekbuying
  • JoyBuy

Sobre de Analytics Lane

En Analytics Lane tratamos de explicar los principales conceptos de la ciencia e ingeniería de datos con un enfoque práctico. Los principales temas tratados son ciencia de datos, ingeniería de datos, inteligencia artificial, machine learning, deep learning y criptografía. Además, también se habla de los principales lenguajes de programación y herramientas utilizadas por los científicos e ingenieros de datos.

Tiendas afiliadas

Ayúdanos realizando tus compras sin coste adicional con los enlaces de la tienda. ¡Gracias!

Amazon

2018-2020 Analytics Lane · Términos y condiciones · Política de Cookies · Política de Privacidad · Herramientas de privacidad · Contacto