Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Платформа тестирования предлагает ценные службы как для платформы тестирования, так и для точек расширения. Эти службы удовлетворяют общим потребностям, таким как доступ к конфигурации, парсинг и получение аргументов командной строки, получение фабрики логирования и доступ к системе логирования, среди прочего.
IServiceProvider реализует шаблон указателя службы для платформы тестирования.
IServiceProvider является производным непосредственно от библиотеки базовых классов.
namespace System
{
public interface IServiceProvider
{
object? GetService(Type serviceType);
}
}
Платформа тестирования предлагает удобные методы расширения для доступа к хорошо известным объектам службы. Все эти методы размещаются в статическом классе в пространстве имен Microsoft.Testing.Platform.Services.
public static class ServiceProviderExtensions
{
public static TService GetRequiredService<TService>(
this IServiceProvider provider)
public static TService? GetService<TService>(
this IServiceProvider provider)
public static IMessageBus GetMessageBus(
this IServiceProvider serviceProvider)
public static IConfiguration GetConfiguration(
this IServiceProvider serviceProvider)
public static ICommandLineOptions GetCommandLineOptions(
this IServiceProvider serviceProvider)
public static ILoggerFactory GetLoggerFactory(
this IServiceProvider serviceProvider)
public static IOutputDevice GetOutputDevice(
this IServiceProvider serviceProvider)
// ... and more
}
Большинство фабрик регистрации, предоставляемых точками расширения, предоставляют доступ к
ITestApplicationBuilder RegisterTestFramework(
Func<IServiceProvider, ITestFrameworkCapabilities> capabilitiesFactory,
Func<ITestFrameworkCapabilities, IServiceProvider, ITestFramework> adapterFactory);
В приведенном выше коде capabilitiesFactory и adapterFactory предоставляют IServiceProvider в качестве параметра.
Служба IConfiguration
Интерфейс IConfiguration можно получить с помощью IServiceProvider, который предоставляет доступ к параметрам конфигурации для платформы тестирования и любых точек расширения. По умолчанию эти конфигурации загружаются из:
- Переменные среды
- JSON-файл с именем
[assemblyName].testingplatformconfig.jsonрасположен рядом с сборкой точки входа.
Порядок приоритета сохраняется, что означает, что если конфигурация найдена в переменных среды, json-файл не будет обработан.
Интерфейс является простой парой "ключ-значение" строк:
public interface IConfiguration
{
string? this[string key] { get; }
}
JSON-файл конфигурации
JSON-файл следует иерархической структуре. Чтобы получать доступ к дочерним свойствам, необходимо использовать разделитель :. Например, рассмотрим конфигурацию для потенциальной платформы тестирования, например:
{
"CustomTestingFramework": {
"DisableParallelism": true
}
}
Фрагмент кода будет выглядеть примерно так:
IServiceProvider serviceProvider = null; // Get the service provider...
var configuration = serviceProvider.GetConfiguration();
if (bool.TryParse(configuration["CustomTestingFramework:DisableParallelism"], out var value) && value is true)
{
// ...
}
В случае массива, например:
{
"CustomTestingFramework": {
"Engine": [
"ThreadPool",
"CustomThread"
]
}
}
Синтаксис для доступа к первому элементу («ThreadPool»):
IServiceProvider serviceProvider = null; // Get the service provider...
var configuration = serviceProvider.GetConfiguration();
var fistElement = configuration["CustomTestingFramework:Engine:0"];
Переменные среды
Разделитель : не работает с иерархическими ключами переменной среды на всех платформах.
__, двойной символ подчеркивания:
- Поддерживается всеми платформами. Например, разделитель
:не поддерживается Bash, но__поддерживается. - Автоматически заменяется на
:
Например, переменная среды может быть задана следующим образом (этот пример применим для Windows):
setx CustomTestingFramework__DisableParallelism=True
При создании ITestApplicationBuilderможно не использовать источник конфигурации переменной среды:
var options = new TestApplicationOptions();
options.Configuration.ConfigurationSources.RegisterEnvironmentVariablesConfigurationSource = false;
var builder = await TestApplication.CreateBuilderAsync(args, options);
Служба ICommandLineOptions
Служба ICommandLineOptions используется для получения сведений о параметрах командной строки, проанализированных платформой. Доступные API:
public interface ICommandLineOptions
{
bool IsOptionSet(string optionName);
bool TryGetOptionArgumentList(
string optionName,
out string[]? arguments);
}
ICommandLineOptions можно получить с помощью определенных API, таких как ICommandLineOptionsProvider, или получить экземпляр из IServiceProvider с помощью метода расширения serviceProvider.GetCommandLineOptions().
ICommandLineOptions.IsOptionSet(string optionName). Этот метод позволяет проверить, указан ли определенный параметр. При указании optionNameопустите префикс --. Например, если пользователь вводит --myOption, необходимо просто передать myOption.
ICommandLineOptions.TryGetOptionArgumentList(string optionName, out string[]? arguments). Этот метод позволяет проверить, задан ли определенный параметр, и, если да, получите соответствующее значение или значения (если arity имеет несколько значений). Как и в предыдущем случае, optionName следует предоставлять без префикса --.
Служба ILoggerFactory
Платформа тестирования поставляется с интегрированной системой ведения журнала, которая создает файл журнала. Параметры ведения журнала можно просмотреть, выполнив команду --help.
Доступные варианты:
--diagnostic Enable the diagnostic logging. The default log level is 'Trace'. The file will be written in the output directory with the name log_[MMddHHssfff].diag
--diagnostic-synchronous-write Force the built-in file logger to write the log synchronously. Useful for scenario where you don't want to lose any log (i.e. in case of crash). Note that this is slowing down the test execution.
--diagnostic-output-directory Output directory of the diagnostic logging, if not specified the file will be generated inside the default 'TestResults' directory.
--diagnostic-file-prefix Prefix for the log file name that will replace '[log]_.'
--diagnostic-verbosity Define the level of the verbosity for the --diagnostic. The available values are 'Trace', 'Debug', 'Information', 'Warning', 'Error', and 'Critical'
С точки зрения программирования, для записи сведений необходимо получить ILoggerFactory из IServiceProvider.
API ILoggerFactory выглядит следующим образом:
public interface ILoggerFactory
{
ILogger CreateLogger(string categoryName);
}
public static class LoggerFactoryExtensions
{
public static ILogger<TCategoryName> CreateLogger<TCategoryName>(this ILoggerFactory factory);
}
Фабрика логгеров позволяет создавать объект ILogger с использованием API CreateLogger. Существует также удобный API, который принимает универсальный аргумент, который будет использоваться в качестве имени категории.
public interface ILogger
{
Task LogAsync<TState>(
LogLevel logLevel,
TState state,
Exception? exception,
Func<TState, Exception?, string> formatter);
void Log<TState>(
LogLevel logLevel,
TState state,
Exception? exception,
Func<TState, Exception?, string> formatter);
bool IsEnabled(LogLevel logLevel);
}
public interface ILogger<out TCategoryName> : ILogger
{
}
public static class LoggingExtensions
{
public static Task LogCriticalAsync(this ILogger logger, string message);
public static Task LogDebugAsync(this ILogger logger, string message);
public static Task LogErrorAsync(this ILogger logger, Exception ex);
public static Task LogErrorAsync(this ILogger logger, string message, Exception ex);
public static Task LogErrorAsync(this ILogger logger, string message);
public static Task LogInformationAsync(this ILogger logger, string message);
public static Task LogTraceAsync(this ILogger logger, string message);
public static Task LogWarningAsync(this ILogger logger, string message);
public static void LogCritical(this ILogger logger, string message);
public static void LogDebug(this ILogger logger, string message);
public static void LogError(this ILogger logger, Exception ex);
public static void LogError(this ILogger logger, string message, Exception ex);
public static void LogError(this ILogger logger, string message);
public static void LogInformation(this ILogger logger, string message);
public static void LogTrace(this ILogger logger, string message);
public static void LogWarning(this ILogger logger, string message);
}
Объект ILogger, созданный ILoggerFactory, предлагает API для ведения журнала информации на различных уровнях. К таким уровням ведения журнала относятся:
public enum LogLevel
{
Trace,
Debug,
Information,
Warning,
Error,
Critical,
None,
}
Ниже приведен пример использования API ведения журнала.
...
IServiceProvider provider = null; // Get the service provider...
var factory = provider.GetLoggerFactory();
var logger = factory.CreateLogger<TestingFramework>();
// ...
if (logger.IsEnabled(LogLevel.Information))
{
await logger.LogInformationAsync(
$"Executing request of type '{context.Request}'");
}
// ...
Помните, что для предотвращения ненужных выделений необходимо проверить, включен ли уровень с помощью API ILogger.IsEnabled(LogLevel).
Служба IMessageBus
Служба шины сообщений является центральным механизмом, который упрощает exchange между платформой тестирования и его расширениями.
Шина сообщений платформы тестирования использует шаблон издатель-подписчик .
Структура общей шины является следующей:
Как показано на схеме, которая включает расширения и тестовую платформу, есть два возможных действия: отправка информации в шину или использование информации из шины.
IMessageBus удовлетворил выполнение действия на шине, и API:
public interface IMessageBus
{
Task PublishAsync(
IDataProducer dataProducer,
IData data);
}
public interface IDataProducer : IExtension
{
Type[] DataTypesProduced { get; }
}
public interface IData
{
string DisplayName { get; }
string? Description { get; }
}
Рассмотрим следующие сведения о параметрах:
IDataProducer:IDataProducerвзаимодействует с шиной сообщений, сообщая, какуюTypeинформацию она может предоставлять, и устанавливает право собственности через наследование от базового интерфейса IExtension. Это означает, что нельзя неизбирательно отправлять данные в шину сообщений; Необходимо заранее объявить тип данных. При отправке непредвиденных данных будет активировано исключение.IData: Этот интерфейс служит заполнителем, где необходимо предоставить только описательные сведения, такие как имя и описание. Интерфейс не показывает много о характере данных, который является преднамеренным. Это означает, что платформа тестирования и расширения могут отправлять любые типы данных в шину, и эти данные могут использоваться любым зарегистрированным расширением или самой платформой тестирования.
Этот подход способствует развитию процесса обмена информацией, предотвращая разрушающие изменения, когда расширение не знакомо с новыми данными. Это позволяет различным версиям расширений и тестовой платформе работать в гармонии, основываясь на их взаимном понимании.
Противоположный конец шины называется потребителем, который подписан на определенный тип данных и, таким образом, может их потреблять.
Важный
Всегда используйте ожидать вызов PublishAsync. Если вы этого не сделаете, IData может не обрабатываться правильно платформой тестирования и расширениями, что может привести к незаметным ошибкам. Это только после того, как вы вернулись из ожидание, что вы можете быть уверены, что IData был помещен в очередь для обработки в шине сообщений. Убедитесь, что, независимо от точки расширения, над которой вы работаете, вы дождались выполнения всех вызовов PublishAsync перед выходом из расширения. Например, если вы реализуете testing framework, то не следует вызывать Complete на запросы , пока вы не дождались всех вызовов PublishAsync для этого конкретного запроса.
Служба IOutputDevice
Платформа тестирования инкапсулирует идею выходного устройства, что позволяет тестовому фреймворку и расширениям представлять информацию, передавая любые данные в текущую используемую систему отображения.
Наиболее традиционным примером выходного устройства является вывод консоли.
Заметка
Хотя платформа тестирования разработана для поддержки пользовательских выходных устройств, в настоящее время эта точка расширения недоступна.
Чтобы передать данные на выходное устройство, необходимо получить IOutputDevice из IServiceProvider.
API состоит из следующих элементов:
public interface IOutputDevice
{
Task DisplayAsync(
IOutputDeviceDataProducer producer,
IOutputDeviceData data);
}
public interface IOutputDeviceDataProducer : IExtension
{
}
public interface IOutputDeviceData
{
}
IOutputDeviceDataProducer расширяет IExtension и предоставляет сведения о отправителе устройству вывода .
IOutputDeviceData служит интерфейсом заполнителя. Концепция IOutputDevice заключается в том, чтобы разместить более сложную информацию, чем просто цветной текст. Например, это может быть сложный объект, который можно представить графически.
Платформа тестирования по умолчанию предлагает традиционную цветную текстовую модель для объекта IOutputDeviceData:
public class TextOutputDeviceData : IOutputDeviceData
{
public TextOutputDeviceData(string text)
public string Text { get; }
}
public sealed class FormattedTextOutputDeviceData : TextOutputDeviceData
{
public FormattedTextOutputDeviceData(string text)
public IColor? ForegroundColor { get; init; }
public IColor? BackgroundColor { get; init; }
}
public sealed class SystemConsoleColor : IColor
{
public ConsoleColor ConsoleColor { get; init; }
}
Ниже приведен пример использования цветного текста с активным выходным устройством:
IServiceProvider provider = null; // Get the service provider...
var outputDevice = provider.GetOutputDevice();
await outputDevice.DisplayAsync(
this,
new FormattedTextOutputDeviceData($"TestingFramework version '{Version}' running tests with parallelism of {_dopValue}")
{
ForegroundColor = new SystemConsoleColor
{
ConsoleColor = ConsoleColor.Green
}
});
Помимо стандартного использования цветного текста, основное преимущество IOutputDevice и IOutputDeviceData заключается в том, что устройство с выходом является полностью независимым и неизвестным для пользователя. Это позволяет разрабатывать сложные пользовательские интерфейсы. Например, вполне возможно реализовать веб-приложение в режиме реального времени, отображающее ход выполнения тестов.
Служба IPlatformInformation
Предоставляет сведения о платформе, например имени, версии, хэш-коде фиксации и дате сборки.