Escribir pruebas unitarias para tus jobs
La mayor parte del código de un job sigue el mismo patrón: obtiene algunos registros, les cambia la forma y los envía a otro lugar. Pero esa parte de transformación suele crecer hasta convertirse en lógica compleja: convertir un texto en un registro estructurado, mapear códigos locales a elementos de datos de DHIS2 o unificar una docena de formatos de fecha en uno solo.
Hacer pruebas unitarias de esa lógica ayuda a comprobar que el código funciona correctamente y a evitar errores cuando se modifique más adelante.
Necesitas @openfn/cli v1.39.0 o posterior para compilar el código de tus jobs
para las pruebas. Comprueba tu versión con openfn -v y actualízala con
npm install -g @openfn/cli.
También necesitas un proyecto de OpenFn descargado en tu computadora:
openfn project pull <uuid>
Así obtienes una carpeta con openfn.yaml, un directorio workflows/ y un
archivo .js por cada step. Consulta OpenFn Sync para
saber cómo descargar proyectos, hacer checkout y desplegarlos.
Paso 1: exporta las funciones auxiliares que quieras probar
Las funciones que quieras probar tienen que estar exportadas:
export const FIELDS = ['id', 'name', 'dob'];
export const parseSms = text =>
Object.fromEntries(FIELDS.map((f, i) => [f, text.split('#')[i]]));
fn(state => ({ ...state, data: state.data.messages.map(parseSms) }));
Paso 2: compila tus workflows
Desde la raíz de tu proyecto (la carpeta que tiene openfn.yaml):
openfn compile --exports-only
[CLI] ✔ Compiled 1 step(s) to /path/to/project/dist
Los archivos compilados se guardan en dist/, con la misma estructura que tus
workflows. Los archivos de salida usan la extensión .mjs. Node siempre
trata los archivos .mjs como módulos ES, así que no necesitas
"type": "module" en tu package.json para que el código compilado se importe
sin problemas.
.mjs generadosLa CLI no agrega un .gitignore para el directorio compilado, así que agrégalo
tú antes de tu primer commit:
dist/
Los archivos .mjs son resultado de la compilación y salen por completo de tus
steps .js. Si los incluyes en el repositorio, cada edición te deja diffs
ruidosos y conflictos de merge, y dist/ puede dejar de coincidir con
workflows/.
Otras opciones útiles:
# Write somewhere other than dist/
openfn compile --exports-only -o workflows
# Wipe the output folder first
openfn compile --exports-only --clean
# Just one workflow, by name
openfn compile sms-parser --exports-only
Ejecuta openfn compile --help para ver la lista completa.
También puedes definir la carpeta de salida de forma permanente en
openfn.yaml:
dirs:
workflows: workflows
compiled: workflows
Paso 3: escribe una prueba
Aquí recomendamos el ejecutor de pruebas integrado de Node porque no necesita dependencias, pero nada de esto es exclusivo de Node. Puedes usar cualquier ejecutor de pruebas que pueda importar un módulo ES.
.test.mjsLa salida compilada es .mjs y no necesita configuración. Pero tus archivos de
prueba son cosa tuya: si les pones la extensión .js en un proyecto sin
"type": "module", Node te avisará de que tiene que volver a analizarlos como
módulos ES. Si los llamas .test.mjs, evitas el aviso sin tocar tu
package.json.
- El código del job
- La salida compilada
- La prueba
export const FIELDS = ['id', 'name', 'dob', 'weight'];
export const parseSms = text => {
const parts = text.trim().split('#');
return FIELDS.reduce((record, field, i) => {
record[field] = parts[i]?.trim() ?? null;
return record;
}, {});
};
fn(state => ({
...state,
data: state.data.messages.map(parseSms),
}));
Después de openfn compile --exports-only:
export const FIELDS = ['id', 'name', 'dob', 'weight'];
export const parseSms = text => {
const parts = text.trim().split('#');
return FIELDS.reduce((record, field, i) => {
record[field] = parts[i]?.trim() ?? null;
return record;
}, {});
};
La operación fn(...) desapareció. Las dos exportaciones se conservaron.
Fíjate en la ruta del import: apunta a dist/, no a tu archivo fuente.
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { parseSms } from '../dist/sms-parser/parse-message.mjs';
test('parses a well-formed message into a record', () => {
assert.deepEqual(parseSms('P-001#Ada Lovelace#1815-12-10#3.2'), {
id: 'P-001',
name: 'Ada Lovelace',
dob: '1815-12-10',
weight: '3.2',
});
});
Ejecutar la prueba
openfn compile --exports-only && node --test
✔ parses a well-formed message into a record (0.9ms)
✔ trims whitespace around each field (0.1ms)
✔ fills missing trailing fields with null (0.1ms)
ℹ tests 1
ℹ pass 1
ℹ fail 0
Paso 4: ejecuta las pruebas en modo watch
Ejecuta el compilador en modo watch en una terminal:
openfn compile --exports-only --watch
Y tu ejecutor de pruebas en modo watch en otra:
node --test --watch
Ahora, cada vez que editas un step, este se vuelve a compilar, lo que cambia un
archivo en dist/ y vuelve a ejecutar tus pruebas.
Páginas relacionadas
- Compilación: qué hace el compilador y por qué
- Buenas prácticas: cómo escribir código de jobs que valga la pena probar
- Uso básico de la CLI: cómo ejecutar workflows en tu computadora
- OpenFn Sync: cómo descargar un proyecto para tener un
openfn.yamlque compilar