Referencia de Dart y Flutter
Estos son los principales componentes que puedes usar para integrar pruebas de Dart y Flutter con Allure utilizando allure_dart_test y allure_flutter_test.
Wrappers de prueba integrables
Las librerías integrables reemplazan las funciones de declaración del framework subyacente y reexportan todo lo demás sin cambios:
package:allure_dart_test/test.dartreemplazatest,group,setUp,tearDown,setUpAllytearDownAlldepackage:test,package:allure_flutter_test/flutter_test.dartademás reemplazatestWidgetsdeflutter_test,package:allure_flutter_test/integration_test.dartproporciona los mismos wrappers más las exportaciones deintegration_test, incluyendoIntegrationTestWidgetsFlutterBinding.
Los wrappers aceptan los mismos argumentos que los originales. Además del comportamiento original, hacen lo siguiente:
- reportan cada prueba como un resultado de prueba de Allure con etiquetas automáticas derivadas de la ruta del archivo y la jerarquía de grupos,
- analizan marcadores de metadatos en línea desde los nombres de las pruebas,
- reportan los callbacks de
setUp,tearDown,setUpAllytearDownAllcomo fixtures de Allure, - omiten las pruebas excluidas por un plan de pruebas de Allure (no se escribe ningún resultado de prueba de Allure).
testWidgets y variantes
Cuando una prueba de widget utiliza un TestVariant (por ejemplo, ValueVariant), el wrapper de Allure reporta cada valor de variante como un resultado de prueba separado:
testWidgets(
'renders both layouts',
(tester) async {
// ...
},
variant: ValueVariant<String>({'compact', 'expanded'}),
);Cada resultado se nombra como renders both layouts (variant: compact) y renders both layouts (variant: expanded), lleva un parámetro variant con el valor, y comparte el nombre de caso de prueba renders both layouts. Los selectores del plan de pruebas coinciden con los nombres completos específicos de la variante.
Adjuntos automáticos de captura de pantalla y golden-diff
installAllure() de allure_flutter_test — no el de allure_dart_test — acepta dos flags exclusivos de Flutter:
installAllure(autoScreenshotOnFailure: true)— en una prueba fallida, captura una captura de pantalla del árbol de widgets y la adjunta comoscreenshot-on-failure(PNG).installAllure(autoAttachGoldenDiff: true)— en un error dematchesGoldenFile, adjunta la imagen renderizada real comogolden-actual, además, en la medida de lo posible (cuando el comparador es elLocalFileComparatorpredeterminado), cualquiera degolden-masterImage,golden-testImage,golden-maskedDiffygolden-isolatedDiffque ya haya escrito en disco. El comparador solo calcula una diferencia de píxeles cuando las imágenes real y golden tienen el mismo tamaño, así que un error de dimensiones adjunta solo las imágenes master y test, mientras que un error de píxeles de mismo tamaño también adjunta las dos visualizaciones de diferencia.
Ambos flags instalan un hook a nivel de proceso la primera vez que cualquiera se pasa como true, funcionan en la medida de lo posible (un error de captura nunca oculta el fallo original de la prueba), y son monótonos — una llamada posterior a installAllure() sin flags en el mismo proceso no los desactiva:
import 'dart:async';
import 'package:allure_flutter_test/allure_flutter_test.dart';
Future<void> testExecutable(FutureOr<void> Function() testMain) async {
installAllure(autoScreenshotOnFailure: true, autoAttachGoldenDiff: true);
await testMain();
}Aún puedes adjuntar capturas de pantalla o archivos golden manualmente con las APIs de adjuntos normales, independientemente de si estos hooks están habilitados.
API en tiempo de ejecución
Las funciones en tiempo de ejecución son exportadas por package:allure_dart_test/allure_dart_test.dart y package:allure_flutter_test/allure_flutter_test.dart. Se aplican a la prueba que se está ejecutando actualmente — o, cuando se llaman dentro de un fixture, al fixture y su alcance. Todas son asíncronas y deben ser esperadas. Importa la librería con un prefijo para mantener los nombres cortos legibles:
import 'package:allure_dart_test/allure_dart_test.dart' as allure;Metadatos y etiquetas
allure.displayName(name)— sobrescribe el nombre de la prueba mostrado en el reporteallure.description(markdown)allure.descriptionHtml(html)allure.label(name, value)allure.labels([AllureLabel(...), ...])allure.allureId(value)allure.owner(value)allure.severity(value)allure.layer(value)allure.tag(value)allure.tags(['smoke', 'auth'])allure.testCaseName(value)allure.testCaseId(value)allure.historyId(value)
Ejemplo:
test('login works', () async {
await allure.description('Verifica que un usuario válido puede iniciar sesión.');
await allure.owner('John Doe');
await allure.severity('critical');
await allure.label('microservice', 'ui');
await allure.tags(['smoke', 'auth']);
});Jerarquías
allure.epic(value)allure.feature(value)allure.story(value)allure.parentSuite(value)allure.suite(value)allure.subSuite(value)
Enlaces y parámetros
allure.link(url, name: ..., type: ...)allure.links([AllureLink(...), ...])allure.issue(url, name: ...)allure.tms(url, name: ...)allure.parameter(name, value, excluded: ..., mode: ...)
Un valor de parámetro puede ser cualquier objeto; los valores que no sean cadenas se codifican en JSON. Los parámetros con excluded: true no afectan el historial de la prueba. El argumento mode controla la visualización: AllureParameterMode.masked oculta el valor detrás de asteriscos, y AllureParameterMode.hidden omite el parámetro del reporte.
test('login works', () async {
await allure.issue('https://jira.example.com/browse/AUTH-123', name: 'AUTH-123');
await allure.parameter('browser', 'firefox');
await allure.parameter('password', 'qwerty', mode: allure.AllureParameterMode.masked);
});Estados
allure.statusDetails(message: ..., trace: ..., known: ..., muted: ..., flaky: ..., actual: ..., expected: ...)allure.markKnown()allure.markMuted()allure.markFlaky()
El estado de una prueba se resuelve automáticamente: los fallos de aserción (como los matchers expect fallidos) se reportan como fallido, cualquier otro error como roto, y las pruebas omitidas (por ejemplo, mediante markTestSkipped, o un skip: en tiempo de declaración en los wrappers integrables, que se convierte en una auto-omisión en tiempo de ejecución) como omitido. La única excepción es un skip: en tiempo de declaración con installAllure() y las importaciones originales del framework: el framework nunca ejecuta setUp para una prueba omitida en declaración, que es donde ese estilo programa el resultado, así que no se produce ningún resultado — consulta Omitir pruebas para el desglose completo, incluyendo el tradeoff de fixture de omisión de grupo. Para los fallos de matcher, los valores actual y esperado se extraen automáticamente en los detalles de estado. La llamada a statusDetails te permite añadir flags de clasificación adicionales:
test('login works', () async {
await allure.statusDetails(flaky: true);
});Pasos
allure.step(name, (step) async { ... })— ejecuta el cuerpo dentro de un paso y retorna su valorallure.logStep(name, status: ..., error: ...)— registra un paso instantáneo ya completado
El objeto de contexto step pasado al cuerpo proporciona:
step.displayName(name)— renombra el paso actualstep.parameter(name, value, mode: ...)— añade un parámetro al paso actual
test('login works', () async {
final session = await allure.step('create session', (step) async {
await step.parameter('user', 'alice');
return Session('alice');
});
await allure.logStep('cleanup skipped', status: allure.AllureStatus.skipped);
});Los pasos se anidan: una llamada a step dentro del cuerpo de otro paso crea un paso hijo. Si el cuerpo lanza una excepción, el paso se marca como fallido o roto y el error se relanza.
Adjuntos
allure.attachment(name, content, contentType: ..., fileExtension: ..., wrapInStep: ..., timestamp: ...)allure.attachmentPath(name, path, contentType: ..., fileExtension: ..., wrapInStep: ..., timestamp: ...)allure.attachTrace(name, path)— adjunta un archivo de volcado de Playwright existente para que el reporte lo abra en el Trace Viewer (no genera trazas ni depende de Playwright)
El contenido del adjunto puede ser un String, una lista de bytes, o cualquier objeto codificable en JSON. Con wrapInStep: true (por defecto), el adjunto se añade como un paso de adjunto, así que mantiene su posición entre los pasos circundantes.
WARNING
Dentro del cuerpo de un testWidgets de Flutter, las llamadas de adjuntos de I/O real (attachmentPath, o attachment con contenido de stream) deben ejecutarse dentro de tester.runAsync(...), o la prueba se queda colgada — testWidgets se ejecuta en una zona fake-async que nunca procesa callbacks de I/O real de otra manera.
test('login works', () async {
await allure.attachment(
'response.json',
'{"status":"ok","user":"demo"}',
contentType: 'application/json',
fileExtension: 'json',
);
await allure.attachmentPath(
'screenshot',
'screenshots/failure.png',
contentType: 'image/png',
);
});Adjuntos y errores a nivel de ejecución
Estas funciones escriben datos a nivel de ejecución no ligados a una sola prueba — por ejemplo, un log de servidor para toda la ejecución o un fallo de infraestructura:
allure.globalAttachment(name, content, contentType: ..., fileExtension: ...)allure.globalAttachmentPath(name, path, contentType: ..., fileExtension: ...)allure.globalError(message: ..., trace: ..., known: ..., muted: ..., flaky: ..., actual: ..., expected: ...)
allureTest
allureTest de package:allure_dart_test/allure_dart_test.dart es una alternativa a los wrappers integrables para pruebas individuales. Declara una prueba de package:test cuyo cuerpo recibe un objeto de contexto con helpers de alcance de prueba, incluyendo APIs de adjuntos duraderos para artefactos grandes o producidos tarde:
import 'package:allure_dart_test/allure_dart_test.dart';
void main() {
allureTest('captures logs', (allure) async {
await allure.step('start server', () async {
// ...
});
await allure.streamAttachment(
name: 'server log',
type: 'text/plain',
extension: 'log',
content: logFile.openRead(),
);
});
}El objeto de contexto proporciona:
step(name, body)— como la API de paso de nivel superior, pero sin el argumento de contexto de pasolabel(name, value),parameter(name, value, ...),testCaseName(value),statusDetails(...)attachment(name: ..., type: ..., content: ..., extension: ..., wrapInStep: ...)— contenido binariotextAttachment(name: ..., content: ..., type: ..., extension: ..., wrapInStep: ...)— contenido de texto,text/plainpor defectostreamAttachment(name: ..., content: ..., type: ..., extension: ..., wrapInStep: ...)— escribe desde un stream de bytespreparedAttachment(name: ..., type: ..., extension: ..., write: ..., wrapInStep: ...)— reserva un archivo de adjunto y permite que tu callback lo escriba antes de que el resultado lo referencie
allureTest también acepta timeout, skip y listas iniciales de labels, parameters y links.
Personalización del ciclo de vida
installAllure() acepta un AllureLifecycle personalizado, que es el lugar para establecer datos de reporte a nivel de ejecución:
import 'package:allure_dart_test/allure_dart_test.dart';
import 'package:test/test.dart';
void main() {
installAllure(
lifecycle: AllureLifecycle(
linkUrlTemplates: {
'issue': 'https://jira.example.com/browse/{}',
'tms': 'https://tms.example.com/cases/{}',
},
executorInfo: const AllureExecutorInfo(
name: 'GitHub Actions',
type: 'github',
buildName: 'Build #42',
),
environmentInfo: const {'stand': 'staging'},
categories: [
AllureCategory(name: 'Infrastructure', messageRegex: RegExp('timeout')),
],
),
);
// ...
}Las opciones más útiles:
linkUrlTemplates/linkNameTemplates— plantillas agrupadas por tipo de enlace, aplicadas a enlaces cuyo URL no es absoluto.{}(o%s) se reemplaza por el valor del enlace, así queallure.issue('AUTH-123')se resuelve al URL completo del tracker.executorInfo— metadatos de CI o lanzador escritos enexecutor.json(nombre, tipo, nombre de build, URL de build, URL de reporte, orden de build).environmentInfo— pares clave-valor escritos enenvironment.properties, combinados con los valores del archivo de configuración.categories— definiciones personalizadas de categorías de defectos escritas encategories.json, que coinciden con resultados por expresiones regulares de mensaje o traza.globalLabels— etiquetas añadidas a cada resultado de prueba, combinadas con los valores del archivo de configuración.listeners— una lista de implementaciones deAllureLifecycleListener. Un listener observa eventos del ciclo de vida (inicio/detención/escritura de prueba, detención de paso, escritura de contenedor, adjuntos, errores globales) y puede modificar un resultado antes de que se escriba — por ejemplo, para añadir etiquetas o limpiar datos. Un listener que lanza una excepción se reporta en stderr sin fallar la ejecución.
WARNING
installAllure() es seguro de llamar más de una vez en el mismo proceso siempre que lifecycle (y frameworkLabelResolver) se omitan o sean idénticos cada vez — una llamada simple a installAllure() nunca altera una configuración ya instalada. Llamarlo de nuevo con una instancia realmente diferente de lifecycle lanza un StateError en vez de mantener silenciosamente la primera.
Construyendo una integración personalizada con allure_dart_commons
Usa allure_dart_commons cuando necesites control de bajo nivel sobre el ciclo de vida:
import 'package:allure_dart_commons/allure_dart_commons.dart';
Future<void> main() async {
final lifecycle = AllureLifecycle(
writer: AllureResultsWriter(outputDirectory: 'allure-results'),
);
final testUuid = lifecycle.startTest(
name: 'login works',
fullName: 'auth/login_test.dart#login works',
);
lifecycle.startStep(testUuid, 'submit credentials');
lifecycle.stopStep(testUuid, status: AllureStatus.passed);
await lifecycle.stopTest(testUuid, status: AllureStatus.passed);
await lifecycle.writeTest(testUuid);
}Los principales tipos de bajo nivel son:
AllureLifecycle— inicia, actualiza, detiene y escribe pruebas, fixtures y pasos; maneja adjuntos y datos a nivel de ejecuciónAllureResultsWriter— escribe archivos de resultados, contenedores y adjuntos en el directorio de resultadosAllureConfig— cargaallure-dart.yamlAllureLifecycleListener— hooks de eventos del ciclo de vidaAllureStatus,AllureStatusDetails,AllureLabel,AllureLink,AllureParametery los otros tipos de modelo
Para artefactos transmitidos y tardíos, el ciclo de vida expone addAttachmentStreamToRoot y addPreparedAttachmentToRoot, que escriben el payload de forma duradera antes de que el resultado lo referencie. Para redirigir la API de tiempo de ejecución de nivel superior a tu propio ciclo de vida, conecta un MessageTestRuntime con setGlobalTestRuntime y lleva el contexto de ejecución a través de los límites asíncronos con runWithAllureContext.