Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Cet article décrit les points d’extensibilité pour Microsoft.Testing.Platform au-delà de l’infrastructure de test proprement dite. Pour la création d’une infrastructure de test, consultez Générer une infrastructure de test.
Pour obtenir le résumé complet du point d’extension et les concepts in-process/out-of-process, consultez Créer des extensions personnalisées.
Points d’extensibilité
La plateforme de test fournit des points d’extensibilité supplémentaires qui vous permettent de personnaliser le comportement de la plateforme et du framework de test. Ces points d’extensibilité sont optionnels et peuvent être utilisés pour améliorer l’expérience de test.
Les extensions ICommandLineOptionsProvider
Remarque
Lors de l’extension de cette API, l’extension personnalisée existera à la fois dans et hors du processus de l’hôte de test.
Comme discuté dans la section architecture, la première étape consiste à créer le ITestApplicationBuilder pour enregistrer le framework de test et les extensions avec lui.
var builder = await TestApplication.CreateBuilderAsync(args);
La méthode CreateBuilderAsync accepte un tableau de chaînes (string[]) nommé args. Ces arguments peuvent être utilisés pour passer des options de ligne de commande à tous les composants de la plateforme de test (y compris les composants intégrés, les frameworks de test et les extensions), permettant de personnaliser leur comportement.
Typiquement, les arguments passés sont ceux reçus dans la méthode standard Main(string[] args). Cependant, si l’environnement d’hébergement diffère, n’importe quelle liste d’arguments peut être fournie.
Les arguments doivent être préfixés par un double tiret --. Par exemple : --filter.
Si un composant tel qu’un framework de test ou un point d’extension souhaite offrir des options de ligne de commande personnalisées, il peut le faire en implémentant l’interface ICommandLineOptionsProvider. Cette implémentation peut ensuite être enregistrée avec le ITestApplicationBuilder via la fabrique d'enregistrement de la propriété CommandLine, comme montré :
builder.CommandLine.AddProvider(
static () => new CustomCommandLineOptions());
Dans l’exemple fourni, CustomCommandLineOptions est une implémentation de l’interface ICommandLineOptionsProvider. Cette interface comprend les membres et types de données suivants :
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);
}
Comme observé, le ICommandLineOptionsProvider étend l’interface IExtension. Donc, comme toute autre extension, vous pouvez choisir de l’activer ou de la désactiver en utilisant l’API IExtension.IsEnabledAsync.
L’ordre d’exécution du ICommandLineOptionsProvider est :
Examinons les APIs et leur signification :
ICommandLineOptionsProvider.GetCommandLineOptions() : Cette méthode est utilisée pour récupérer toutes les options offertes par le composant. Chaque CommandLineOption nécessite que les propriétés suivantes soient spécifiées :
string name : Il s’agit du nom de l’option, présenté sans tiret. Par exemple, filter serait utilisé comme --filter par les utilisateurs.
string description : Il s’agit d’une description de l’option. Elle sera affichée lorsque les utilisateurs passent --help comme argument au générateur d’application.
ArgumentArity arity : L’arité d’une option est le nombre de valeurs qui peuvent être passées si cette option ou commande est spécifiée. Les arités disponibles actuellement sont :
-
Zero: Représente une arité d’argument de zéro. -
ZeroOrOne: Indique une arité des arguments de zéro ou un. -
ZeroOrMore: Représente une arité d’argument de zéro ou plus. -
OneOrMore: Représente une arité d’argument d'un ou plusieurs. -
ExactlyOne: Représente une arité d’argument exactement égale à un.
Pour des exemples, consultez la table d’arité de System.CommandLine.
bool isHidden : Cette propriété signifie que l’option est disponible pour utilisation mais ne sera pas affichée dans la description lorsque --help est invoquée.
ICommandLineOptionsProvider.ValidateOptionArgumentsAsync : Cette méthode est utilisée pour valider l’argument fourni par l’utilisateur.
Par exemple, si vous avez un paramètre nommé --dop qui représente le degré de parallélisme pour notre framework de test personnalisé, un utilisateur pourrait entrer --dop 0. Dans ce scénario, la valeur 0 serait invalide car on s’attend à un degré de parallélisme de 1 ou plus. En utilisant ValidateOptionArgumentsAsync, vous pouvez effectuer une validation préalable et renvoyer un message d’erreur si nécessaire.
Une implémentation possible pour l’exemple ci-dessus pourrait être :
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;
}
ICommandLineOptionsProvider.ValidateCommandLineOptionsAsync : Cette méthode est appelée en dernier et permet de faire une vérification de cohérence globale.
Par exemple, supposons que notre framework de test ait la capacité de générer un rapport de résultat de test et de l’enregistrer dans un fichier. Cette fonctionnalité est accessible en utilisant l’option --generatereport, et le nom de fichier est spécifié avec --reportfilename myfile.rep. Dans ce scénario, si un utilisateur fournit uniquement l’option --generatereport sans spécifier un nom de fichier, la validation devrait échouer car le rapport ne peut pas être généré sans un nom de fichier.
Une implémentation possible pour l’exemple ci-dessus pourrait être :
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;
}
Veuillez noter que la méthode ValidateCommandLineOptionsAsync fournit le service ICommandLineOptions, qui est utilisé pour récupérer les informations d’argument analysées par la plateforme elle-même.
Les extensions ITestSessionLifetimeHandler
Le ITestSessionLifeTimeHandler est une extension in-process qui permet l’exécution de code avant et après la session de test.
Pour enregistrer un ITestSessionLifeTimeHandler personnalisé, utilisez l’API suivante :
var builder = await TestApplication.CreateBuilderAsync(args);
// ...
builder.TestHost.AddTestSessionLifetimeHandle(
static serviceProvider => new CustomTestSessionLifeTimeHandler());
L’usine utilise le IServiceProvider pour accéder à la suite de services offerts par la plateforme de test.
Importante
La séquence d’enregistrement est importante, car les APIs sont appelées dans l’ordre où elles ont été enregistrées.
L’interface ITestSessionLifeTimeHandler inclut les méthodes suivantes :
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
{
}
Le ITestSessionLifetimeHandler est un type de ITestHostExtension, qui sert de base pour toutes les extensions hôte de test. Comme tous les autres points d’extension, il hérite également de IExtension. Donc, comme toute autre extension, vous pouvez choisir de l’activer ou de la désactiver en utilisant l’API IExtension.IsEnabledAsync.
Considérez les détails suivants pour cette API :
OnTestSessionStartingAsync : Cette méthode est invoquée avant le début de la session de test et reçoit l’objet SessionUid, qui fournit un identifiant opaque pour la session de test en cours.
OnTestSessionFinishingAsync : Cette méthode est invoquée après la fin de la session de test, s’assurant que le framework de test a terminé l’exécution de tous les tests et a rapporté toutes les données pertinentes à la plateforme. En règle générale, dans cette méthode, l’extension utilise le IMessageBus pour transmettre des ressources ou des données personnalisées au bus de plateforme partagé. Cette méthode peut également signaler à toute extension personnalisée out-of-process que la session de test est terminée.
Enfin, les deux APIs prennent un CancellationToken que l’extension est censée respecter.
Si votre extension nécessite une initialisation intensive et que vous avez besoin d’utiliser le modèle async/await, vous pouvez vous référer au Async extension initialization and cleanup. Si vous avez besoin de partager l’état entre les points d’extension, vous pouvez vous référer à la section CompositeExtensionFactory<T>.
Les extensions ITestApplicationLifecycleCallbacks
Le ITestApplicationLifecycleCallbacks est une extension in-process qui permet l’exécution de code avant tout, c’est comme avoir accès à la première ligne du supposé main de l’hôte de test.
Pour enregistrer un ITestApplicationLifecycleCallbacks personnalisé, utilisez l’API suivante :
var builder = await TestApplication.CreateBuilderAsync(args);
// ...
builder.TestHost.AddTestApplicationLifecycleCallbacks(
static serviceProvider
=> new CustomTestApplicationLifecycleCallbacks());
L’usine utilise le IServiceProvider pour accéder à la suite de services offerts par la plateforme de test.
Importante
La séquence d’enregistrement est importante, car les APIs sont appelées dans l’ordre où elles ont été enregistrées.
L’interface ITestApplicationLifecycleCallbacks inclut les méthodes suivantes :
public interface ITestApplicationLifecycleCallbacks : ITestHostExtension
{
Task BeforeRunAsync(CancellationToken cancellationToken);
Task AfterRunAsync(
int exitCode,
CancellationToken cancellation);
}
public interface ITestHostExtension : IExtension
{
}
Le ITestApplicationLifecycleCallbacks est un type de ITestHostExtension, qui sert de base pour toutes les extensions hôte de test. Comme tous les autres points d’extension, il hérite également de IExtension. Donc, comme toute autre extension, vous pouvez choisir de l’activer ou de la désactiver en utilisant l’API IExtension.IsEnabledAsync.
BeforeRunAsync : Cette méthode sert de point de contact initial pour l’hôte de test et est la première occasion pour une extension in-process d’exécuter une fonctionnalité. C’est généralement utilisé pour établir une connexion avec toute extension out-of-process correspondante si une fonctionnalité est conçue pour fonctionner à travers les deux environnements.
Par exemple, la fonctionnalité intégrée de vidage en cas de blocage est composée d’extensions inter-processus et hors-processus, et cette méthode est utilisée pour échanger des informations avec le composant hors-processus de l’extension.
AfterRunAsync : Cette méthode est l’appel final avant de quitter le int ITestApplication.RunAsync() et elle fournit le exit code. Elle doit être utilisée uniquement pour les tâches de nettoyage et pour notifier toute extension out-of-process correspondante que l’hôte de test est sur le point de se terminer.
Enfin, les deux APIs prennent un CancellationToken que l’extension est censée respecter.
Les extensions IDataConsumer
Le IDataConsumer est une extension en processus capable de s’abonner et de recevoir des informations IData qui sont poussées au IMessageBus par le cadre de test et ses extensions.
Ce point d’extensibilité est crucial car il permet aux développeurs de recueillir et de traiter toutes les informations générées lors d’une session de test.
Pour enregistrer un IDataConsumer personnalisé, utilisez l’API suivante :
var builder = await TestApplication.CreateBuilderAsync(args);
// ...
builder.TestHost.AddDataConsumer(
static serviceProvider => new CustomDataConsumer());
L’usine utilise le IServiceProvider pour accéder à la suite de services offerts par la plateforme de test.
Importante
La séquence d’enregistrement est importante, car les APIs sont appelées dans l’ordre où elles ont été enregistrées.
L’interface IDataConsumer inclut les méthodes suivantes :
public interface IDataConsumer : ITestHostExtension
{
Type[] DataTypesConsumed { get; }
Task ConsumeAsync(
IDataProducer dataProducer,
IData value,
CancellationToken cancellationToken);
}
public interface IData
{
string DisplayName { get; }
string? Description { get; }
}
Le IDataConsumer est un type de ITestHostExtension, qui sert de base pour toutes les extensions hôte de test. Comme tous les autres points d’extension, il hérite également de IExtension. Donc, comme toute autre extension, vous pouvez choisir de l’activer ou de la désactiver en utilisant l’API IExtension.IsEnabledAsync.
DataTypesConsumed : Cette propriété renvoie une liste de Type que cette extension prévoit de consommer. Elle correspond à IDataProducer.DataTypesProduced. Notamment, un IDataConsumer peut s’abonner à plusieurs types provenant de différentes instances de IDataProducer sans aucun problème.
ConsumeAsync : Cette méthode est déclenchée chaque fois que des données d’un type auquel le consommateur actuel est abonné sont poussées sur le IMessageBus. Elle reçoit le IDataProducer pour fournir des détails sur le producteur de la charge utile de données, ainsi que la charge utile IData elle-même. Comme vous pouvez le voir, IData est une interface de remplacement générique qui contient des données informatives générales. La possibilité de pousser différents types de IData implique que le consommateur doit switcher sur le type lui-même pour le convertir au type correct et accéder aux informations spécifiques.
Une implémentation d’exemple d’un consommateur qui veut élaborer le TestNodeUpdateMessage produit par un framework de test pourrait être :
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;
}
...
}
Enfin, l’API prend un CancellationToken que l’extension est censée respecter.
Importante
Il est crucial de traiter la charge utile directement dans la méthode ConsumeAsync. Le IMessageBus peut gérer à la fois le traitement synchrone et asynchrone, en coordonnant l’exécution avec le framework de test. Bien que le processus de consommation soit entièrement asynchrone et ne bloque pas le IMessageBus.Push au moment de la rédaction, il s’agit d’un détail d’implémentation qui peut changer à l’avenir en raison d’exigences futures. Cependant, la plateforme garantit que cette méthode est toujours appelée une fois, éliminant le besoin de synchronisation complexe, ainsi que la gestion de l’évolutivité des consommateurs.
Avertissement
Lorsque vous utilisez IDataConsumer en conjonction avec ITestHostProcessLifetimeHandler au sein d’un point d’extension composite, il est crucial d’ignorer toute donnée reçue après l’exécution de ITestSessionLifetimeHandler.OnTestSessionFinishingAsync. Le OnTestSessionFinishingAsync est la dernière opportunité de traiter les données accumulées et de transmettre de nouvelles informations au IMessageBus, donc, toute donnée consommée au-delà de ce point ne sera pas utilisable par l’extension.
Si votre extension nécessite une initialisation intensive et que vous avez besoin d’utiliser le modèle async/await, vous pouvez vous référer au Async extension initialization and cleanup. Si vous avez besoin de partager l’état entre les points d’extension, vous pouvez vous référer à la section CompositeExtensionFactory<T>.
Les extensions ITestHostEnvironmentVariableProvider
Le ITestHostEnvironmentVariableProvider est une extension out-of-process qui vous permet d’établir des variables d’environnement personnalisées pour l’hôte de test. Utiliser ce point d’extension garantit que la plateforme de test initiera un nouvel hôte avec les variables d’environnement appropriées, comme détaillé dans la section architecture.
Pour enregistrer un ITestHostEnvironmentVariableProvider personnalisé, utilisez l’API suivante :
var builder = await TestApplication.CreateBuilderAsync(args);
// ...
builder.TestHostControllers.AddEnvironmentVariableProvider(
static serviceProvider => new CustomEnvironmentVariableForTestHost());
L’usine utilise le IServiceProvider pour accéder à la suite de services offerts par la plateforme de test.
Importante
La séquence d’enregistrement est importante, car les APIs sont appelées dans l’ordre où elles ont été enregistrées.
L’interface ITestHostEnvironmentVariableProvider inclut les méthodes et types suivants :
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; }
}
Le ITestHostEnvironmentVariableProvider est un type de ITestHostControllersExtension, qui sert de base pour toutes les extensions contrôleur d’hôte de test. Comme tous les autres points d’extension, il hérite également de IExtension. Donc, comme toute autre extension, vous pouvez choisir de l’activer ou de la désactiver en utilisant l’API IExtension.IsEnabledAsync.
Considérez les détails pour cette API :
UpdateAsync : Cette API de mise à jour fournit une instance de l’objet IEnvironmentVariables, à partir de laquelle vous pouvez appeler les méthodes SetVariable ou RemoveVariable. Lorsque vous utilisez SetVariable, vous devez passer un objet de type EnvironmentVariable, qui nécessite les spécifications suivantes :
-
Variable: nom de la variable d’environnement. -
Value: valeur de la variable d’environnement. -
IsSecret: Cela indique si la variable d’environnement contient des informations sensibles qui ne devraient pas être journalisées ou accessibles via leTryGetVariable. -
IsLocked: Cela détermine si d’autres extensionsITestHostEnvironmentVariableProviderpeuvent modifier cette valeur.
ValidateTestHostEnvironmentVariablesAsync : Cette méthode est invoquée après que toutes les méthodes UpdateAsync des instances enregistrées de ITestHostEnvironmentVariableProvider ont été appelées. Elle vous permet de vérifier la configuration correcte des variables d’environnement. Elle prend un objet qui implémente IReadOnlyEnvironmentVariables, qui fournit la méthode TryGetVariable pour récupérer des informations spécifiques sur les variables d’environnement avec le type d’objet OwnedEnvironmentVariable. Après validation, vous renvoyez un ValidationResult contenant toutes les raisons d’échec.
Remarque
La plateforme de test, par défaut, implémente et enregistre le SystemEnvironmentVariableProvider. Ce fournisseur charge toutes les variables d’environnement actuelles. En tant que premier fournisseur enregistré, il s’exécute en premier, donnant accès aux variables d’environnement par défaut pour toutes les autres extensions ITestHostEnvironmentVariableProvider utilisateur.
Si votre extension nécessite une initialisation intensive et que vous avez besoin d’utiliser le modèle async/await, vous pouvez vous référer au Async extension initialization and cleanup. Si vous avez besoin de partager l’état entre les points d’extension, vous pouvez vous référer à la section CompositeExtensionFactory<T>.
Les extensions ITestHostProcessLifetimeHandler
Le ITestHostProcessLifetimeHandler est une extension out-of-process qui vous permet d’observer le processus de l’hôte de test depuis un point de vue externe. Cela garantit que votre extension reste non affectée par les plantages ou blocages potentiels qui pourraient être induits par le code sous test. Utiliser ce point d’extension incitera la plateforme de test à initier un nouvel hôte, comme détaillé dans la section architecture.
Pour enregistrer un ITestHostProcessLifetimeHandler personnalisé, utilisez l’API suivante :
var builder = await TestApplication.CreateBuilderAsync(args);
// ...
builder.TestHostControllers.AddProcessLifetimeHandler(
static serviceProvider => new CustomMonitorTestHost());
L’usine utilise le IServiceProvider pour accéder à la suite de services offerts par la plateforme de test.
Importante
La séquence d’enregistrement est importante, car les APIs sont appelées dans l’ordre où elles ont été enregistrées.
L’interface ITestHostProcessLifetimeHandler inclut les méthodes suivantes :
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; }
}
Le ITestHostProcessLifetimeHandler est un type de ITestHostControllersExtension, qui sert de base pour toutes les extensions contrôleur d’hôte de test. Comme tous les autres points d’extension, il hérite également de IExtension. Donc, comme toute autre extension, vous pouvez choisir de l’activer ou de la désactiver en utilisant l’API IExtension.IsEnabledAsync.
Considérez les détails suivants pour cette API :
BeforeTestHostProcessStartAsync : Cette méthode est invoquée avant que la plateforme de test n’initie les hôtes de test.
OnTestHostProcessStartedAsync : Cette méthode est invoquée immédiatement après le démarrage de l’hôte de test. Cette méthode offre un objet qui implémente l’interface ITestHostProcessInformation, qui fournit des détails clés sur le résultat du processus de l’hôte de test.
Importante
L’invocation de cette méthode n’arrête pas l’exécution de l’hôte de test. Si vous avez besoin de le mettre en pause, vous devriez enregistrer une extension in-process telle que ITestApplicationLifecycleCallbacks et la synchroniser avec l’extension out-of-process.
OnTestHostProcessExitedAsync : Cette méthode est invoquée lorsque l’exécution de la suite de tests est terminée. Cette méthode fournit un objet qui adhère à l’interface ITestHostProcessInformation, qui transmet des détails cruciaux sur le résultat du processus de l’hôte de test.
L’interface ITestHostProcessInformation fournit les détails suivants :
-
PID: L’ID du processus de l’hôte de test. -
ExitCode: Le code de sortie du processus. Cette valeur est uniquement disponible dans la méthodeOnTestHostProcessExitedAsync. Essayer d’y accéder dans la méthodeOnTestHostProcessStartedAsyncentraînera une exception. -
HasExitedGracefully: Une valeur booléenne indiquant si l’hôte de test a planté. Si c'est le cas, cela signifie que l'hôte de test n'a pas quitté correctement.
Ordre d’exécution des extensions
La plateforme de test se compose d’un framework de test et d’un nombre quelconque d’extensions qui peuvent fonctionner in-process ou out-of-process. Ce document décrit la séquence des appels à tous les points d'extensibilité potentiels afin de clarifier à quel moment une fonctionnalité est censée être invoquée.
- ITestHostEnvironmentVariableProvider.UpdateAsync : Hors processus
- ITestHostEnvironmentVariableProvider.ValidateTestHostEnvironmentVariablesAsync : hors processus
- ITestHostProcessLifetimeHandler.BeforeTestHostProcessStartAsync : hors processus
- Démarrage du processus de l’hôte de test
- ITestHostProcessLifetimeHandler.OnTestHostProcessStartedAsync : Hors du processus, cet événement peut entrelacer les actions des extensions de dans le processus, selon les conditions de concurrence.
- ITestApplicationLifecycleCallbacks.BeforeRunAsync : En cours
- ITestSessionLifetimeHandler.OnTestSessionStartingAsync : En cours
- ITestFramework.CreateTestSessionAsync : En cours
- ITestFramework.ExecuteRequestAsync : In-process, cette méthode peut être appelée une ou plusieurs fois. À ce stade, le framework de test transmettra des informations au IMessageBus qui peuvent être utilisées par le IDataConsumer.
- ITestFramework.CloseTestSessionAsync : En cours
- ITestSessionLifetimeHandler.OnTestSessionFinishingAsync : En cours
- ITestApplicationLifecycleCallbacks.AfterRunAsync : En cours
- Le nettoyage en cours implique d’appeler dispose et IAsyncCleanableExtension sur tous les points d’extension.
- ITestHostProcessLifetimeHandler.OnTestHostProcessExitedAsync : Hors processus
- Le nettoyage hors-procédé implique d’appeler dispose et IAsyncCleanableExtension sur tous les points d’extension.
Assistants d’extensions
La plateforme de test fournit un ensemble de classes et d’interfaces d’assistance pour simplifier l’implémentation des extensions. Ces assistants sont conçus pour rationaliser le processus de développement et garantir que l’extension adhère aux normes de la plateforme.
Initialisation asynchrone et nettoyage des extensions
La création de l’infrastructure de test et des extensions par le biais de fabriques respecte le mécanisme standard de création d’objets .NET, qui utilise des constructeurs synchrones. Si une extension nécessite une initialisation intensive (comme accéder au système de fichiers ou au réseau), elle ne peut pas utiliser le modèle async/await dans le constructeur car les constructeurs renvoient void, pas Task.
Par conséquent, la plateforme de test fournit un moyen d’initialiser une extension en utilisant le modèle async/await via une interface simple. Pour la symétrie, il offre également une interface asynchrone pour le nettoyage que les extensions peuvent implémenter facilement.
public interface IAsyncInitializableExtension
{
Task InitializeAsync();
}
public interface IAsyncCleanableExtension
{
Task CleanupAsync();
}
IAsyncInitializableExtension.InitializeAsync : Cette méthode est assurée d’être invoquée après l’usine de création.
IAsyncCleanableExtension.CleanupAsync : Cette méthode est assurée d’être invoquée au moins une fois lors de la terminaison de la session de test, avant le DisposeAsync ou le Dispose par défaut.
Importante
Semblable à la méthode standard Dispose, CleanupAsync peut être invoquée plusieurs fois. Si la méthode CleanupAsync d’un objet est appelée plus d’une fois, l’objet doit ignorer tous les appels après le premier. L’objet ne doit pas lever d’exception si sa méthode CleanupAsync est appelée plusieurs fois.
Remarque
Par défaut, la plateforme de test appellera DisposeAsync si elle est disponible, ou Dispose si elle est implémentée. Il est important de noter que la plateforme de test n’appellera pas les deux méthodes de dispose mais privilégiera la méthode asynchrone si elle est implémentée.
CompositeExtensionFactory<T>
Comme décrit dans la section extensions, la plateforme de test vous permet d’implémenter des interfaces pour incorporer des extensions personnalisées à la fois in-process et out-of-process.
Chaque interface traite d’une fonctionnalité particulière et, en fonction de .NET conception, vous implémentez cette interface dans un objet spécifique. Vous pouvez enregistrer l’extension elle-même en utilisant l’API d’enregistrement spécifique AddXXX du TestHost ou l’objet TestHostController du ITestApplicationBuilder comme détaillé dans les sections correspondantes.
Cependant, si vous avez besoin de partager l’état entre deux extensions, le fait que vous puissiez implémenter et enregistrer différents objets implémentant différentes interfaces rend le partage une tâche difficile. Sans aucune assistance, vous auriez besoin d’un moyen de passer une extension à l’autre pour partager des informations, ce qui complique la conception.
Ainsi, la plateforme de test fournit une méthode sophistiquée pour implémenter plusieurs points d’extension en utilisant le même type, rendant le partage de données une tâche simple. Tout ce que vous avez à faire est d’utiliser le CompositeExtensionFactory<T>, qui peut ensuite être enregistré en utilisant la même API que vous le feriez pour une implémentation d’interface unique.
Par exemple, considérez un type qui implémente à la fois ITestSessionLifetimeHandler et IDataConsumer. C’est un scénario courant car vous voulez souvent recueillir des informations du framework de test et ensuite, lorsque la session de test se termine, vous expédierez votre artefact en utilisant le IMessageBus au sein du ITestSessionLifetimeHandler.OnTestSessionFinishingAsync.
Ce que vous devriez faire est d’implémenter normalement les interfaces :
internal class CustomExtension : ITestSessionLifetimeHandler, IDataConsumer, ...
{
...
}
Une fois que vous avez créé le CompositeExtensionFactory<CustomExtension> pour votre type, vous pouvez l’enregistrer avec les deux APIs IDataConsumer et ITestSessionLifetimeHandler, qui offrent une surcharge pour le CompositeExtensionFactory<T> :
var builder = await TestApplication.CreateBuilderAsync(args);
// ...
var factory = new CompositeExtensionFactory<CustomExtension>(serviceProvider => new CustomExtension());
builder.TestHost.AddTestSessionLifetimeHandle(factory);
builder.TestHost.AddDataConsumer(factory);
Le constructeur d’usine utilise le IServiceProvider pour accéder aux services fournis par la plateforme de test.
La plateforme de test sera responsable de gérer le cycle de vie de l’extension composite.
Il est important de noter qu’en raison du support par la plateforme de test des extensions à la fois in-process et out-of-process, vous ne pouvez pas combiner n’importe quel point d’extension arbitrairement. La création et l’utilisation des extensions dépendent du type d’hôte, ce qui signifie que vous ne pouvez regrouper que les extensions in-process (TestHost) et out-of-process (TestHostController) ensemble.
Les combinaisons suivantes sont possibles :
- Pour
ITestApplicationBuilder.TestHost, vous pouvez combinerIDataConsumeretITestSessionLifetimeHandler. - Pour
ITestApplicationBuilder.TestHostControllers, vous pouvez combinerITestHostEnvironmentVariableProvideretITestHostProcessLifetimeHandler.