MSTest 4.4 permet d’exécuter les projets de test avec le même modèle de déploiement que celui que l’application pourrait utiliser en production, grâce à la génération du code source des tests et à l’activation de Native AOT et de la réduction. L’objectif n’est pas de remplacer l’exécution managée habituelle des tests, mais d’ajouter un parcours natif qui révèle les problèmes liés à la compilation anticipée et à la suppression du code inutilisé avant la mise en production de l’application.
Selon Amaury Levé, Principal Software Engineer, l’utilisation de MSTest.Sdk/4.4.0 avec le ciblage de net10.0 et la définition de PublishAot=true active la génération du code source MSTest et le parcours vers un fichier exécutable natif. MSTest.Sdk utilise par défaut la plateforme Microsoft Testing Platform, ou MTP. Les projets qui utilisent encore VSTest doivent consulter les consignes de migration vers MTP, car les paramètres de ligne de commande, l’intégration à la CI et certaines entrées .runsettings prises en charge diffèrent.
Qu’est-ce qui change concrètement ?
Après la configuration du projet, les tests doivent être publiés pour le même système d’exploitation et la même architecture que ceux ciblés par l’application. La source fournit un exemple utilisant l’identifiant linux-x64, qui peut être remplacé par des valeurs telles que win-x64 ou osx-arm64. Après la publication, le fichier exécutable généré est lancé directement, ou avec l’extension .exe sous Windows.
Ce parcours réduit la dépendance à l’inspection réflexive complète de l’assembly, comme l’appel à Assembly.GetTypes(), et utilise des attributs et des délégués générés pour créer et invoquer les tests pris en charge. Toutefois, la génération de code source ne signifie pas l’absence de Reflection : le mode ReflectionFree par défaut conserve certains parcours réflexifs de secours. Lors de l’analyse des problèmes de compatibilité, MSTestSourceGenMode=Rooting peut être utilisé pour conserver les membres de test détectés tout en maintenant l’exécution réflexive.
Un parcours CI limité avant l’élargissement
La recommandation pratique consiste à conserver l’exécution rapide des tests managés pour le retour quotidien, puis à sélectionner un projet de test directement lié au parcours de déploiement et à ajouter une expérimentation Native AOT dans la CI. Les deux parcours doivent être comparés selon trois aspects précis :
- détecter exactement le même nombre de tests ;
- obtenir les mêmes résultats pour les tests ;
- consigner séparément la durée de publication et d’exécution natives de la durée d’exécution des tests.
Il est préférable de commencer l’expérimentation dans une tâche planifiée ou lors de la phase de validation de la version, puis de la déplacer vers chaque demande de fusion uniquement si le signal qu’elle fournit justifie le coût supplémentaire de publication et d’exécution. Il convient également de choisir un projet qui teste des parcours sensibles au déploiement, tels que la sérialisation, l’injection de dépendances, la liaison de configuration, les extensions reposant sur Reflection ou une bibliothèque dont les équipes doivent démontrer la compatibilité avec Native AOT. En revanche, un projet qui ne contient que des tests de calcul simples ne fournira pas beaucoup d’éléments sur l’état réel de préparation de l’application.
Des limitations à transformer en portes d’acceptation
Une partie des tests peut réussir et le processus se terminer correctement alors que certaines classes ne sont pas enregistrées. Cela se produit, par exemple, lorsque la classe de test hérite de l’attribut [TestClass] au lieu de le déclarer directement, ou lorsque la classe est inaccessible, locale au fichier, statique, publique ouverte ou abstraite. La source indique que le diagnostic MSTEST0069 aide à détecter l’un de ces cas. La concordance du nombre de tests doit donc être une condition de mise en production, et non une remarque pouvant être ignorée.
Les autres limitations comprennent les méthodes de test publiques ou utilisant des paramètres ref, out ou in, ainsi que l’absence de prise en charge de certains modèles de parties statiques via [AssemblyFixtureProvider]. Certaines intégrations du MSTest SDK, extensions MTP et fonctions de création de rapports CI ne sont pas disponibles dans le parcours Native AOT, tandis que la prise en charge de TRX et de Code Coverage reste disponible selon l’article. Les avertissements de l’analyseur et les diagnostics de compilation doivent donc être traités comme des portes de transition, et non comme des avertissements à désactiver.
Pourquoi cette approche est-elle importante ?
Les tests managés et le parcours Native AOT répondent à deux questions différentes : le premier accélère le cycle de développement, tandis que le second vérifie que les tests eux-mêmes peuvent fonctionner dans le modèle de déploiement qui sera utilisé par l’application. Cela n’équivaut pas à un test exhaustif de la version finale de production : la configuration, le système d’exploitation, l’architecture, les services externes et le conditionnement peuvent différer. Cette approche supprime toutefois une variable importante : la différence de modèle de réduction et de compilation anticipée entre les tests et l’application.
L’amélioration des performances n’est ni garantie ni ne doit constituer la justification principale. Le temps de découverte et de démarrage peut diminuer grâce à la génération du code source, mais la durée d’exécution, le démarrage du processus, la publication et la Reflection restante peuvent dominer la durée totale. La lecture éditoriale est ici que la principale valeur de l’expérimentation réside dans le renforcement de la correspondance entre les tests et le déploiement, même si le gain de vitesse reste limité. L’approche reste réversible : si le coût du parcours dépasse la confiance qu’il apporte, il est possible d’en réduire la fréquence, de changer de projet ou d’arrêter l’expérimentation sans désactiver l’ensemble des tests managés.