La Guía Definitiva de Pruebas Unitarias con Dext: Calidad, Abstracción y la Revolución de Dext Test Explorer

La ingeniería de software moderna exige confiabilidad. Sin embargo, durante décadas, escribir pruebas en Delphi requirió un esfuerzo hercúleo de configuración interna. Aunque la comunidad cuenta con excelentes iniciativas inspiradas en .NET —que pavimentaron el camino hasta aquí—, el desarrollador aún necesitaba entrelazar manualmente diferentes bibliotecas de aserción, motores de mock y runners para obtener un entorno completo. Este roce de integración y la falta de una experiencia unificada en tiempo de diseño terminaban alejando a muchos equipos del hábito de probar.
El Dext Testing Framework fue desarrollado específicamente para romper esa barrera. Inspirado en las mejores prácticas y bibliotecas consolidadas del ecosistema .NET (como MSTest 2, NUnit, xUnit, Moq y Fluent Assertions), Dext trae a Delphi una suite de pruebas unificada, robusta, con un núcleo totalmente libre de dependencias externas y con un rendimiento excepcional.
In este guía completa, exploraremos a fondo los conceptos de diseño detrás del framework, detallaremos cada una de sus funciones y presentaremos el nuevo Dext Test Explorer IDE Expert, la herramienta visual definitiva para la productividad del desarrollador en RAD Studio.
1. El Manifiesto Dext: Calidad, Aislamiento y Abstracción
Sección titulada «1. El Manifiesto Dext: Calidad, Aislamiento y Abstracción»Escribir pruebas no se limita a verificar si 1 + 1 = 2. Una verdadera prueba unitaria es una herramienta de diseño de software. Fuerza al desarrollador a escribir código desacoplado y adherente a los principios de SOLID.
El Paradigma del SUT (System Under Test) y Aislamiento
Sección titulada «El Paradigma del SUT (System Under Test) y Aislamiento»En una prueba unitaria pura, probamos una sola clase (el SUT - System Under Test) de forma totalmente aislada. Cualquier dependencia externa (base de datos, llamadas de red o servicios) debe aislarse utilizando Mocks, Stubs o Fakes.
- Aislamiento Garantizado: Si la prueba falla, usted sabe exactamente qué unidad de código falló. No hay falsos negativos causados por una red inestable o registros ausentes en la base de datos.
- Abstracción y Flexibilidad de Acoplamiento: Para permitir el aislamiento, el SUT idealmente debe consumir abstracciones (interfaces). Dext hace que el mocking de estas interfaces sea tan natural como declarar una variable. Sin embargo, consciente de que los sistemas heredados o las arquitecturas existentes no siempre pueden refactorizarse para usar interfaces de inmediato, Dext Testing va más allá y ofrece soporte nativo para mocks de clases concretas (sobrescribiendo métodos virtuales). Esto garantiza total flexibilidad para aislar dependencias incluso bajo estructuras de acoplamiento más rígidas.
2. El Puente a .NET: Una Stack Consolidada
Sección titulada «2. El Puente a .NET: Una Stack Consolidada»En el ecosistema .NET, los desarrolladores usan una combinación de bibliotecas para obtener una experiencia completa de pruebas:
- xUnit / NUnit: Para el runner de pruebas y la estructuración de fixtures.
- Moq / NSubstitute: Para mockear dependencias y verificar llamadas.
- Fluent Assertions: Para aserciones legibles y expresivas.
En Delphi clásico, obtener este resultado requeriría instalar DUnitX, integrar Delphi-Mocks y buscar bibliotecas de aserciones fluidas de terceros, lo que frecuentemente genera conflictos de compatibilidad, acoplamiento de dependencias pesadas y una experiencia de desarrollo inconsistente.
Dext Testing unifica toda esta stack de forma nativa. Al consolidar el equivalente a múltiples frameworks distintos del ecosistema .NET (como runners, bibliotecas de mock, aserciones fluidas y motores de snapshot) en una sola solución cohesiva, eliminamos por completo el roce clásico de intentar integrar paquetes de diferentes autores.
Todas las funciones de Dext Testing fueron diseñadas desde el primer día para funcionar en perfecta armonía y de forma totalmente integrada. Esto significa que la declaración de la prueba con atributos, la creación del mock, las aserciones con Should y la exportación de informes comparten la misma infraestructura interna y convenciones. No hay necesidad de adaptadores, soluciones alternativas o configuraciones complejas. Esta sinergia nativa simplifica la curva de aprendizaje, garantiza la máxima eficiencia en tiempo de ejecución y optimización de compilación, además de permitir una evolución natural e integrada de toda la suite de pruebas.
Vea cómo las características de Dext se comparan con los gigantes de .NET:
| Recurso / Concepto | Ecosistema .NET | Equivalente en Dext Testing | Ventaja Dext |
|---|---|---|---|
| Definición de Fixtures | [TestClass] (MSTest) / [TestFixture] (NUnit) | [TestClass], [TestFixture] | Permite criar clases de prueba PODO puras, eliminando la obligatoriedad de herencia (como el clásico TTestCase de DUnit). |
| Aserciones | fluent.Should().Be(...) (Fluent Assertions) | Should(Value).Be(...) | Sintaxis altamente fluida con encadenamiento. |
| Mocking | new Mock<T>() (Moq) | Mock<T>.Create | Gestión de ciclo de vida automática (Records en lugar de Clases), eliminando fugas de memoria en pruebas. |
| Auto-Mocking | AutoMocker (Moq.AutoMocker) | TAutoMocker | Instanciación automática del SUT resolviendo constructores con Mocks preconfigurados. |
| Data-Driven Tests | [Theory] (xUnit) / [TestCase] (NUnit) | [Test], [TestCase], [TestCaseSource] | Pruebas parametrizadas nativas que admiten fuzzing con [Random], [Range] y [Values]. |
| Snapshot Testing | Snapshooter / Verify | MatchSnapshot | Nativo, guardando automáticamente estructuras complejas como JSON en una carpeta de snapshots. |
| Cobertura de Código | Coverlet / dotnet-coverage | dext.exe --coverage | Nativo a través de CLI (informes HTML/XML) y pronto integrado directamente en la UI del Test Explorer en el IDE. |
| IDE Runner | Test Explorer (Visual Studio) | Dext Test Explorer (RAD Studio Expert) | Integración perfecta con RAD Studio, ofreciendo árbol interactivo, agrupamientos, inspector de errores y exportaciones. |
3. Guía de Referencia Técnica de Funcionalidades
Sección titulada «3. Guía de Referencia Técnica de Funcionalidades»Exploremos detalladamente cómo usar cada recurso de Dext con ejemplos prácticos de código.
3.1. RTTI-Based Runner (PODO Test Fixtures)
Sección titulada «3.1. RTTI-Based Runner (PODO Test Fixtures)»Diga adiós a la necesidad de herdar sus clases de prueba de TTestCase o TDephiTestCase. En Dext, cualquier clase Delphi común (PODO - Plain Old Delphi Object) puede contener pruebas, siempre que esté debidamente decorada con atributos.
unit Dext.Core.UnitTests;
interface
uses Dext.Testing;
type [TestFixture] [Category('Business')] TDiscountServiceTests = class private FService: IDiscountService; public [Setup] procedure Setup;
[TearDown] procedure Cleanup;
[Test] [Description('Valida si un cliente estándar sin cupón no recibe descuento')] procedure TestNoDiscountForStandardUser;
[Test] // Parámetros: Subtotal, IsVip, Cupón, DescuentoEsperado [TestCase(100.0, False, '', 0.0)] [TestCase(100.0, True, '', 10.0)] [TestCase(200.0, False, 'BLACKFRIDAY', 30.0)] procedure TestDiscountRules(const Subtotal: Double; const IsVip: Boolean; const Coupon: string; const ExpectedDiscount: Double); end;
implementation
procedure TDiscountServiceTests.Setup;begin FService := TDiscountService.Create;end;
procedure TDiscountServiceTests.Cleanup;begin FService := nil;end;
procedure TDiscountServiceTests.TestNoDiscountForStandardUser;begin var Discount := FService.CalculateDiscount(50.0, False, ''); Should(Discount).Be(0.0);end;
procedure TDiscountServiceTests.TestDiscountRules(const Subtotal: Double; const IsVip: Boolean; const Coupon: string; const ExpectedDiscount: Double);begin var Discount := FService.CalculateDiscount(Subtotal, IsVip, Coupon); Should(Discount).Be(ExpectedDiscount);end;
end.Atributos de Ciclo de Vida del Runner:
Sección titulada «Atributos de Ciclo de Vida del Runner:»[Setup]: Ejecutado antes de cada prueba de la clase.[TearDown]: Executado después de cada prueba de la clase.[BeforeAll]/[ClassInitialize]: Ejecutado una sola vez antes de que ruede cualquier prueba de la clase.[AfterAll]/[ClassCleanup]: Ejecutado una sola vez después de que finalicen todas las pruebas de la clase.[AssemblyInitialize]: Ejecutado una vez en la inicialización del Runner de pruebas.[AssemblyCleanup]: Ejecutado una vez al finalizar el Runner.
Control de Ejecución y Resiliencia:
Sección titulada «Control de Ejecución y Resiliencia:»[Ignore('Motivo')]: Omite la prueba proporcionando una explicación que aparece en los informes y en el IDE.[Timeout(Milliseconds)]: Cancela y falla la prueba si la ejecución excede el tiempo límite especificado.[Repeat(N)]: Ejecuta la pruebaNveces consecutivas. Excelente para detectar flaky tests (pruebas inestables) y condiciones de carrera (race conditions).[MaxTime(Milliseconds)]: La prueba pasa si la lógica es correcta, pero genera una advertencia en los informes si tarda más del límite permitido (útil para detectar regresiones de rendimiento).[Explicit]: La prueba solo se ejecuta si el usuario la selecciona explícitamente (útil para pruebas de integración lentas).[Platform('Win64')]: Limita la ejecución de la prueba a arquitecturas específicas.
3.2. Fluent Assertions (Should Syntax)
Sección titulada «3.2. Fluent Assertions (Should Syntax)»Las aserciones fluidas de Dext aumentan significativamente la legibilidad de las pruebas. La estructura del código se asemeja a una frase en inglés, facilitando la revisión de código.
// Encadeamiento fluido con .And / .AndAlsoShould(Name).StartWith('Jo').AndAlso.EndWith('ao').And.NotBe('John');
// Valores numéricosShould(Count).BeGreaterThan(0);Should(Value).BeInRange(1, 100);
// Aserciones para GUID y UUID nativos de DextShould(RecordGuid).NotBeEmpty;
// Listas y ColeccionesShould(UserList).HaveCountLessThan(10);Should(UserList).Contain(AdminUser);Should(UserList).BeEquivalentTo(ExpectedList); // Compara elementos ignorando el orden
// Tratamiento elegante de ExcepcionesShould(procedure begin FService.CalculateDiscount(-10.0, False, ''); // Lanza excepción si el valor es negativo end).Throw<EArgumentOutOfRangeException>();Soft Assertions (Assert.Multiple)
Sección titulada «Soft Assertions (Assert.Multiple)»Por defecto, un error en una aserción interrumpe la ejecución de la prueba de inmediato. Con Assert.Multiple, puede agrupar varias aserciones. El Runner ejecutará todas ellas e informará detalladamente cuáles fallaron al final del bloque.
Assert.Multiple(procedure begin Should(User.Name).Be('Maria'); Should(User.Age).Be(28); Should(User.Email).Contain('@company.com'); end);Property Accessors (WhichString, WhichInteger, etc.)
Sección titulada «Property Accessors (WhichString, WhichInteger, etc.)»Permite acceder a propiedades de subobjetos de forma segura y fluida sin necesidad de romper la cadena de aserciones:
Should(Order) .NotBeNil .HaveProperty('Customer').WhichObject .HaveProperty('Name').WhichString .StartWith('Enterprise');Smart Entities (Evitando Strings Mágicas)
Sección titulada «Smart Entities (Evitando Strings Mágicas)»Para evitar el uso de strings mágicas al probar propiedades de objetos, Dext proporciona Prototype.Entity<T> para extraer metadatos fuertemente tipados de las propiedades:
var u := Prototype.Entity<TUser>;Should(CurrentUser).HaveValue(u.Email, 'suporte@dext.dev');3.3. El Poderoso Motor de Mocking
Sección titulada «3.3. El Poderoso Motor de Mocking»A diferencia de .NET, Delphi no tiene árboles de expresión (Expression Trees) nativos. Para resolver esto con elegancia y tipado fuerte, Dext implementa una arquitectura basada en Proxy-Recording (Setup...When.MethodCall).
[!IMPORTANT] El
Mock<T>de Dext está implementado como un Record Genérico. Esto significa que vive en el ámbito de la pila y no requiere liberación manual (.Free). La instancia de la interfaz mockeada se destruye automáticamente de acuerdo con las reglas de conteo de referencias de Delphi.
💡 El Ciclo de Vida Gestionado de Mock
Los frameworks de prueba tradicionales suelen requerir una atención redoblada en la gestión de memoria de las instancias de mock. Dext resuelve este dolor al implementar Mock
utilizando Managed Records y conteo de referencias nativo. El Mock nace y muere respetando el alcance del método de prueba asignado en la pila, eliminando la necesidad de bloques try..finally manuales solo para liberar la infraestructura de pruebas. Es la sofisticación de la ingeniería moderna de Object Pascal trabajando para mantener el código limpio.
uses Dext.Mocks;
type {$M+} // Obligatorio para habilitar RTTI extendida en la interfaz IPaymentService = interface ['{8F4E6B20-562F-4DFA-A39B-C53805D7AAEC}'] function ProcessPayment(const CardNum: string; const Amount: Double): Boolean; function GetTransactionCount: Integer; end; {$M-}
procedure TOrderTests.TestOrderPayment;begin // 1. Creación del Mock var MockPayment := Mock<IPaymentService>.Create;
// 2. Setup del comportamiento (Retorna true para cualquier número de tarjeta y valor) MockPayment.Setup .Returns(True) .When .ProcessPayment(Arg.Any<string>, Arg.Any<Double>);
// 3. Setup de secuencia (retorna valores diferentes en cada llamada subsiguiente) MockPayment.Setup .ReturnsInSequence([1, 2, 3]) .When .GetTransactionCount;
// 4. Ejecutando el SUT con el mock inyectado (.Instance proporciona la interfaz física) var OrderProcessor := TOrderProcessor.Create(MockPayment.Instance); try var Success := OrderProcessor.Checkout('1234-5678', 150.00);
// Aserción Should(Success).BeTrue; finally OrderProcessor.Free; end;
// 5. Verificación de llamadas (Asserts de comportamiento) MockPayment.Received(Times.Once).ProcessPayment('1234-5678', 150.00); MockPayment.DidNotReceive.ProcessPayment(Arg.Is<string>(function(S: string): Boolean begin Result := S.StartsWith('0000'); // Garantiza que no se envió ninguna tarjeta inválida end), Arg.Any<Double>);
// Garantiza que no hubo llamadas inesperadas además de las verificadas MockPayment.VerifyNoOtherCalls;end;Mocking de Clases (Mocks Parciales/Spies)
Sección titulada «Mocking de Clases (Mocks Parciales/Spies)»Dext también permite mockear métodos virtuales de clases concretas y configurar comportamiento parcial (redireccionar llamadas no configuradas a la clase base):
var MockRepo := Mock<TUserRepository>.Create;MockRepo.CallsBaseForUnconfiguredMembers := True; // Comportamiento de Spy
MockRepo.Setup.Returns(MockedUser).When.FindById(99);// FindById(99) retorna MockedUser. Otros IDs invocarán la lógica real de TUserRepository.3.4. Contenedor de Auto-Mocking (TAutoMocker)
Sección titulada «3.4. Contenedor de Auto-Mocking (TAutoMocker)»Gestionar dependencias manualmente en pruebas complejas puede generar una cantidad masiva de código de inicialización (boilerplate). TAutoMocker automatiza esto inspeccionando los constructores de la clase bajo prueba, creando los mocks necesarios e inyectándolos automáticamente.
procedure TUserTests.TestUserRegistration;begin var Mocker := TAutoMocker.Create;
// El AutoMocker crea el mock de IUserRepository y IEmailService silenciosamente // e inyecta en los parámetros del constructor de TUserService var UserService := Mocker.CreateInstance<TUserService>; try // Podemos obtener el mock creado y configurar comportamiento Mocker.GetMock<IUserRepository>.Setup .Returns(True) .When .Save(Arg.Any<TUser>);
UserService.Register('John Doe', 'john@dext.dev');
// Verifica si se envió el correo de bienvenida Mocker.GetMock<IEmailService>.Received(Times.Once).SendWelcomeEmail('john@dext.dev'); finally UserService.Free; Mocker.Free; end;end;3.5. Snapshot Testing (MatchSnapshot)
Sección titulada «3.5. Snapshot Testing (MatchSnapshot)»Al probar respuestas complejas (como payloads JSON grandes generados por un servicio de serialización), las aserciones manuales pueden volverse impracticables. Snapshot Testing guarda el estado completo del objeto en un archivo JSON de referencia y valida ejecuciones futuras contra él.
[Test]procedure TestComplexReportGeneration;begin var Report := FReportService.Generate(2026, 'Ventas');
Report.MatchSnapshot(procedure(Options: TSnapshotOptions) begin // Ignora campos generados dinámicamente como marcas de tiempo o IDs aleatorios Options.IgnorePaths([ '$.Metadata.GeneratedAt', '$.Metadata.TraceId' ]); end);end;Para actualizar los archivos de referencia cuando un cambio de comportamiento sea intencional, basta con ejecutar el runner a través de CLI:
dext test --update-snapshots3.6. Cobertura de Código (Code Coverage)
Sección titulada «3.6. Cobertura de Código (Code Coverage)»¿De qué sirve tener miles de pruebas si cubren solo una fracción insignificante del sistema? La Cobertura de Código (Code Coverage) es la métrica que indica qué líneas de código de su producto fueron ejecutadas durante la ejecución de pruebas unitarias.
Hoy en día, Dext proporciona soporte nativo para la cobertura de código a través de su utilidad de CLI, dext.exe.
Al ejecutar en la terminal:
dext test --coverageEsta funcionalidad es viable gracias a la integración transparente de Dext con la herramienta de código abierto de la comunidad Delphi Code Coverage (https://github.com/DelphiCodeCoverage/DelphiCodeCoverage). La utilidad dext.exe automatiza todo el proceso, incluyendo la opción de descargar la última versión directamente desde el repositorio oficial de la herramienta si no está presente en la máquina.
Dext coordina la ejecución de la herramienta y consolida la generación de informes detallados de cobertura, exportables en formatos como HTML y XML (totalmente compatibles con SonarQube para componer los Quality Gates de la pipeline).
🚀 Próximo Paso: Cobertura Integrada en el IDE
Sección titulada «🚀 Próximo Paso: Cobertura Integrada en el IDE»Para elevar aún más la experiencia en tiempo de diseño (Design-Time DX), estamos integrando la Cobertura de Código directamente en la interfaz visual de Dext Test Explorer en RAD Studio.
Con esta integración, los desarrolladores podrán ejecutar el análisis de cobertura con un solo clic y visualizar el porcentaje de cobertura de las clases directamente en el árbol de pruebas y el resaltado coloreado de las líneas ejecutadas y no ejecutadas en el propio editor de código del IDE, eliminando la necesidad de exportaciones manuales o verificaciones externas durante el desarrollo.
3.7. El Ecosistema de Integración Continua (CI/CD) y Quality Gates
Sección titulada «3.7. El Ecosistema de Integración Continua (CI/CD) y Quality Gates»En el desarrollo de software moderno, la calidad no se delega solo al final del ciclo de desarrollo. Se valida de forma continua en cada commit. Aquí es donde entra el concepto de Quality Gates (Puertas de Calidad).
¿Qué es un Quality Gate y por qué salva negocios?
Sección titulada «¿Qué es un Quality Gate y por qué salva negocios?»Un Quality Gate es un conjunto de condiciones y métricas automatizadas que un tramo de código debe satisfacer antes de integrarse en la rama principal o promoverse a producción. Evalúa:
- Ejecución exitosa del 100% de las pruebas unitarias y de integración.
- Cobertura mínima de código probado (ej: 80%).
- Ausencia de vulnerabilidades de seguridad y errores críticos detectados por análisis estático.
El Costo del Error en Producción:
Según la clásica regla de la Ingeniería de Software, un error encontrado durante la fase de codificación cuesta 1x. Si pasa a la fase de pruebas manuales/QA, cuesta 10x. Si llega a producción, el costo salta a 100x o más. En sistemas ERP de misión crítica escritos en Delphi (que gestionan facturación, emisión fiscal, contabilidad y existencias), un error crítico en producción puede paralizar las operaciones de cientos de clientes corporativos, lo que conlleva multas contractuales, pérdidas financieras masivas y daños irreparables a la reputación de la casa de software.
Cómo Dext Habilita la Cultura de Calidad en Delphi
Sección titulada «Cómo Dext Habilita la Cultura de Calidad en Delphi»Tradicionalmente, la comunidad Delphi enfrentaba dificultades para integrar pruebas de proyectos heredados con herramientas de CI/CD por falta de formatos de informes compatibles con los analizadores del mercado.
Dext resuelve esto de forma nativa al actuar como un generador de informes multiformato. Con la Fluent API de Dext, usted configura exportadores que guardan los resultados de las pruebas en los estándares requeridos por las principales herramientas de DevSecOps del mercado:
if TTest.Configure .Verbose .RegisterFixtures([TDiscountServiceTests, TUsuarioServiceTests]) .ExportToJUnit('results-junit.xml') // Estándar de GitHub Actions, Jenkins y GitLab CI .ExportToXUnit('results-xunit.xml') // Estándar del ecosistema .NET .ExportToTRX('results.trx') // Formato nativo para integración perfecta con Azure DevOps .ExportToJson('report.json') // Útil para scripts de auditoría personalizados .ExportToSonarQube('sonar-generic.xml') // Integración directa con los Quality Gates de SonarQube .ExportToHtml('dashboard.html') // Informe estático autocontenido con gráficos estadísticos .Run then ExitCode := 0else ExitCode := 1;Otros Recursos e Integración Práctica con Herramientas del Mercado:
Sección titulada «Otros Recursos e Integración Práctica con Herramientas del Mercado:»- SonarQube: Al generar el archivo
sonar-generic.xml, el escáner de SonarQube lee los resultados de éxito, fallo y skips de Dext, integrando estos datos directamente en las reglas de bloqueo de la Pull Request en la plataforma de Code Review. - Azure DevOps: El formato
.trxes el estándar oficial del ecosistema de Microsoft. Al utilizarlo, el panel de Azure Pipelines genera gráficos nativos detallados del progreso de las pruebas, el tiempo dedicado y el historial de estabilidad de las compilaciones de forma automática. - GitHub Actions / GitLab CI / Jenkins: Utilizando el formato clásico JUnit XML, cualquier runner de compilación detecta los fallos en la terminal, impide el despliegue automático de código roto y envía alertas inmediatas al equipo.
3.8. Live Dashboard (Hoja de Ruta de Evolución)
Sección titulada «3.8. Live Dashboard (Hoja de Ruta de Evolución)»Dext Testing trae el soporte a un Live Dashboard basado en un servidor HTTP embebido y Server-Sent Events (SSE) para proveer una visualización enriquecida y una línea de tiempo en tiempo real de la ejecución de las pruebas.
4. La Revolución de Dext Test Explorer
Sección titulada «4. La Revolución de Dext Test Explorer»La mayor novedad de la última versión de Dext es Dext Test Explorer, un Expert (plugin) nativo de alto nivel integrado directamente en RAD Studio. Trae la experiencia visual fluida del Test Explorer de Visual Studio directamente al entorno Delphi, reemplazando las implementaciones clásicas por una interfaz de usuario rica y moderna.

La interfaz de Dext Test Explorer integrada en RAD Studio.
Principales Características del Test Explorer:
Sección titulada «Principales Características del Test Explorer:»- Soporte para Múltiples Proyectos de Prueba (Project Group): Dext Test Explorer permite gestionar múltiples proyectos de pruebas unitarias dentro del mismo Grupo de Proyectos (
.groupproj) cargado en el IDE. El desarrollador selecciona en qué proyecto de pruebas desea enfocarse a través de un combobox intuitivo en la parte superior de la interfaz. Esto permite trabajar de forma aislada y modularizada. En bases de código grandes (con cientos o miles de pruebas), se evita la lentitud de recompilar y enlazar un ejecutable gigante en cada alteración, permitiendo compilar y ejecutar solo el proyecto seleccionado, reduciendo drásticamente el tiempo de feedback. - Árbol de Pruebas Dinámico con Parser Ultra-Rápido: Inspecciona el proyecto de prueba activo seleccionado, descubriendo automáticamente las Fixtures y Pruebas a través de RTTI. El parser interno de carga ha sido optimizado extensivamente para un rendimiento instantáneo: incluso en proyectos complejos con más de 1000 casos de prueba, la carga y el mapeo en el árbol ocurren de forma prácticamente inmediata en el IDE. En nuestros benchmarks prácticos (visibles en la interfaz real del IDE reproducida abajo), el motor de Dext ejecutó una suite de 61 pruebas unitarias complejas de serialización en menos de 1 segundo de tiempo computacional puro (exactamente 0,73s). La barra de estado también muestra, con total transparencia, el tiempo total de ciclo (10,06s), que abarca el recorrido completo del IDE: compilación, enlace y la carga del proceso. Tener este nivel de feedback visual sin necesidad de salir del editor de texto es lo que mantiene al desarrollador enfocado y productivo. Permite filtrar y buscar pruebas en tiempo real a medida que escribe.
- Modos de Agrupamiento Flexibles:
- Group by Code Structure: Organiza las pruebas siguiendo la estructura lógica de Units y Clases/Fixtures.
- Group by Test Status: Agrupa por Passed (Aprobadas), Failed (Fallidas), Skipped (Omitidas) e Idle (No ejecutadas).
- Diseños Personalizables:
- Tabbed Layout: Permite organizar la interfaz en pestañas limpias.
- Split Layouts (Bottom/Right): Divide la pantalla para mostrar los registros de la consola y el árbol de pruebas junto con el editor de código del IDE.
- Pestaña Test Inspector: Muestra información detallada de la prueba seleccionada, incluyendo nombre completo, estado de ejecución, duración precisa y la ubicación física exacta (unit y línea). Un doble clic en la prueba lleva el cursor directamente al código correspondiente en el editor de RAD Studio.
- Pestaña de Configuración y Automatización: Panel dedicado a personalizar la experiencia de ejecución de pruebas:
- Custom Command Line Parameters: Permite pasar parámetros de línea de comandos personalizados al runner de pruebas (como filtros avanzados
--filter mytest*o modo--verbose). - Run tests automatically on Save: Ejecuta la suite de pruebas automáticamente cada vez que se guarda un archivo del proyecto en el IDE.
- Run tests automatically on Idle: Ejecuta las pruebas de forma asíncrona cuando el IDE detecta inactividad del desarrollador (Continuous Testing).
- Enable Dext Test Explorer: Interruptor global para habilitar o deshabilitar la integración activa del plugin de forma rápida.
- Custom Command Line Parameters: Permite pasar parámetros de línea de comandos personalizados al runner de pruebas (como filtros avanzados
- Log de Consola Integrado: Pestaña dedicada a la visualización directa del
Stdouty los registros generados durante las ejecuciones de las pruebas. - Barra de Estado Analítica: Estadísticas agregadas en la parte inferior que muestran: Total, Seleccionadas, Passed, Failed, Skipped, Tiempo de Ejecución de las pruebas y Tiempo de Ejecución Global.
- Menú Visual de Exportación de Informes (
...):- Exportación instantánea con un clic a JUnit XML, xUnit XML, JSON, SonarQube XML y HTML Report.
- Cobertura de Código Integrada (Próximamente): Ejecución del análisis de Code Coverage con un solo clic directamente a través del Test Explorer, proporcionando informes visuales del porcentaje de cobertura y coloreado de líneas ejecutadas directamente en el editor de código del IDE.
4.1. Soporte Heredado y Ecosistemas de la Comunidad: DUnit, DUnit2 y DUnitX
Sección titulada «4.1. Soporte Heredado y Ecosistemas de la Comunidad: DUnit, DUnit2 y DUnitX»Sabemos que migrar toda la base de pruebas de un sistema corporativo de una vez a una nueva suite es inviable. Consciente de ello, Dext Test Explorer nació preparado para respetar y valorar el ecosistema existente de la comunidad Delphi.
El Expert trae soporte nativo inicial para ejecutar pruebas heredadas y modernas escritas en:
- DUnit: El pionero y clásico framework basado en JUnit.
- DUnit2: La evolución enfocada en mejoras estructurales del clásico DUnit.
- DUnitX: El framework de pruebas moderno más adoptado hoy en día, inspirado en conceptos de .NET.
Al mapear el árbol de pruebas de su Proyecto o Grupo de Proyectos, Dext Test Explorer descubre y ejecuta perfectamente estas suites clásicas de forma transparente y asíncrona, mostrando los resultados en el mismo panel visual unificado. Nos colocamos totalmente a disposición de cualquier persona que desee experimentar y usar estas integraciones en sus proyectos; si encuentra algún problema, dificultad o comportamiento inesperado, por favor avísenos para que podamos ayudar y evolucionar la herramienta juntos.
Homologado en la Práctica con Proyectos Open Source
Sección titulada «Homologado en la Práctica con Proyectos Open Source»Para comprobar el poder y la madurez de la integración de Dext Test Explorer con herramientas de la comunidad, realizamos la ejecución y homologación completa de suites de pruebas unitarias de grandes proyectos de código abierto del ecosistema Delphi.
Las pruebas de estas suites, que se ejecutan bajo la estructura de DUnitX, fueron cargadas y ejecutadas por Dext Test Explorer de forma directa, sin necesidad de adaptaciones ni de herramientas intermedias. El resultado fue un feedback visual instantáneo de las pruebas aprobadas en tiempo de diseño, demostrando que Dext no busca aislar al desarrollador, sino unir el ecosistema clásico con una experiencia visual moderna y profesional.
5. El Próximo Horizonte: Una Visión para la Evolución de la RTL y del IDE
Sección titulada «5. El Próximo Horizonte: Una Visión para la Evolución de la RTL y del IDE»Más que entregar una suite lista, el desarrollo de Dext Testing nos trajo una claridad profunda sobre el futuro del ecosistema Object Pascal. Para que la cultura de calidad se convierta en el estándar absoluto en la industria Delphi, necesitamos discutir cómo la testabilidad puede integrarse de forma nativa y conectable en el corazón de la plataforma.
La ingeniería moderna ganaría una tracción sin precedentes si las herramientas oficiales de la RTL y de RAD Studio nacieran preparadas para el aislamiento de código. Imagine el impacto de tener:
- Abstracciones Testables Nativas: Mocks y stubs simplificados y conectables para componentes críticos como FireDAC, WebBroker, DataSnap y los nuevos motores de WebStencils. Probar una regla de negocio que interactúa con una solicitud web o una transacción de base de datos no debería requerir que el desarrollador cree pesadas capas de contorno.
- Interfaces de E/S Desacopladas: Primitivas de lectura y escritura de archivos y comunicación de red que admitan la inyección de dependencias nativa en la RTL, facilitando el aislamiento del SUT (System Under Test).
- Una Open Tools API (OTA) Enfocada en Continuous Testing: La infraestructura de extensibilidad del IDE podría evolucionar para permitir que los Experts ejecuten suites de prueba de forma totalmente asíncrona y en segundo plano, marcando fallos o líneas no cubiertas de manera suave y visual directamente en el gutter (el margen lateral) del editor de código. El desarrollador sabría que rompió una prueba en el mismo segundo en que guarda el archivo, sin que el foco de la escritura o la interfaz de RAD Studio sufran ninguna interrupción.
Dext Testing demuestra que el lenguaje está listo para este nivel de sofisticación. El siguiente paso lógico es unir fuerzas como comunidad y plataforma para hacer de este flujo de diseño la regla, y no la excepción.
6. Conclusión: ¿Por qué Dext Lleva a Delphi Más Allá?
Sección titulada «6. Conclusión: ¿Por qué Dext Lleva a Delphi Más Allá?»Al unificar conceptos avanzados y ofrecer una herramienta integrada de vanguardia como Dext Test Explorer, Dext demuestra que Delphi es perfectamente capaz de ejecutar pruebas unitarias y de integración con la misma facilidad, expresividad y velocidad que stacks como .NET, Java, Rust o Node.js.
Escribir pruebas robustas utilizando abstracción, aislamiento y mocking estructurado no solo protege al software contra errores en producción, sino que redefine la calidad y la arquitectura general de los proyectos heredados y nuevos en el ecosistema Delphi.
¡Participe y Contribuya!
Sección titulada «¡Participe y Contribuya!»Dext Test Explorer ya se está utilizando activamente en el día a día. Sin embargo, al ser una herramienta en constante evolución, puede contener errores o inestabilidades temporales. Si encuentra algún problema, por favor infórmelo abriendo un issue, y si tiene sugerencias de mejora, no dude en enviar su solicitud.
- Repositorio Oficial: GitHub - cesarliws/dext
- Documentación de Pruebas (PT-BR): Guía de Pruebas (PT)
- Documentación de Pruebas (EN): Guía de Pruebas (EN)
- Instalación de Dext: Guía de Instalación
¡Pruebe Dext Testing hoy mismo y revolucione el flujo de entrega de su equipo!