Prueba tus aplicaciones de Compute de forma integral con JavaScript
Las pruebas automatizadas son una parte fundamental del desarrollo de aplicaciones modernas, y las que se crean para el edge en la plataforma Compute de Fastly no son una excepción. Los desarrolladores pueden probar sus aplicaciones de Compute con scripts de shell personalizados, pero queríamos ofrecerles una manera más cómoda y natural de hacerlo. La nueva biblioteca de pruebas de aplicaciones de Compute te permite escribir tus pruebas en JavaScript.
Aquí tienes un ejemplo de lo sencillo que resulta:
describe('/user.json', () => {
it('returns 200 status and valid username', async () => {
const resp = await app.fetch('/user.json');
assert.strictEqual(resp.status, 200);
const data = await resp.json();
assert.ok(/^\w+$/.test(data.username));
});
});
En este artículo compararemos la realización de pruebas mediante scripts de shell y mediante la biblioteca de pruebas de aplicaciones de Compute, para que elijas la opción que más te convenga, independientemente del lenguaje de programación en el que hayas escrito tu aplicación de Compute.
Las pruebas automatizadas son una técnica que se emplea durante el proceso de desarrollo de software para comprobar que el código funciona según lo previsto y que los cambios no se llevarán por delante sus funcionalidades. Al combinarlas con estrategias como la distribución continua, los desarrolladores pueden crear y desplegar software fiable. De esta forma, los equipos siempre tienen a mano un producto de alta calidad y listo para enviar.
Existen varios tipos de pruebas: las pruebas unitarias son las que se llevan a cabo en los elementos más pequeños del software de manera aislada, generalmente a nivel de función, clase o API; las pruebas de integración analizan las interacciones entre las distintas unidades que componen el software; y, por último, las pruebas integrales, o de extremo a extremo, son aquellas que se realizan en la totalidad de una aplicación para comprobar que unas entradas específicas producen las salidas esperadas.
Aunque todas estas pruebas son muy importantes, en este artículo vamos a centrarnos en las pruebas de extremo a extremo, ya que resultan muy efectivas para garantizar que una aplicación de Compute de Fastly produce las salidas esperadas.
¿Cómo se prueban las aplicaciones de Compute de extremo a extremo?
Compute es una plataforma de Fastly que ejecuta módulos de WebAssembly en nuestra red global de servidores en el edge. Estos módulos se compilan en el lenguaje de tu elección, que puede ser Rust, Go o JavaScript. Fastly proporciona un entorno local de pruebas para Compute enfocado en el desarrollo.
La pregunta es cómo se hace una prueba de extremo a extremo de una aplicación que se está ejecutando en Compute de Fastly. Como las aplicaciones de Compute se atienden como API de HTTP, una forma de hacerlo sería utilizar un flujo de acciones de GitHub para iniciar una aplicación en el entorno de pruebas y, acto seguido, poner en marcha un script de shell que ejecute comandos cURL:
.github/workflows/tests.yaml (fragmento)
jobs:
curl-test:
name: Build Compute Edge service, and test with curl
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Set up Fastly CLI
uses: fastly/compute-actions/setup@main
- name: Install Edge code dependencies
run: npm install
- name: Build and start Compute application
run: fastly compute serve > ./out.txt & (tail -f ./out.txt &) | grep -qF 'Listening on http://127.0.0.1:7676'
- name: Run tests
run: ./curl-tests/test.sh
./curl-tests/test.sh
#! /bin/bash
echo "test: returns 200 and the text \"Hello, World!\" for /"
OUTPUT=$(curl -vs "http://127.0.0.1:7676/" 2>&1)
grep -qF "200 OK" <<< "$OUTPUT" || { echo 'status not 200' ; exit 1; }
grep -qF "Hello, World!" <<< "$OUTPUT" || { echo 'unexpected response content' ; exit 1; }
echo "test: returns 200 and json including \"newField\": \"newValue\" for /json"
OUTPUT=$(curl -vs "http://127.0.0.1:7676/json" 2>&1)
grep -qF "200 OK" <<< "$OUTPUT" || { echo 'status not 200' ; exit 1; }
grep -qF "\"newField\":\"newValue\"" <<< "$OUTPUT" || { echo 'unexpected response content' ; exit 1; }
Si bien es cierto que los scripts de shell requieren trastear un poco con el texto, estas pruebas garantizan que el programa siga produciendo las salidas deseadas.
Pruebas escritas en JavaScript
En cualquier caso, muchos lenguajes de programación, plataformas y comunidades ofrecen opciones superiores, como el uso de entornos diseñados expresamente para la escritura y la ejecución de pruebas.
Queríamos que esta misma funcionalidad estuviera presente en Compute de Fastly y que diera la posibilidad de escribir pruebas sencillas para un servicio de nuestra plataforma, como se puede ver aquí:
it('returns 200 and the text "Hello, World!" for /', async () => {
const resp = await app.fetch('/');
assert.strictEqual(resp.status, 200);
assert.ok((await resp.text()).includes('Hello, World!'));
});
it('returns 200 and json including "newField": "newValue" for /json', async () => {
const resp = await app.fetch('/json');
assert.strictEqual(resp.status, 200);
const responseJson = await resp.json();
assert.strictEqual(responseJson['data']?.['newField'], 'newValue');
});
Este es precisamente el motivo por el que creamos la biblioteca de pruebas de aplicaciones de Compute para JavaScript.
NOTA: las pruebas de extremo a extremo solo tienen en cuenta las entradas y las salidas de un programa. Por tanto, las pruebas y la aplicación de Compute en las que se llevan a cabo pueden estar escritas en el mismo lenguaje o en lenguajes distintos. Esta biblioteca te permite utilizar JavaScript para escribir pruebas de extremo a extremo dirigidas a tu aplicación de Compute.
JavaScript es un lenguaje omnipresente y muy popular. Es una gran opción para crear peticiones web, analizar JSON de forma nativa, echar mano de utilidades como expresiones regulares, acceder a estructuras de datos como objetos y matrices, y trabajar con una amplia biblioteca de paquetes disponible en npm. Por todas estas razones, escribir pruebas de extremo a extremo en JavaScript nos pareció lo más lógico. Y como solo hay que comprobar las entradas y las salidas, da igual el lenguaje en el que esté escrita una aplicación de Compute.
La biblioteca de pruebas de aplicaciones de Compute para JavaScript está disponible en npm como @fastly/compute-testing. Tu aplicación de prueba se ejecutará en Node.js, por lo que querrás crearla por separado con respecto a tu aplicación de Compute. Desde ahí podrás añadirla como dependencia de desarrollo:
npm install --save-dev @fastly/compute-testing
Veamos qué aspecto tiene una prueba concreta.
Si conoces el entorno de pruebas Node.js o uno de estilo BDD como Jest, esto debería resultarte familiar: El caso de prueba, llamado «returns 200 and the text "Hello, World!" for /», utiliza la variable «app» para hacer una llamada a la ruta «/» de la aplicación de Compute. A continuación, hace una serie de aserciones acerca del código de estado y el contenido del texto de la respuesta.
Te preguntarás qué es la variable «app». Se trata de una instancia de ComputeApplication, una clase que te permite instanciar tu aplicación de Compute en el entorno de pruebas local. La variable representa una instancia de la aplicación de Compute y se usa de este modo:
import { ComputeApplication } from '@fastly/compute-testing';
describe('Edge app', () => {
const app = new ComputeApplication();
before(async () => {
await app.start({
// Set 'appRoot' to the directory in which to start the app. This is usually
// the directory that contains the 'fastly.toml' file.
appRoot: path.join(__dirname, '..'),
});
});
after(async() => {
await app.shutdown();
});
// ...tests here
});
Cuando la clase se instancia, hace una llamada a la CLI de Fastly para generar una instancia de tu aplicación de Compute en appRoot. Mientras se esté ejecutando, tus pruebas podrán enviarle peticiones mediante «.fetch()». Como recibe los mismos parámetros que la función global Fetch, puedes pasarle un objeto URL, una cadena o un objeto Request como primer parámetro e indicar los encabezados que necesites para que te devuelva un objeto Response en el que podrás realizar pruebas relativas al estado, los encabezados y los contenidos. Al tratarse de una respuesta, podrás utilizar otras funcionalidades tan útiles como la deserialización de JSON integrada:
it('returns 200 and json including "newField": "newValue" for /json', async () => {
const resp = await app.fetch('/json');
assert.strictEqual(resp.status, 200);
const responseJson = await resp.json();
assert.strictEqual(responseJson['data']?.['newField'], 'newValue');
});
Hay un montón de funcionalidades de JavaScript con las que puedes escribir pruebas detalladas. Sin ir más lejos, puedes usar Request para enviar datos en formato JSON, datos de formulario (mediante FormData) y blobs de streaming. Como se te devuelve un objeto Response, puedes acceder a streaming nativo y análisis de JSON, que te vendrán muy bien para comprobar las respuestas HTTP.
Naturalmente, el uso de Node.js también pone a tu alcance todos los paquetes disponibles en npm: si quieres analizar un DOM de HTML, para eso está JSDOM. Y si necesitas trabajar con un token web de JSON (JWT), jsonwebtoken es justo lo que buscas. En esta publicación hemos utilizado el entorno de pruebas y las aserciones de Node,js, pero si prefieres utilizar otro entorno u otra biblioteca de aserciones compatible con Node.js, como Jest, Mocha o Chai, también tienes esa posibilidad. Sea cual sea el objetivo de tus pruebas, escribirlas en JavaScript para Node.js te ayudará a alcanzarlo.
Dicho esto, la ejecución de estas pruebas se puede llevar a cabo mediante un flujo de GitHub:
.github/workflows/tests.yaml (fragmento)
jobs:
compute-testing-test:
name: Test Compute Edge service using compute-testing
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Set up Fastly CLI
uses: fastly/compute-actions/setup@main
- name: Install Edge code dependencies
run: npm install
- name: Install Test code dependencies
working-directory: ./test
run: npm install
- name: Run tests
working-directory: ./test
run: npm test
El resultado de este flujo es un formato bien ordenado que facilita la consulta de los nombres de las pruebas y otros datos:
Si quieres estudiar más a fondo el código y las pruebas de este ejemplo, lo tienes todo en mi GitHub: https://github.com/harmony7/compute-testing-demo.
Haz la prueba con tu propio código
La escritura de pruebas con JavaScript es una alternativa excelente al uso de scripts. Las pruebas de aplicaciones de Compute para JavaScript están a tu disposición en npm. Verás lo fácil que es crear y ejecutar pruebas en tu aplicación de Compute, así como añadirlas a tus pruebas de CI.
NOTA: @fastly/compute-testing se ofrece como un producto de Fastly Labs. Consulta aquí las condiciones de uso.
Visita nuestra página de proyecto en GitHub para obtener más información y ver otros ejemplos.
En Fastly, nuestro objetivo es darte la posibilidad de ejecutar y desarrollar más código en el edge con tus herramientas favoritas. Nos encanta cuando los usuarios sacan partido de las posibilidades que ofrecemos. ¡Únete al foro comunitario de Fastly y dinos en qué has estado trabajando!