Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este artículo se tratan los puntos de extensibilidad de Microsoft.Testing.Platform más allá del propio marco de pruebas. Para la creación del marco de pruebas, consulte Compilación de un marco de pruebas.
Para obtener el resumen completo del punto de extensión y los conceptos dentro del proceso o fuera del proceso, consulte Creación de extensiones personalizadas.
Puntos de extensibilidad
La plataforma de pruebas proporciona puntos de extensibilidad adicionales que permiten personalizar el comportamiento de la plataforma y el marco de pruebas. Estos puntos de extensibilidad son opcionales y se pueden usar para mejorar la experiencia de prueba.
Las extensiones
Nota:
Al extender esta API, la extensión personalizada existirá tanto dentro como fuera del proceso de host de prueba.
Como se describe en la sección arquitectura, el paso inicial implica crear para registrar el marco de pruebas y las extensiones con él.
var builder = await TestApplication.CreateBuilderAsync(args);
El método acepta una matriz de cadenas () denominada . Estos argumentos se pueden usar para pasar opciones de línea de comandos a todos los componentes de la plataforma de pruebas (incluidos los componentes integrados, los marcos de pruebas y las extensiones), lo que permite personalizar su comportamiento.
Normalmente, los argumentos pasados son los recibidos en el método estándar . Sin embargo, si el entorno de hosting difiere, se puede proporcionar cualquier lista de argumentos.
Los argumentos deben ir precedidos por un doble guion . Por ejemplo: .
Si un componente como un marco de pruebas o un punto de extensión desea ofrecer opciones de línea de comandos personalizadas, puede hacerlo implementando la interfaz . A continuación, esta implementación se puede registrar con a través de la fábrica de registro de la propiedad , como se muestra aquí:
builder.CommandLine.AddProvider(
static () => new CustomCommandLineOptions());
En el ejemplo proporcionado, es una implementación de la interfaz . Esta interfaz consta de los siguientes miembros y tipos de datos:
public interface ICommandLineOptionsProvider : IExtension
{
IReadOnlyCollection<CommandLineOption> GetCommandLineOptions();
Task<ValidationResult> ValidateOptionArgumentsAsync(
CommandLineOption commandOption,
string[] arguments);
Task<ValidationResult> ValidateCommandLineOptionsAsync(
ICommandLineOptions commandLineOptions);
}
public sealed class CommandLineOption
{
public string Name { get; }
public string Description { get; }
public ArgumentArity Arity { get; }
public bool IsHidden { get; }
// ...
}
public interface ICommandLineOptions
{
bool IsOptionSet(string optionName);
bool TryGetOptionArgumentList(
string optionName,
out string[]? arguments);
}
Como se observa, extiende la interfaz . Por lo tanto, al igual que cualquier otra extensión, puede optar por habilitarla o deshabilitarla mediante la API .
El orden de ejecución de es:
Diagrama que representa el orden de ejecución de la interfaz "ICommandLineOptionsProvider".
Vamos a examinar las APIs y su significado.
: este método se utiliza para recuperar todas las opciones que ofrece el componente. Cada requiere que se especifiquen las siguientes propiedades:
: Este es el nombre de la opción, presentado sin guion. Por ejemplo, los usuarios utilizarían el filtro como .
: se trata de una descripción de la opción. Se mostrará cuando los usuarios pasen como argumento al generador de aplicaciones.
: la aridad de una opción es el número de valores que se pueden pasar si se especifica esa opción o comando. Las aridades actualmente disponibles son:
- : representa una aridad de argumentos de cero.
- : representa una aridad de argumento de cero o uno.
- : representa una aridad de argumentos de cero o más.
- : Representa una aridad de uno o más argumentos.
- : representa una aridad de argumentos de exactamente uno.
Para ver ejemplos, consulte la tabla de aridades System.CommandLine.
: esta propiedad indica que la opción está disponible para su uso, pero no se mostrará en la descripción cuando se invoque .
: este método se emplea para validar el argumento proporcionado por el usuario.
Por ejemplo, si tiene un parámetro denominado que representa el grado de paralelismo de nuestro marco de pruebas personalizado, un usuario podría escribir . En este escenario, el valor no sería válido porque se espera que tenga un grado de paralelismo de o más. Al usar , puede realizar una validación por adelantado y devolver un mensaje de error si es necesario.
Una posible implementación del ejemplo anterior sería:
public Task<ValidationResult> ValidateOptionArgumentsAsync(
CommandLineOption commandOption,
string[] arguments)
{
if (commandOption.Name == "dop")
{
if (!int.TryParse(arguments[0], out int dopValue) || dopValue <= 0)
{
return ValidationResult.InvalidTask("--dop must be a positive integer");
}
}
return ValidationResult.ValidTask;
}
: este método se llama en último lugar y permite hacer la comprobación de coherencia global.
Por ejemplo, supongamos que nuestro marco de pruebas tiene la capacidad de generar un informe de resultados de prueba y guardarlo en un archivo. Se obtiene acceso a esta característica mediante la opción y el nombre de archivo se especifica con . En este escenario, si un usuario solo proporciona la opción sin especificar un nombre de archivo, se producirá un error en la validación porque el informe no se puede generar sin un nombre de archivo. Una posible implementación del ejemplo anterior sería:
public Task<ValidationResult> ValidateCommandLineOptionsAsync(ICommandLineOptions commandLineOptions)
{
bool generateReportEnabled = commandLineOptions.IsOptionSet(GenerateReportOption);
bool reportFileName = commandLineOptions.TryGetOptionArgumentList(ReportFilenameOption, out string[]? _);
return (generateReportEnabled || reportFileName) && !(generateReportEnabled && reportFileName)
? ValidationResult.InvalidTask("Both `--generatereport` and `--reportfilename` need to be provided simultaneously.")
: ValidationResult.ValidTask;
}
Tenga en cuenta que el método proporciona el servicio , que se usa para capturar la información del argumento analizada por la propia plataforma.
Las extensiones
es una extensión dentro del proceso que permite la ejecución del código antes y después de la sesión de prueba.
Para registrar un personalizado, use la API siguiente:
var builder = await TestApplication.CreateBuilderAsync(args);
// ...
builder.TestHost.AddTestSessionLifetimeHandle(
static serviceProvider => new CustomTestSessionLifeTimeHandler());
La fábrica utiliza IServiceProvider para obtener acceso al conjunto de servicios ofrecidos por la plataforma de pruebas.
Importante
La secuencia de registro es significativa, ya que las API se llaman en el orden en que se registraron.
La interfaz incluye los métodos siguientes:
public interface ITestSessionLifetimeHandler : ITestHostExtension
{
Task OnTestSessionStartingAsync(
SessionUid sessionUid,
CancellationToken cancellationToken);
Task OnTestSessionFinishingAsync(
SessionUid sessionUid,
CancellationToken cancellationToken);
}
public readonly struct SessionUid(string value)
{
public string Value { get; } = value;
}
public interface ITestHostExtension : IExtension
{
}
es un tipo de , que actúa como base para todas las extensiones del host de prueba. Al igual que todos los demás puntos de extensión, también hereda de IExtension. Por lo tanto, al igual que cualquier otra extensión, puede optar por habilitarla o deshabilitarla mediante la API .
Tenga en cuenta los detalles siguientes para esta API:
: este método se invoca antes del inicio de la sesión de prueba y recibe el objeto , que proporciona un identificador opaco para la sesión de prueba actual.
: este método se invoca después de la finalización de la sesión de prueba, lo que garantiza que el marco de pruebas ha terminado de ejecutar todas las pruebas y ha notificado todos los datos pertinentes a la plataforma. Normalmente, en este método, la extensión emplea para transmitir recursos o datos personalizados al bus de plataforma compartida. Este método también puede indicar a cualquier extensión personalizada fuera de proceso que la sesión de prueba ha concluido.
Por último, ambas API toman un valor que se espera que la extensión respete.
Si la extensión requiere una inicialización intensiva y necesita usar el patrón async/await, puede hacer referencia a . Si necesita compartir el estado entre puntos de extensión, consulte la sección .
Las extensiones
es una extensión dentro del proceso que permite la ejecución del código antes de todo; es como tener acceso a la primera línea del hipotético main del host de prueba.
Para registrar un personalizado, use la API siguiente:
var builder = await TestApplication.CreateBuilderAsync(args);
// ...
builder.TestHost.AddTestApplicationLifecycleCallbacks(
static serviceProvider
=> new CustomTestApplicationLifecycleCallbacks());
La fábrica utiliza IServiceProvider para obtener acceso al conjunto de servicios ofrecidos por la plataforma de pruebas.
Importante
La secuencia de registro es significativa, ya que las API se llaman en el orden en que se registraron.
La interfaz incluye los métodos siguientes:
public interface ITestApplicationLifecycleCallbacks : ITestHostExtension
{
Task BeforeRunAsync(CancellationToken cancellationToken);
Task AfterRunAsync(
int exitCode,
CancellationToken cancellation);
}
public interface ITestHostExtension : IExtension
{
}
es un tipo de , que actúa como base para todas las extensiones del host de prueba. Al igual que todos los demás puntos de extensión, también hereda de IExtension. Por lo tanto, al igual que cualquier otra extensión, puede optar por habilitarla o deshabilitarla mediante la API .
: este método actúa como punto de contacto inicial para el host de prueba y es la primera oportunidad para que una extensión dentro del proceso ejecute una característica. Normalmente se usa para establecer una conexión con las extensiones fuera de proceso correspondientes, si una característica está diseñada para funcionar en ambos entornos.
Por ejemplo, la característica de volcado de memoria de bloqueo integrada se compone tanto de extensiones dentro del proceso como fuera del proceso, y este método se usa para intercambiar información con el componente fuera del proceso de la extensión.
: este método es la llamada final antes de salir de y proporciona . Debe usarse únicamente para tareas de limpieza y notificar a cualquier extensión fuera del proceso correspondiente que el host de prueba está a punto de finalizar.
Por último, ambas API toman un valor que se espera que la extensión respete.
Las extensiones
es una extensión dentro del proceso capaz de suscribirse y recibir información que se inserta en IMessageBus por medio del marco de prueba y sus extensiones.
Este punto de extensión es fundamental, ya que permite a los desarrolladores recopilar y procesar toda la información generada durante una sesión de prueba.
Para registrar un personalizado, use la API siguiente:
var builder = await TestApplication.CreateBuilderAsync(args);
// ...
builder.TestHost.AddDataConsumer(
static serviceProvider => new CustomDataConsumer());
La fábrica utiliza IServiceProvider para obtener acceso al conjunto de servicios ofrecidos por la plataforma de pruebas.
Importante
La secuencia de registro es significativa, ya que las API se llaman en el orden en que se registraron.
La interfaz incluye los métodos siguientes:
public interface IDataConsumer : ITestHostExtension
{
Type[] DataTypesConsumed { get; }
Task ConsumeAsync(
IDataProducer dataProducer,
IData value,
CancellationToken cancellationToken);
}
public interface IData
{
string DisplayName { get; }
string? Description { get; }
}
es un tipo de , que actúa como base para todas las extensiones del host de prueba. Al igual que todos los demás puntos de extensión, también hereda de IExtension. Por lo tanto, al igual que cualquier otra extensión, puede optar por habilitarla o deshabilitarla mediante la API .
: esta propiedad devuelve una lista de que esta extensión tiene planificado consumir. Se corresponde con . En particular, puede suscribirse a varios tipos que se originan en instancias diferentes sin problemas.
: este método se activa cada vez que se insertan en el datos de un tipo al que el consumidor actual está suscrito. Recibe para proporcionar detalles sobre el productor de la carga de datos, así como sobre la carga de datos en sí misma. Como puede ver, es una interfaz genérica de marcador de posición que contiene datos informativos generales. La capacidad de insertar diferentes tipos de implica que el consumidor debe cambiar en el propio tipo para convertirlo al tipo correcto y acceder a la información específica.
Una implementación de ejemplo de un consumidor que quiere elaborar el generado por un marco de pruebas podría ser:
internal class CustomDataConsumer : IDataConsumer, IOutputDeviceDataProducer
{
public Type[] DataTypesConsumed => new[] { typeof(TestNodeUpdateMessage) };
...
public Task ConsumeAsync(
IDataProducer dataProducer,
IData value,
CancellationToken cancellationToken)
{
var testNodeUpdateMessage = (TestNodeUpdateMessage)value;
switch (testNodeUpdateMessage.TestNode.Properties.Single<TestNodeStateProperty>())
{
case InProgressTestNodeStateProperty _:
{
...
break;
}
case PassedTestNodeStateProperty _:
{
...
break;
}
case FailedTestNodeStateProperty failedTestNodeStateProperty:
{
...
break;
}
case SkippedTestNodeStateProperty _:
{
...
break;
}
...
}
return Task.CompletedTask;
}
...
}
Por último, la API toma un que se espera que la extensión respete.
Importante
Es fundamental procesar la carga directamente dentro del método . IMessageBus puede administrar el procesamiento sincrónico y asincrónico, coordinando la ejecución con el marco de pruebas. Aunque el proceso de consumo es completamente asincrónico y no bloquea IMessageBus.Push en el momento de escribirlo, se trata de un detalle de implementación que puede cambiar en el futuro debido a requisitos futuros. Sin embargo, la plataforma garantiza que este método se llame siempre una vez, lo que elimina la necesidad de una sincronización compleja, además de administrar la escalabilidad de los consumidores.
Advertencia
Cuando se usa junto con ITestHostProcessLifetimeHandler dentro de un punto de extensión compuesto, es fundamental ignorar los datos recibidos después de la ejecución de ITestSessionLifetimeHandler.OnTestSessionFinishingAsync. es la oportunidad final de procesar datos acumulados y transmitir nueva información a IMessageBus, por lo que los datos consumidos más allá de este punto no serán utilizables por la extensión.
Si la extensión requiere una inicialización intensiva y necesita usar el patrón async/await, puede hacer referencia a . Si necesita compartir el estado entre puntos de extensión, consulte la sección .
Las extensiones
es una extensión fuera del proceso que permite establecer variables de entorno personalizadas para el host de prueba. El uso de este punto de extensión garantiza que la plataforma de prueba iniciará un nuevo host con las variables de entorno adecuadas, como se detalla en la sección arquitectura .
Para registrar un personalizado, use la API siguiente:
var builder = await TestApplication.CreateBuilderAsync(args);
// ...
builder.TestHostControllers.AddEnvironmentVariableProvider(
static serviceProvider => new CustomEnvironmentVariableForTestHost());
La fábrica utiliza IServiceProvider para obtener acceso al conjunto de servicios ofrecidos por la plataforma de pruebas.
Importante
La secuencia de registro es significativa, ya que las API se llaman en el orden en que se registraron.
La interfaz incluye los métodos y tipos siguientes:
public interface ITestHostEnvironmentVariableProvider : ITestHostControllersExtension, IExtension
{
Task UpdateAsync(IEnvironmentVariables environmentVariables);
Task<ValidationResult> ValidateTestHostEnvironmentVariablesAsync(
IReadOnlyEnvironmentVariables environmentVariables);
}
public interface IEnvironmentVariables : IReadOnlyEnvironmentVariables
{
void SetVariable(EnvironmentVariable environmentVariable);
void RemoveVariable(string variable);
}
public interface IReadOnlyEnvironmentVariables
{
bool TryGetVariable(
string variable,
[NotNullWhen(true)] out OwnedEnvironmentVariable? environmentVariable);
}
public sealed class OwnedEnvironmentVariable : EnvironmentVariable
{
public IExtension Owner { get; }
public OwnedEnvironmentVariable(
IExtension owner,
string variable,
string? value,
bool isSecret,
bool isLocked);
}
public class EnvironmentVariable
{
public string Variable { get; }
public string? Value { get; }
public bool IsSecret { get; }
public bool IsLocked { get; }
}
es un tipo de , que actúa como base para todas las extensiones del controlador del host de prueba. Al igual que todos los demás puntos de extensión, también hereda de IExtension. Por lo tanto, al igual que cualquier otra extensión, puede optar por habilitarla o deshabilitarla mediante la API .
Tenga en cuenta los detalles de esta API:
: esta API de actualización proporciona una instancia del objeto , desde el que puede llamar a los métodos o . Al usar , debe pasar un objeto de tipo , que requiere las siguientes especificaciones:
- : el nombre de la variable de entorno.
- : valor de la variable de entorno.
- : indica si la variable de entorno contiene información confidencial que no se debe registrar ni obtener acceso a ella a través de .
- : determina si otras extensiones pueden modificar este valor.
: este método se invoca después de llamar a todos los métodos de las instancias registradas . Permite comprobar la configuración correcta de las variables de entorno. Toma un objeto que implementa , que proporciona el método para capturar información de variable de entorno específica con el tipo de objeto . Después de la validación, se devuelve que contiene todos los motivos de error.
Nota:
De forma predeterminada, la plataforma de prueba implementa y registra . Este proveedor carga todas las variables de entorno actuales. Como primer proveedor registrado, se ejecuta primero, concediendo acceso a las variables de entorno predeterminadas para todas las demás extensiones de usuario .
Si la extensión requiere una inicialización intensiva y necesita usar el patrón async/await, puede hacer referencia a . Si necesita compartir el estado entre puntos de extensión, consulte la sección .
Las extensiones
es una extensión fuera del proceso que permite observar el proceso de host de prueba desde un punto de vista externo. Esto garantiza que la extensión no se vea afectada por posibles bloqueos o errores inducidos por el código que se está probando. El uso de este punto de extensión solicitará a la plataforma de prueba que inicie un nuevo host, como se detalla en la sección arquitectura.
Para registrar un personalizado, use la API siguiente:
var builder = await TestApplication.CreateBuilderAsync(args);
// ...
builder.TestHostControllers.AddProcessLifetimeHandler(
static serviceProvider => new CustomMonitorTestHost());
La fábrica utiliza IServiceProvider para obtener acceso al conjunto de servicios ofrecidos por la plataforma de pruebas.
Importante
La secuencia de registro es significativa, ya que las API se llaman en el orden en que se registraron.
La interfaz incluye los métodos siguientes:
public interface ITestHostProcessLifetimeHandler : ITestHostControllersExtension
{
Task BeforeTestHostProcessStartAsync(CancellationToken cancellationToken);
Task OnTestHostProcessStartedAsync(
ITestHostProcessInformation testHostProcessInformation,
CancellationToken cancellation);
Task OnTestHostProcessExitedAsync(
ITestHostProcessInformation testHostProcessInformation,
CancellationToken cancellation);
}
public interface ITestHostProcessInformation
{
int PID { get; }
int ExitCode { get; }
bool HasExitedGracefully { get; }
}
es un tipo de , que actúa como base para todas las extensiones del controlador del host de prueba. Al igual que todos los demás puntos de extensión, también hereda de IExtension. Por lo tanto, al igual que cualquier otra extensión, puede optar por habilitarla o deshabilitarla mediante la API .
Tenga en cuenta los detalles siguientes para esta API:
: este método se invoca antes de que la plataforma de prueba inicie los hosts de prueba.
: este método se invoca inmediatamente después de que se inicie el host de prueba. Este método ofrece un objeto que implementa la interfaz , que proporciona detalles clave sobre el resultado del proceso del host de prueba.
Importante
La invocación de este método no detiene la ejecución del host de prueba. Si necesita ponerla en pausa, debe registrar una extensión dentro del proceso como y sincronizarla con la extensión fuera de proceso.
: este método se invoca cuando se completa la ejecución del conjunto de pruebas. Este método proporciona un objeto que se ajusta a la interfaz de , la cual transmite detalles cruciales sobre el resultado del proceso del host de prueba.
La interfaz de proporciona los siguientes detalles:
- : ID de proceso del host de prueba.
- : código de salida del proceso. Este valor solo está disponible en el método . Si intenta acceder a él dentro del método , se producirá una excepción.
- : Un valor booleano que indica si el host de prueba ha fallado. Si es verdadero, significa que el host de prueba no salió de forma adecuada.
Orden de ejecución de extensiones
La plataforma de pruebas consta de un marco de pruebas y de cualquier número de extensiones que pueden funcionar dentro del proceso o fuera del proceso. Este documento describe la secuencia de llamadas a todos los puntos de extensibilidad potenciales para proporcionar claridad sobre cuándo se prevé que se invoque una característica:
- ITestHostEnvironmentVariableProvider.UpdateAsync: fuera del proceso
- ITestHostEnvironmentVariableProvider.ValidateTestHostEnvironmentVariablesAsync: fuera del proceso
- ITestHostProcessLifetimeHandler.BeforeTestHostProcessStartAsync: fuera del proceso
- Inicio del proceso de host de prueba
- ITestHostProcessLifetimeHandler.OnTestHostProcessStartedAsync: fuera del proceso, este evento puede entrelazar las acciones de las extensiones dentro del proceso, en función de las condiciones de carrera.
- ITestApplicationLifecycleCallbacks.BeforeRunAsync: En proceso
- ITestSessionLifetimeHandler.OnTestSessionStartingAsync: dentro del proceso
- ITestFramework.CreateTestSessionAsync: en proceso
- ITestFramework.ExecuteRequestAsync: dentro del proceso; se puede llamar a este método una o varias veces. En este momento, el marco de pruebas transmitirá información a IMessageBus que IDataConsumer puede usar.
- ITestFramework.CloseTestSessionAsync: en proceso
- ITestSessionLifetimeHandler.OnTestSessionFinishingAsync: dentro del proceso
- ITestApplicationLifecycleCallbacks.AfterRunAsync: dentro del proceso
- La limpieza dentro del proceso implica invocar a dispose e IAsyncCleanableExtension en todos los puntos de extensión.
- ITestHostProcessLifetimeHandler.OnTestHostProcessExitedAsync: fuera del proceso
- La limpieza de procesos externos implica llamar a dispose e IAsyncCleanableExtension en todos los puntos de extensión.
Ayudantes de extensiones
La plataforma de pruebas proporciona un conjunto de clases e interfaces auxiliares para simplificar la implementación de extensiones. Estos asistentes están diseñados para simplificar el proceso de desarrollo y asegurarse de que la extensión cumpla los estándares de la plataforma.
Inicialización asincrónica y limpieza de extensiones
La creación del marco de pruebas y las extensiones a través de factorías se adhiere al mecanismo estándar de creación de objetos .NET, que usa constructores sincrónicos. Si una extensión requiere una inicialización intensiva (por ejemplo, el acceso al sistema de archivos o la red), no puede emplear el patrón async/await en el constructor porque los constructores devuelven void, no .
Por lo tanto, la plataforma de pruebas proporciona un método para inicializar una extensión mediante el patrón async/await a través de una interfaz sencilla. En aras de la simetría, también ofrece una interfaz asincrónica para la limpieza que las extensiones pueden implementar sin complicaciones.
public interface IAsyncInitializableExtension
{
Task InitializeAsync();
}
public interface IAsyncCleanableExtension
{
Task CleanupAsync();
}
: Se garantiza que este método se invoque después de la factoría de creación.
: este método garantiza que se invoque al menos una vez durante la finalización de la sesión de prueba, antes del valor predeterminado o .
Importante
De forma similar al método estándar , se puede invocar varias veces. Si se llama más de una vez al método de un objeto, el objeto debe omitir todas las llamadas después de la primera. El objeto no debe producir una excepción si se llama varias veces a su método .
Nota:
De forma predeterminada, la plataforma de pruebas llamará a si está disponible o si se implementa. Es importante tener en cuenta que la plataforma de pruebas no llamará a ambos métodos dispose, sino que dará prioridad al método async si se implementa.
CompositeExtensionFactoryT
Como se describe en la sección extensiones, la plataforma de pruebas le permite implementar interfaces para incorporar extensiones personalizadas tanto dentro como fuera del proceso.
Cada interfaz aborda una característica determinada y, según .NET diseño, se implementa esta interfaz en un objeto específico. Puede registrar la propia extensión mediante la API de registro específica desde el objeto o desde , tal y como se detalla en las secciones correspondientes.
Sin embargo, si debe compartir el estado entre dos extensiones, el hecho de que pueda implementar y registrar diferentes objetos implementando distintas interfaces, hace que compartir sea una tarea complicada. Sin ninguna ayuda, necesitaría una manera de pasar una extensión a la otra para compartir información, lo que complica el diseño.
Por lo tanto, la plataforma de pruebas proporciona un método sofisticado para implementar varios puntos de extensión con el mismo tipo, lo que hace que compartir datos sea una tarea sencilla. Lo único que debe hacer es usar , que luego se puede registrar con la misma API que utilizaría para una sola implementación de interfaz.
Por ejemplo, considere un tipo que implementa tanto como . Este es un escenario común porque a menudo se desea recopilar información del marco de pruebas y, a continuación, cuando la sesión de pruebas concluya, se enviará el artefacto mediante dentro de .
Lo que debe hacer es implementar las interfaces con normalidad:
internal class CustomExtension : ITestSessionLifetimeHandler, IDataConsumer, ...
{
...
}
Una vez que haya creado el para su tipo, puede registrarlo con las APIs y , que ofrecen una sobrecarga para :
var builder = await TestApplication.CreateBuilderAsync(args);
// ...
var factory = new CompositeExtensionFactory<CustomExtension>(serviceProvider => new CustomExtension());
builder.TestHost.AddTestSessionLifetimeHandle(factory);
builder.TestHost.AddDataConsumer(factory);
El constructor de fábrica emplea IServiceProvider para obtener acceso a los servicios proporcionados por la plataforma de pruebas.
La plataforma de pruebas será responsable de administrar el ciclo de vida de la extensión compuesta.
Es importante tener en cuenta que, debido a la compatibilidad de la plataforma de pruebas con las extensiones dentro del proceso y fuera del proceso, no se puede combinar ningún punto de extensión arbitrariamente. La creación y el uso de extensiones dependen del tipo de host, lo que significa que solo se pueden agrupar extensiones dentro del proceso (TestHost) y fuera del proceso (TestHostController).
Las siguientes combinaciones están disponibles:
- Para , puede combinar y .
- Para , puede combinar y .