Layanan Microsoft.Testing.Platform

Platform pengujian menawarkan layanan berharga untuk kerangka kerja pengujian dan titik ekstensi. Layanan ini memenuhi kebutuhan umum seperti mengakses konfigurasi, mengurai dan mengambil argumen baris perintah, mendapatkan fasilitas pencatatan, dan mengakses sistem logging, antara lain. IServiceProvider menerapkan pola pencari layanan untuk platform pengujian.

IServiceProvider berasal langsung dari pustaka kelas dasar.

namespace System
{
    public interface IServiceProvider
    {
        object? GetService(Type serviceType);
    }
}

Platform pengujian menawarkan metode ekstensi yang berguna untuk mengakses objek layanan yang terkenal. Semua metode ini ditempatkan dalam kelas statis dalam namespace 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
}

Sebagian besar pabrik pendaftaran yang diekspos oleh titik ekstensi memberikan akses ke IServiceProvider: Misalnya, ketika mendaftarkan kerangka kerja pengujian, IServiceProvider diteruskan sebagai parameter ke metode pabrik.

ITestApplicationBuilder RegisterTestFramework(
    Func<IServiceProvider, ITestFrameworkCapabilities> capabilitiesFactory,
    Func<ITestFrameworkCapabilities, IServiceProvider, ITestFramework> adapterFactory);

Dalam kode sebelumnya, baik capabilitiesFactory dan adapterFactory menyediakan IServiceProvider sebagai parameter.

Dimulai dengan MTP 2.5, gunakan GetRequiredPlatformService<TService>() atau GetPlatformService<TService>() saat proyek Anda juga mengimpor Microsoft.Extensions.DependencyInjection. Nama-nama ini menghindari ambiguitas dengan metode ekstensi GetRequiredService dan GetService milik paket dependency injection. Metode layanan yang diperlukan melempar ketika layanan platform tidak ada; metode layanan opsional mengembalikan null.

Layanan IConfiguration

Antarmuka IConfiguration dapat diambil menggunakan IServiceProvider dan menyediakan akses ke pengaturan konfigurasi untuk kerangka kerja pengujian serta berbagai titik ekstensi. Secara default, konfigurasi ini dimuat dari:

  • Opsi baris perintah, diekspos di bawah bagian commandLineOptions: .
  • Variabel lingkungan.
  • File JSON bernama [appname].testconfig.json terletak di samping aplikasi pengujian yang dapat dieksekusi.

Opsi baris perintah lebih diutamakan daripada variabel lingkungan, yang lebih diutamakan daripada nilai dari [appname].testconfig.json. MTP memuat setiap sumber dan memilih sumber pertama yang memasok setiap kunci. Untuk nilai commandLineOptions:, MTP memilih satu sumber untuk opsi penuh agar argumen yang diindeks tidak digabungkan dari beberapa sumber. Untuk detail tentang penemuan dan prioritas file konfigurasi, lihat Pengaturan konfigurasi MTP.

Antarmukanya adalah pasangan kunci-nilai string yang sederhana.

public interface IConfiguration
{
    string? this[string key] { get; }
}

Dimulai dengan MTP 2.4.0, layanan konfigurasi juga mengimplementasikan IConfigurationRoot antarmuka. Gunakan GetSection untuk memperoleh IConfigurationSection, dan gunakan GetChildren untuk membuat daftar bagian anak langsung. Bagian mengekspos Key, Value lengkap, skalar opsional Path, dan status HasValue. Penyedia harus menerapkan IHierarchicalConfigurationProvider sebelum kunci mereka muncul melalui enumerasi, tetapi Anda dapat mengambil jalur yang diketahui dari penyedia mana pun.

File konfigurasi JSON

File JSON mengikuti struktur hierarkis. Untuk mengakses properti anak, Anda perlu menggunakan pemisah :. Misalnya, pertimbangkan konfigurasi untuk kerangka kerja pengujian potensial seperti:

{
  "CustomTestingFramework": {
    "DisableParallelism": true
  }
}

Cuplikan kode akan terlihat seperti ini:

IServiceProvider serviceProvider = null; // Get the service provider...

var configuration = serviceProvider.GetConfiguration();

if (bool.TryParse(configuration["CustomTestingFramework:DisableParallelism"], out var value) && value is true)
{
    // ...
}

Dalam kasus sebuah array, seperti:

{
  "CustomTestingFramework": {
    "Engine": [
      "ThreadPool",
      "CustomThread"
    ]
  }
}

Sintaks untuk mengakses elemen pertama ("ThreadPool") adalah:

IServiceProvider serviceProvider = null; // Get the service provider...

var configuration = serviceProvider.GetConfiguration();

var fistElement = configuration["CustomTestingFramework:Engine:0"];

Variabel lingkungan

Pemisah : tidak berfungsi dengan kunci hierarki variabel lingkungan di semua platform. __, garis bawah ganda, adalah:

  • Didukung oleh semua platform. Misalnya, pemisah : tidak didukung oleh Bash, tetapi __.
  • Digantikan secara otomatis oleh :

Misalnya, variabel lingkungan dapat diatur sebagai berikut (Contoh ini berlaku untuk Windows):

setx CustomTestingFramework__DisableParallelism=True

Anda dapat memilih untuk tidak menggunakan sumber konfigurasi variabel lingkungan saat membuat ITestApplicationBuilder:

var options = new TestApplicationOptions();

options.Configuration.ConfigurationSources.RegisterEnvironmentVariablesConfigurationSource = false;

var builder = await TestApplication.CreateBuilderAsync(args, options);

Layanan ICommandLineOptions

Layanan ICommandLineOptions digunakan untuk mengambil detail mengenai opsi baris perintah yang telah diurai platform. API yang tersedia meliputi:

public interface ICommandLineOptions
{
    bool IsOptionSet(string optionName);

    bool TryGetOptionArgumentList(
        string optionName, 
        out string[]? arguments);
}

ICommandLineOptions dapat diperoleh melalui API tertentu, contoh ICommandLineOptionsProvider, atau Anda dapat mengambil instans tersebut dari IServiceProvider dengan menggunakan metode ekstensi serviceProvider.GetCommandLineOptions().

ICommandLineOptions.IsOptionSet(string optionName): Metode ini memungkinkan Anda memverifikasi apakah opsi tertentu telah ditentukan. Saat menentukan optionName, hilangkan awalan --. Misalnya, jika pengguna memasukkan --myOption, Anda cukup meneruskan myOption.

ICommandLineOptions.TryGetOptionArgumentList(string optionName, out string[]? arguments): Metode ini memungkinkan Anda untuk memeriksa apakah opsi tertentu telah diatur dan, jika demikian, ambil nilai atau nilai yang sesuai (jika aritasnya lebih dari satu). Mirip dengan kasus sebelumnya, optionName harus disediakan tanpa awalan --.

Layanan IArtifactNamingService

Dimulai dengan MTP 2.4.0, IArtifactNamingService memberikan ekstensi templat nama file lintas platform yang sama dengan yang digunakan ekstensi laporan MTP. Ambil dengan serviceProvider.GetArtifactNamingService(), lalu panggil ResolveFileName dengan templat.

Layanan ini memperluas {pname}, , {pid}{asm}, {tfm}, {arch}, dan {time}. Ini mempertahankan segmen direktori dan menyesuaikan nama file terakhir sesuai dengan sistem operasi yang digunakan saat ini. Placeholder yang tidak dikenal tetap tidak diubah. Untuk deskripsi placeholder, lihat Nama file laporan.

Layanan ILoggerFactory

Platform pengujian dilengkapi dengan sistem pengelogan terintegrasi yang menghasilkan file log. Anda dapat melihat opsi pengelogan dengan menjalankan perintah --help. Opsi yang dapat Anda pilih meliputi:

--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'

Dari sudut pandang pemrograman, untuk mencatat informasi, Anda perlu mendapatkan ILoggerFactory dari IServiceProvider. API ILoggerFactory adalah sebagai berikut:

public interface ILoggerFactory
{
    ILogger CreateLogger(string categoryName);
}

public static class LoggerFactoryExtensions
{
    public static ILogger<TCategoryName> CreateLogger<TCategoryName>(this ILoggerFactory factory);
}

Pabrik pencatat memungkinkan Anda membuat objek ILogger menggunakan API CreateLogger. Ada juga API nyaman yang menerima argumen generik, yang akan digunakan sebagai nama kategori.

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);
}

Objek ILogger, yang dibuat oleh ILoggerFactory, menawarkan API untuk informasi pengelogan di berbagai tingkatan. Tingkatan pencatatan ini termasuk:

public enum LogLevel
{
    Trace,
    Debug,
    Information,
    Warning,
    Error,
    Critical,
    None,
}

Berikut adalah contoh bagaimana Anda dapat menggunakan API pengelogan:

...
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}'");
}

// ...

Perlu diingat bahwa untuk mencegah alokasi yang tidak perlu, Anda harus memeriksa apakah tingkat diaktifkan menggunakan API ILogger.IsEnabled(LogLevel).

Layanan IDiagnosticLoggingInformation

Dimulai dengan pratinjau MTP 2.5, panggil serviceProvider.GetDiagnosticLoggingInformation() untuk mengambil informasi eksperimental tentang pencatat file diagnostik bawaan. Metode mengembalikan null ketika pembuatan log diagnostik tidak diaktifkan.

Layanan IDiagnosticLoggingInformation menyediakan:

  • LogFile, berkas yang saat ini menampung entri diagnostik.
  • LogLevel, tingkat minimum yang ditulis ke file.
  • SynchronousWrite, yang menunjukkan apakah pencatat file menulis entri secara sinkron.

Layanan ini sudah aktif. Selama konstruksi aplikasi pengujian, MTP dapat merelokasi log ke direktori hasil yang efektif. Pertahankan layanan dan baca LogFile saat Anda memerlukan path, alih-alih menyimpan cache FileInfo pertama. Jika pemulihan log meninggalkan file parsial di lokasi asli, LogFile mengidentifikasi file pengganti yang menerima entri baru.

Penting

API ini menggunakan TPEXP ID diagnostik dan dapat berubah atau dihapus dalam rilis mendatang.

Layanan IMessageBus

Layanan bus pesan adalah mekanisme pusat yang memfasilitasi pertukaran informasi antara kerangka kerja pengujian dan ekstensinya.

Bus pesan platform pengujian menggunakan pola publish-subscribe .

Struktur menyeluruh bus bersama adalah sebagai berikut:

Gambar yang mewakili interaksi berbagai ekstensi dengan bus pesan.

Sebagai ilustrasi dalam diagram, yang mencakup kerangka kerja pengujian dan ekstensi, ada dua aksi potensial: mengirim informasi ke bus atau mengambil informasi dari bus.

IMessageBus memastikan tindakan pendorongan ke bus dan API-nya adalah:

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; }
}

Pertimbangkan detail berikut tentang parameter:

  • IDataProducer: IDataProducer berkomunikasi dengan bus pesan mengenai Type informasi yang dapat disediakan dan menetapkan kepemilikan melalui pewarisan dari antarmuka dasar IExtension. Ini menyiratkan bahwa Anda tidak dapat secara sembarangan mendorong data ke bus pesan; Anda harus mendeklarasikan jenis data yang dihasilkan terlebih dahulu. Jika Anda memasukkan data yang tidak terduga, pengecualian akan dipicu.

  • IData: Antarmuka ini berfungsi sebagai tempat penampung di mana Anda hanya perlu memberikan detail deskriptif seperti nama dan deskripsi. Antarmuka tidak mengungkapkan banyak tentang sifat data, yang disengaja. Ini menyiratkan bahwa kerangka kerja dan ekstensi pengujian dapat mengirim semua jenis data ke bus, dan data ini dapat digunakan oleh ekstensi yang terdaftar atau oleh kerangka kerja pengujian itu sendiri.

Pendekatan ini memfasilitasi evolusi proses pertukaran informasi, mencegah perubahan yang merusak bila ekstensi tidak mengenali data baru. Ini memungkinkan berbagai versi ekstensi dan kerangka kerja pengujian beroperasi secara harmonis, berdasarkan pemahaman bersama mereka.

Ujung bus yang berlawanan disebut sebagai consumer, yang berlangganan jenis data tertentu dan dengan demikian dapat mengonsumsinya.

Penting

Selalu gunakan menunggu panggilan ke PublishAsync. Jika tidak, IData mungkin tidak akan diproses dengan benar oleh platform pengujian dan ekstensi, yang dapat menyebabkan bug yang sulit dideteksi. Hanya setelah Anda kembali dari menunggu di, Anda dapat yakin bahwa IData telah diantrekan untuk diproses di message bus. Terlepas dari titik ekstensi yang sedang Anda kerjakan, pastikan Anda telah menunggu semua panggilan PublishAsync sebelum keluar dari titik ekstensi. Misalnya, jika Anda menerapkan testing framework, Anda tidak boleh memanggil Complete pada permintaan hingga Anda menunggu semua panggilan PublishAsync untuk permintaan tertentu tersebut.

Layanan ITestCoverageCapabilities

Mulai dari MTP 2.4, dapatkan ITestCoverageCapabilities dari IServiceProvider untuk menemukan dukungan untuk pesan cakupan. Layanan ini menyediakan:

  • SupportsTestCoverageMessages, yang menunjukkan dukungan untuk kontrak pesan cakupan platform.
  • EnabledProducerUids, cuplikan UID produsen yang diaktifkan yang mendeklarasikan setidaknya salah satu dari TestCoverageMessage, TestCoverageThresholdMessage, atau TestCoverageReportMessage.

Baca daftar produsen dari panggilan balik siklus hidup sesi setelah konstruksi ekstensi, bukan dari pabrik pendaftaran atau konstruktor. Produsen yang diaktifkan mendeklarasikan dukungan; daftar tidak menjamin bahwa produsen telah menerbitkan pengukuran. Daftar kosong tidak berarti platform tidak memiliki dukungan untuk pesan cakupan.

Di MTP 2.5 atau yang lebih baru, ambil layanan dengan serviceProvider.GetRequiredPlatformService<ITestCoverageCapabilities>(). Di MTP 2.4, gunakan GetRequiredService<ITestCoverageCapabilities>() di Microsoft.Testing.Platform.Services.

Untuk contoh produsen dan konsumen yang dapat dijalankan, lihat Mempublikasikan hasil cakupan.

Layanan ITestCoverageResult

Dimulai dengan MTP 2.4, ITestCoverageResult menyediakan data cakupan platform yang berkorelasi. Ambil layanan dari IServiceProvider dan gunakan anggota berikut:

Anggota Purpose
GetOverall(sessionUid) Mengembalikan ringkasan keseluruhan sesi yang dilaporkan, atau null jika tidak ada.
Scopes Mengembalikan CoverageScopeSummary entri dengan sesi, cakupan, dan metriknya.
Thresholds Mengembalikan evaluasi ambang batas yang dilaporkan, termasuk evaluasi yang lulus dan gagal.
Reports Mengembalikan referensi laporan cakupan serta format dan ID produsennya.
HasThresholdFailure Menunjukkan apakah ada ambang batas yang dilaporkan mengalami kegagalan.

Kunci korelasi pengukuran mencakup sesi, produsen, cakupan, metrik, dan nama metrik kustom jika berlaku. Pengukuran selanjutnya dengan kunci yang sama menggantikan nilai sebelumnya; MTP tidak menjumlahkan pesan duplikat. Produsen yang berbeda tetap terpisah bahkan ketika mereka melaporkan metrik dan cakupan yang sama.

CoverageScopeSummary.Metrics mempertahankan ProducerId setiap metriknya. Pengindeks praktis, seperti summary[CoverageMetric.Line], mengembalikan hasil produsen pertama yang cocok. Untuk memilih kolektor tertentu, periksa Metrics dan cocokkan ProducerId. Gunakan GetCustom(name) untuk metrik kustom alih-alih pengindeks.

Ringkasan yang tidak ada berarti tidak ada pengukuran yang cocok yang dilaporkan. Hasil dengan HasCoverableData diatur ke false berarti pengumpul melaporkan nol unit yang dapat dicakup. Jangan ganti kedua kasus dengan hasil sukses 100 persen.

Karena bus pesan memproses data secara asinkron, jangan baca layanan segera setelah PublishAsync dan asumsikan bahwa pesan baru ada. Untuk hasil akhir eksekusi, baca setelah sesi selesai, seperti yang dilakukan contoh cakupan di ITestHostApplicationLifetime.AfterRunAsync.

Layanan IClientInfo

Untuk mengidentifikasi klien yang menjalankan aplikasi pengujian, panggil serviceProvider.GetClientInfo() saat permintaan pengujian atau sesi aktif. Dalam mode server, handshake inisialisasi menetapkan informasi ini. Layanan eksperimental IClientInfo mengekspos Id, , Versiondan Capabilities. Dimulai dengan MTP 2.4, Capabilities memberikan nilai IClientCapabilities yang merepresentasikan status stateful yang dinyatakan oleh klien.

Klien stateful mempertahankan serangkaian node pengujian yang dapat dialamati untuk sesi dan menyimpan status terakhir node yang diketahui sampai pembaruan menggantikannya. Klien stateless mengonsumsi pembaruan tanpa mempertahankan state tersebut. Perbedaan tidak menjelaskan masa pakai koneksi atau apakah server menerima beberapa permintaan.

Gunakan clientInfo.Capabilities.IsStateful untuk hasil Boolean konservatif: kemampuan yang tidak dinyatakan mengembalikan false. Untuk membedakan sebuah false yang eksplisit dari kemampuan yang tidak dinyatakan, gunakan ClientCapabilitiesExtensions.GetIsStateful() di MTP 2.4.1 atau yang lebih baru:

Result Meaning
true Klien secara eksplisit menyatakan status simpul pengujian yang dipertahankan.
false Klien secara eksplisit menyatakan perilaku stateless.
null Layanan yang disediakan platform tidak memiliki deklarasi dari klien.

Untuk implementasi kustom IClientCapabilities, GetIsStateful() mengembalikan nilai IsStateful-nya. Untuk mendeklarasikan kemampuan dari editor atau alat, lihat Mendeklarasikan statefulness klien.

Penting

IClientInfo, IClientCapabilities, GetClientInfo, dan ClientCapabilitiesExtensions bersifat eksperimental dan menggunakan TPEXP ID diagnostik. Kehadiran mereka dalam paket MTP yang stabil tidak membuat API stabil.

Layanan IOutputDevice

Platform pengujian merangkum gagasan perangkat output , memungkinkan kerangka kerja pengujian dan ekstensi untuk menyajikan informasi dengan mengirimkan segala jenis data ke sistem tampilan yang saat ini digunakan.

Contoh paling tradisional dari perangkat output adalah output konsol.

Nota

Meskipun platform pengujian direkayasa untuk mendukung perangkat output kustom, saat ini, titik ekstensi ini tidak tersedia.

Untuk mengirimkan data ke perangkat output , Anda harus mendapatkan IOutputDevice dari IServiceProvider.

API terdiri dari:

public interface IOutputDevice
{
    Task DisplayAsync(
        IOutputDeviceDataProducer producer,
        IOutputDeviceData data,
        CancellationToken cancellationToken);
}

public interface IOutputDeviceDataProducer : IExtension
{
}

public interface IOutputDeviceData
{
}

IOutputDeviceDataProducer memperluas IExtension dan memberikan informasi tentang pengirim ke perangkat output .

IOutputDeviceData berfungsi sebagai antarmuka tempat penampung. Konsep di balik IOutputDevice adalah mengakomodasi informasi yang lebih rumit daripada hanya teks berwarna. Misalnya, itu bisa menjadi objek kompleks yang dapat diwakili secara grafis.

Platform pengujian, secara default, menawarkan model teks berwarna tradisional untuk objek 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; }
}

Berikut adalah contoh bagaimana Anda dapat menggunakan teks berwarna dengan perangkat aktif output:

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
        }
    },
    CancellationToken.None);

Di luar penggunaan standar teks berwarna, keuntungan utama IOutputDevice dan IOutputDeviceData adalah bahwa perangkat output sepenuhnya independen dan tidak diketahui oleh pengguna. Ini memungkinkan pengembangan antarmuka pengguna yang kompleks. Misalnya, sepenuhnya layak untuk mengimplementasikan aplikasi web real-time yang menampilkan kemajuan pengujian.

Layanan IPlatformInformation

Layanan eksperimental IPlatformInformation menyediakan platform Name, opsional Version, opsional CommitHash, dan opsional BuildDate.